mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge pull request #325 from liyunfan1223/dev-20240711
Fix crash caused by dulicate login; Rndbots gear quality configuration
This commit is contained in:
@@ -614,11 +614,11 @@ AiPlayerbot.PremadeSpecLink.3.2.80 = -005305101-5000032500033330522135301331
|
||||
#
|
||||
|
||||
AiPlayerbot.PremadeSpecName.4.0 = as pve
|
||||
AiPlayerbot.PremadeSpecGlyph.4.0 = 45768,43379,45761,43380,43378,45767
|
||||
AiPlayerbot.PremadeSpecGlyph.4.0 = 45768,43379,45761,43380,43378,45766
|
||||
AiPlayerbot.PremadeSpecLink.4.0.60 = 005323005350100520103331051
|
||||
AiPlayerbot.PremadeSpecLink.4.0.80 = 005323005350100520103331051-005005005003-2
|
||||
AiPlayerbot.PremadeSpecName.4.1 = combat pve
|
||||
AiPlayerbot.PremadeSpecGlyph.4.1 = 45762,43379,45767,43380,43378,45766
|
||||
AiPlayerbot.PremadeSpecGlyph.4.1 = 42962,43379,45762,43380,43378,42969
|
||||
AiPlayerbot.PremadeSpecLink.4.1.60 = -0252051000035015223100501251
|
||||
AiPlayerbot.PremadeSpecLink.4.1.80 = 00532000523-0252051000035015223100501251
|
||||
AiPlayerbot.PremadeSpecName.4.2 = subtlety pve
|
||||
@@ -696,8 +696,8 @@ AiPlayerbot.PremadeSpecLink.7.1.60 = -30205033005001333031131131051
|
||||
AiPlayerbot.PremadeSpecLink.7.1.80 = 053030052-30205033005021333031131131051
|
||||
AiPlayerbot.PremadeSpecName.7.2 = resto pve
|
||||
AiPlayerbot.PremadeSpecGlyph.7.2 = 41517,43385,41527,43386,44923,45775
|
||||
AiPlayerbot.PremadeSpecLink.7.2.60 = --50005301335310501002331241
|
||||
AiPlayerbot.PremadeSpecLink.7.2.80 = -00505031-50005331335310501022331251
|
||||
AiPlayerbot.PremadeSpecLink.7.2.60 = --50005301235310501102321251
|
||||
AiPlayerbot.PremadeSpecLink.7.2.80 = -00502033-50005331335310501122331251
|
||||
|
||||
#
|
||||
#
|
||||
@@ -715,8 +715,8 @@ AiPlayerbot.PremadeSpecLink.8.0.60 = 23000503110033014032310150532
|
||||
AiPlayerbot.PremadeSpecLink.8.0.80 = 23000523310033015032310250532-03-203203001
|
||||
AiPlayerbot.PremadeSpecName.8.1 = fire pve
|
||||
AiPlayerbot.PremadeSpecGlyph.8.1 = 42739,43339,45737,43364,44920,42751
|
||||
AiPlayerbot.PremadeSpecLink.8.1.60 = -0055030012303330053120300351
|
||||
AiPlayerbot.PremadeSpecLink.8.1.80 = 23000503310003-0055030012303330053120300351
|
||||
AiPlayerbot.PremadeSpecLink.8.1.60 = -0055030011302231053120321341
|
||||
AiPlayerbot.PremadeSpecLink.8.1.80 = 23000503110003-0055030011302331053120321351
|
||||
AiPlayerbot.PremadeSpecName.8.2 = frost pve
|
||||
AiPlayerbot.PremadeSpecGlyph.8.2 = 42742,43339,50045,43364,43361,42751
|
||||
AiPlayerbot.PremadeSpecLink.8.2.60 = --3533103310203100232102231151
|
||||
@@ -891,6 +891,14 @@ AiPlayerbot.AutoPickTalents = 1
|
||||
#
|
||||
#
|
||||
|
||||
# Equips quality limitation for random bots (1 = normal, 2 = uncommon, 3 = rare, 4 = epic, 5 = legendary)
|
||||
# default: 3 (rare)
|
||||
AiPlayerbot.RandomGearQualityLimit = 3
|
||||
|
||||
# Equips gear score limitation for random bots (0 = no limit)
|
||||
# default: 0 (no limit)
|
||||
AiPlayerbot.RandomGearScoreLimit = 0
|
||||
|
||||
# Change random bot has lower gear
|
||||
AiPlayerbot.RandomGearLoweringChance = 0
|
||||
|
||||
|
||||
@@ -95,7 +95,10 @@ bool PlayerbotAIConfig::Initialize()
|
||||
autoAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoAvoidAoe", true);
|
||||
tellWhenAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.TellWhenAvoidAoe", true);
|
||||
|
||||
randomGearLoweringChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomGearLoweringChance", 0.15f);
|
||||
randomGearLoweringChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomGearLoweringChance", 0.0f);
|
||||
randomGearQualityLimit = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomGearQualityLimit", 3);
|
||||
randomGearScoreLimit = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomGearScoreLimit", 0);
|
||||
|
||||
randomBotMaxLevelChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotMaxLevelChance", 0.15f);
|
||||
randomBotRpgChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotRpgChance", 0.20f);
|
||||
|
||||
|
||||
@@ -79,6 +79,8 @@ class PlayerbotAIConfig
|
||||
std::vector<uint32> randomBotQuestIds;
|
||||
uint32 randomBotTeleportDistance;
|
||||
float randomGearLoweringChance;
|
||||
int32 randomGearQualityLimit;
|
||||
int32 randomGearScoreLimit;
|
||||
float randomBotMaxLevelChance;
|
||||
float randomBotRpgChance;
|
||||
uint32 minRandomBots, maxRandomBots;
|
||||
|
||||
@@ -149,7 +149,10 @@ void PlayerbotFactory::Prepare()
|
||||
{
|
||||
if (!itemQuality)
|
||||
{
|
||||
itemQuality = ITEM_QUALITY_RARE;
|
||||
uint32 gs = sPlayerbotAIConfig->randomGearScoreLimit == 0 ? 0 :
|
||||
PlayerbotFactory::CalcMixedGearScore(sPlayerbotAIConfig->randomGearScoreLimit, sPlayerbotAIConfig->randomGearQualityLimit);
|
||||
itemQuality = sPlayerbotAIConfig->randomGearQualityLimit;
|
||||
gearScoreLimit = gs;
|
||||
}
|
||||
|
||||
if (bot->isDead())
|
||||
@@ -3821,9 +3824,10 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot)
|
||||
score += (agility + strength + intellect + spirit + stamina + defense + dodge + parry + block +
|
||||
resilience + hit + crit + haste + expertise + attack_power + mana_regeneration + spell_power + armor_penetration +
|
||||
spell_penetration + armor + rangeDps + meleeDps) * 0.001;
|
||||
// todo: remove duplicate code
|
||||
if (cls == CLASS_HUNTER) {
|
||||
// AGILITY only
|
||||
score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 2.5 + crit * 2 + haste * 2.5 + intellect;
|
||||
score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 2 + crit * 2 + haste * 2 + intellect;
|
||||
} else if (cls == CLASS_WARLOCK ||
|
||||
cls == CLASS_MAGE ||
|
||||
(cls == CLASS_PRIEST && tab == 2) || // shadow
|
||||
@@ -3832,7 +3836,7 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot)
|
||||
) {
|
||||
// SPELL DPS
|
||||
score += intellect * 0.5 + spirit * 0.5 + spell_power + spell_penetration
|
||||
+ hit * 1.2 + crit * 0.7 + haste * 1 + rangeDps;
|
||||
+ hit * 1 + crit * 0.7 + haste * 1 + rangeDps;
|
||||
} else if ((cls == CLASS_PALADIN && tab == 0) || // holy
|
||||
(cls == CLASS_PRIEST && tab != 2) || // discipline / holy
|
||||
(cls == CLASS_SHAMAN && tab == 2) || // heal
|
||||
@@ -3840,9 +3844,9 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot)
|
||||
) {
|
||||
// HEALER
|
||||
score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1 + rangeDps;
|
||||
} else if (cls == CLASS_ROGUE) {
|
||||
} else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) {
|
||||
// AGILITY mainly (STRENGTH also)
|
||||
score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 2 + crit * 1.5 + haste * 1.5 + expertise * 2.5;
|
||||
score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5;
|
||||
} else if ((cls == CLASS_PALADIN && tab == 2) || // retribution
|
||||
(cls == CLASS_WARRIOR && tab != 2) || // arm / fury
|
||||
(cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy
|
||||
@@ -3852,20 +3856,20 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot)
|
||||
} else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement
|
||||
// STRENGTH mainly (AGILITY, INTELLECT also)
|
||||
score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + meleeDps * 5
|
||||
+ hit * 2 + crit * 1.5 + haste * 1.5 + expertise * 2;
|
||||
+ hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2;
|
||||
} else if ((cls == CLASS_WARRIOR && tab == 2) ||
|
||||
(cls == CLASS_PALADIN && tab == 1)) {
|
||||
// TANK WITH SHIELD
|
||||
score += strength * 1 + agility * 2 + attack_power * 0.2
|
||||
+ defense * 2.5 + parry * 2 + dodge * 2 + resilience * 2 + block * 2 + armor * 0.3 + stamina * 3
|
||||
+ hit * 1 + crit * 0.2 + haste * 0.5 + expertise * 3;
|
||||
+ hit * 0.5 + crit * 0.2 + haste * 0.5 + expertise * 3;
|
||||
} else if (cls == CLASS_DEATH_KNIGHT && tab == 0){
|
||||
// BLOOD DK TANK
|
||||
score += strength * 1 + agility * 2 + attack_power * 0.2
|
||||
+ defense * 3.5 + parry * 2 + dodge * 2 + resilience * 2 + armor * 0.3 + stamina * 2.5
|
||||
+ hit * 2 + crit * 0.5 + haste * 0.5 + expertise * 3.5;
|
||||
+ hit * 0.5 + crit * 0.5 + haste * 0.5 + expertise * 3.5;
|
||||
} else {
|
||||
// BEAR DRUID TANK (AND FERAL DRUID...?)
|
||||
// BEAR DRUID TANK
|
||||
score += agility * 1.5 + strength * 1 + attack_power * 0.5 + armor_penetration * 0.5 + meleeDps * 2
|
||||
+ defense * 0.25 + dodge * 0.25 + armor * 0.3 + stamina * 1.5
|
||||
+ hit * 1 + crit * 1 + haste * 0.5 + expertise * 3;
|
||||
@@ -4242,9 +4246,10 @@ float PlayerbotFactory::CalculateEnchantScore(uint32 enchant_id, Player* bot)
|
||||
float score = (agility + strength + intellect + spirit + stamina + defense + dodge + parry + block +
|
||||
resilience + hit + crit + haste + expertise + attack_power + mana_regeneration + spell_power + armor_penetration +
|
||||
spell_penetration + armor + dps) * 0.001;
|
||||
// todo: remove duplicate code
|
||||
if (cls == CLASS_HUNTER) {
|
||||
// AGILITY only
|
||||
score += agility * 2.5 + attack_power + armor_penetration * 2 + dps * 5 + hit * 2.5 + crit * 2 + haste * 2.5 + intellect;
|
||||
score += agility * 2.5 + attack_power + armor_penetration * 2 + dps * 5 + hit * 2 + crit * 2 + haste * 2.5 + intellect;
|
||||
} else if (cls == CLASS_WARLOCK ||
|
||||
cls == CLASS_MAGE ||
|
||||
(cls == CLASS_PRIEST && tab == 2) || // shadow
|
||||
@@ -4253,7 +4258,7 @@ float PlayerbotFactory::CalculateEnchantScore(uint32 enchant_id, Player* bot)
|
||||
) {
|
||||
// SPELL DPS
|
||||
score += intellect * 0.5 + spirit * 0.5 + spell_power + spell_penetration
|
||||
+ hit * 1.2 + crit * 0.7 + haste * 1;
|
||||
+ hit * 1 + crit * 0.7 + haste * 1;
|
||||
} else if ((cls == CLASS_PALADIN && tab == 0) || // holy
|
||||
(cls == CLASS_PRIEST && tab != 2) || // discipline / holy
|
||||
(cls == CLASS_SHAMAN && tab == 2) || // heal
|
||||
@@ -4261,9 +4266,9 @@ float PlayerbotFactory::CalculateEnchantScore(uint32 enchant_id, Player* bot)
|
||||
) {
|
||||
// HEALER
|
||||
score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1;
|
||||
} else if (cls == CLASS_ROGUE) {
|
||||
} else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) {
|
||||
// AGILITY mainly (STRENGTH also)
|
||||
score += agility * 2 + strength + attack_power + armor_penetration * 1 + dps * 5 + hit * 2 + crit * 1.5 + haste * 1.5 + expertise * 2.5;
|
||||
score += agility * 2 + strength + attack_power + armor_penetration * 1 + dps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5;
|
||||
} else if ((cls == CLASS_PALADIN && tab == 2) || // retribution
|
||||
(cls == CLASS_WARRIOR && tab != 2) || // arm / fury
|
||||
(cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy
|
||||
@@ -4273,20 +4278,20 @@ float PlayerbotFactory::CalculateEnchantScore(uint32 enchant_id, Player* bot)
|
||||
} else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement
|
||||
// STRENGTH mainly (AGILITY, INTELLECT also)
|
||||
score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + dps * 5
|
||||
+ hit * 2 + crit * 1.5 + haste * 1.5 + expertise * 2;
|
||||
+ hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2;
|
||||
} else if ((cls == CLASS_WARRIOR && tab == 2) ||
|
||||
(cls == CLASS_PALADIN && tab == 1)) {
|
||||
// TANK WITH SHIELD
|
||||
score += strength * 1 + agility * 2 + attack_power * 0.2
|
||||
+ defense * 2.5 + parry * 2 + dodge * 2 + resilience * 2 + block * 2 + armor * 0.3 + stamina * 3
|
||||
+ hit * 1 + crit * 0.2 + haste * 0.5 + expertise * 3;
|
||||
+ hit * 0.5 + crit * 0.2 + haste * 0.5 + expertise * 3;
|
||||
} else if (cls == CLASS_DEATH_KNIGHT && tab == 0){
|
||||
// BLOOD DK TANK
|
||||
score += strength * 1 + agility * 2 + attack_power * 0.2
|
||||
+ defense * 3.5 + parry * 2 + dodge * 2 + resilience * 2 + armor * 0.3 + stamina * 2.5
|
||||
+ hit * 2 + crit * 0.5 + haste * 0.5 + expertise * 3.5;
|
||||
+ hit * 0.5 + crit * 0.5 + haste * 0.5 + expertise * 3.5;
|
||||
} else {
|
||||
// BEAR DRUID TANK (AND FERAL DRUID...?)
|
||||
// BEAR DRUID TANK
|
||||
score += agility * 1.5 + strength * 1 + attack_power * 0.5 + armor_penetration * 0.5 + dps * 2
|
||||
+ defense * 0.25 + dodge * 0.25 + armor * 0.3 + stamina * 1.5
|
||||
+ hit * 1 + crit * 1 + haste * 0.5 + expertise * 3;
|
||||
@@ -4521,9 +4526,10 @@ float PlayerbotFactory::CalculateSpellScore(uint32 spell_id, Player* bot, uint32
|
||||
}
|
||||
}
|
||||
float score = 0;
|
||||
// todo: remove duplicate code
|
||||
if (cls == CLASS_HUNTER) {
|
||||
// AGILITY only
|
||||
score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 2.5 + crit * 2 + haste * 2.5 + intellect;
|
||||
score += agility * 2.5 + attack_power + armor_penetration * 2 + rangeDps * 5 + hit * 2 + crit * 2 + haste * 2.5 + intellect;
|
||||
} else if (cls == CLASS_WARLOCK ||
|
||||
cls == CLASS_MAGE ||
|
||||
(cls == CLASS_PRIEST && tab == 2) || // shadow
|
||||
@@ -4532,7 +4538,7 @@ float PlayerbotFactory::CalculateSpellScore(uint32 spell_id, Player* bot, uint32
|
||||
) {
|
||||
// SPELL DPS
|
||||
score += intellect * 0.5 + spirit * 0.5 + spell_power + spell_penetration
|
||||
+ hit * 1.2 + crit * 0.7 + haste * 1 + rangeDps;
|
||||
+ hit * 1 + crit * 0.7 + haste * 1 + rangeDps;
|
||||
} else if ((cls == CLASS_PALADIN && tab == 0) || // holy
|
||||
(cls == CLASS_PRIEST && tab != 2) || // discipline / holy
|
||||
(cls == CLASS_SHAMAN && tab == 2) || // heal
|
||||
@@ -4540,9 +4546,9 @@ float PlayerbotFactory::CalculateSpellScore(uint32 spell_id, Player* bot, uint32
|
||||
) {
|
||||
// HEALER
|
||||
score += intellect * 0.5 + spirit * 0.5 + spell_power + mana_regeneration * 0.5 + crit * 0.5 + haste * 1 + rangeDps;
|
||||
} else if (cls == CLASS_ROGUE) {
|
||||
} else if (cls == CLASS_ROGUE || (cls == CLASS_DRUID && tab == 2 && !PlayerbotAI::IsTank(bot))) {
|
||||
// AGILITY mainly (STRENGTH also)
|
||||
score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 2 + crit * 1.5 + haste * 1.5 + expertise * 2.5;
|
||||
score += agility * 2 + strength + attack_power + armor_penetration * 1 + meleeDps * 5 + hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2.5;
|
||||
} else if ((cls == CLASS_PALADIN && tab == 2) || // retribution
|
||||
(cls == CLASS_WARRIOR && tab != 2) || // arm / fury
|
||||
(cls == CLASS_DEATH_KNIGHT && tab != 0) // ice / unholy
|
||||
@@ -4552,20 +4558,20 @@ float PlayerbotFactory::CalculateSpellScore(uint32 spell_id, Player* bot, uint32
|
||||
} else if ((cls == CLASS_SHAMAN && tab == 1)) { // enhancement
|
||||
// STRENGTH mainly (AGILITY, INTELLECT also)
|
||||
score += strength * 1 + agility * 1.5 + intellect * 1.5 + attack_power + spell_power * 1.5 + armor_penetration * 0.5 + meleeDps * 5
|
||||
+ hit * 2 + crit * 1.5 + haste * 1.5 + expertise * 2;
|
||||
+ hit * 1.5 + crit * 1.5 + haste * 1.5 + expertise * 2;
|
||||
} else if ((cls == CLASS_WARRIOR && tab == 2) ||
|
||||
(cls == CLASS_PALADIN && tab == 1)) {
|
||||
// TANK WITH SHIELD
|
||||
score += strength * 1 + agility * 2 + attack_power * 0.2
|
||||
+ defense * 2.5 + parry * 2 + dodge * 2 + resilience * 2 + block * 2 + armor * 0.3 + stamina * 3
|
||||
+ hit * 1 + crit * 0.2 + haste * 0.5 + expertise * 3;
|
||||
+ hit * 0.5 + crit * 0.2 + haste * 0.5 + expertise * 3;
|
||||
} else if (cls == CLASS_DEATH_KNIGHT && tab == 0){
|
||||
// BLOOD DK TANK
|
||||
score += strength * 1 + agility * 2 + attack_power * 0.2
|
||||
+ defense * 3.5 + parry * 2 + dodge * 2 + resilience * 2 + armor * 0.3 + stamina * 2.5
|
||||
+ hit * 2 + crit * 0.5 + haste * 0.5 + expertise * 3.5;
|
||||
+ hit * 0.5 + crit * 0.5 + haste * 0.5 + expertise * 3.5;
|
||||
} else {
|
||||
// BEAR DRUID TANK (AND FERAL DRUID...?)
|
||||
// BEAR DRUID TANK
|
||||
score += agility * 1.5 + strength * 1 + attack_power * 0.5 + armor_penetration * 0.5 + meleeDps * 2
|
||||
+ defense * 0.25 + dodge * 0.25 + armor * 0.3 + stamina * 1.5
|
||||
+ hit * 1 + crit * 1 + haste * 0.5 + expertise * 3;
|
||||
|
||||
@@ -74,6 +74,12 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId
|
||||
|
||||
void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder)
|
||||
{
|
||||
// has bot already been added?
|
||||
Player* loginBot = ObjectAccessor::FindConnectedPlayer(holder.GetGuid());
|
||||
if (loginBot && loginBot->IsInWorld()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 botAccountId = holder.GetAccountId();
|
||||
|
||||
WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), LOCALE_enUS, 0, false, false, 0, true);
|
||||
|
||||
@@ -152,6 +152,7 @@ class ActionContext : public NamedObjectContext<Action>
|
||||
creators["auto talents"] = &ActionContext::auto_talents;
|
||||
creators["auto learn spell"] = &ActionContext::auto_learn_spell;
|
||||
creators["auto teleport for level"] = &ActionContext::auto_teleport_for_level;
|
||||
creators["auto upgrade equip"] = &ActionContext::auto_upgrade_equip;
|
||||
creators["xp gain"] = &ActionContext::xp_gain;
|
||||
creators["invite nearby"] = &ActionContext::invite_nearby;
|
||||
creators["invite guild"] = &ActionContext::invite_guild;
|
||||
@@ -319,6 +320,7 @@ class ActionContext : public NamedObjectContext<Action>
|
||||
static Action* auto_talents(PlayerbotAI* botAI) { return new AutoSetTalentsAction(botAI); }
|
||||
static Action* auto_learn_spell(PlayerbotAI* botAI) { return new AutoLearnSpellAction(botAI); }
|
||||
static Action* auto_teleport_for_level(PlayerbotAI* botAI) { return new AutoTeleportForLevelAction(botAI); }
|
||||
static Action* auto_upgrade_equip(PlayerbotAI* botAI) { return new AutoUpgradeEquipAction(botAI); }
|
||||
static Action* xp_gain(PlayerbotAI* botAI) { return new XpGainAction(botAI); }
|
||||
static Action* invite_nearby(PlayerbotAI* botAI) { return new InviteNearbyToGroupAction(botAI); }
|
||||
static Action* invite_guild(PlayerbotAI* botAI) { return new InviteGuildToGroupAction(botAI); }
|
||||
|
||||
@@ -95,7 +95,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bot->IsMounted() && bot->IsWithinLOSInMap(target) && sServerFacade->GetDistance2d(bot, target) < 40.0f)
|
||||
if (bot->IsMounted() && bot->IsWithinLOSInMap(target))
|
||||
{
|
||||
WorldPacket emptyPacket;
|
||||
bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket);
|
||||
|
||||
@@ -24,7 +24,6 @@ bool AutoLearnSpellAction::Execute(Event event)
|
||||
out << ".";
|
||||
botAI->TellMaster(out);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -181,3 +180,15 @@ void AutoLearnSpellAction::LearnSpell(uint32 spellId, std::ostringstream* out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AutoUpgradeEquipAction::Execute(Event event) {
|
||||
if (!sPlayerbotAIConfig->autoUpgradeEquip || !sRandomPlayerbotMgr->IsRandomBot(bot)) {
|
||||
return false;
|
||||
}
|
||||
PlayerbotFactory factory(bot, bot->GetLevel(), ITEM_QUALITY_RARE);
|
||||
if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) {
|
||||
factory.InitEquipment(true);
|
||||
}
|
||||
factory.InitAmmo();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,4 +23,12 @@ class AutoLearnSpellAction : public Action
|
||||
void LearnSpell(uint32 spellId, std::ostringstream* out);
|
||||
};
|
||||
|
||||
class AutoUpgradeEquipAction : public Action
|
||||
{
|
||||
public:
|
||||
AutoUpgradeEquipAction(PlayerbotAI* botAI, std::string const name = "auto upgrade equip") : Action(botAI, name) { }
|
||||
|
||||
bool Execute(Event event);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#include "SharedDefines.h"
|
||||
|
||||
bool AutoTeleportForLevelAction::Execute(Event event) {
|
||||
AutoUpgradeEquip();
|
||||
|
||||
if (!sPlayerbotAIConfig->autoTeleportForLevel || !sRandomPlayerbotMgr->IsRandomBot(bot)) {
|
||||
return false;
|
||||
}
|
||||
@@ -17,14 +15,3 @@ bool AutoTeleportForLevelAction::Execute(Event event) {
|
||||
sRandomPlayerbotMgr->RandomTeleportForLevel(bot);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AutoTeleportForLevelAction::AutoUpgradeEquip() {
|
||||
if (!sPlayerbotAIConfig->autoUpgradeEquip || !sRandomPlayerbotMgr->IsRandomBot(bot)) {
|
||||
return;
|
||||
}
|
||||
PlayerbotFactory factory(bot, bot->GetLevel(), ITEM_QUALITY_RARE);
|
||||
if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) {
|
||||
factory.InitEquipment(true);
|
||||
}
|
||||
factory.InitAmmo();
|
||||
}
|
||||
@@ -15,8 +15,6 @@ class AutoTeleportForLevelAction : public Action
|
||||
AutoTeleportForLevelAction(PlayerbotAI* botAI, std::string const name = "auto teleport for level") : Action(botAI, name) { }
|
||||
|
||||
bool Execute(Event event);
|
||||
private:
|
||||
void AutoUpgradeEquip();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4115,7 +4115,8 @@ bool BGTactics::selectObjective(bool reset)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -4503,7 +4504,7 @@ bool BGTactics::atFlag(std::vector<BattleBotPath*> const& vPaths, std::vector<ui
|
||||
if (f == vFlagIds.end())
|
||||
continue;
|
||||
|
||||
if (!go->isSpawned() || !go->GetGoState() == GO_STATE_READY)
|
||||
if (!go->isSpawned() || go->GetGoState() != GO_STATE_READY)
|
||||
continue;
|
||||
|
||||
if (!bot->CanUseBattlegroundObject(go) && bgType != BATTLEGROUND_WS)
|
||||
@@ -4644,6 +4645,8 @@ bool BGTactics::atFlag(std::vector<BattleBotPath*> const& vPaths, std::vector<ui
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ bool BuyAction::Execute(Event event)
|
||||
case ITEM_USAGE_SKILL:
|
||||
needMoneyFor = NeedMoneyFor::tradeskill;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (needMoneyFor == NeedMoneyFor::none)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
uint32 FindLastSeparator(std::string const text, std::string const sep)
|
||||
{
|
||||
uint32 pos = text.rfind(sep);
|
||||
size_t pos = text.rfind(sep);
|
||||
if (pos == std::string::npos)
|
||||
return pos;
|
||||
|
||||
@@ -64,7 +64,7 @@ bool CastCustomSpellAction::Execute(Event event)
|
||||
|
||||
Item* itemTarget = nullptr;
|
||||
|
||||
uint32 pos = FindLastSeparator(text, " ");
|
||||
size_t pos = FindLastSeparator(text, " ");
|
||||
uint32 castCount = 1;
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
|
||||
@@ -46,19 +46,19 @@ void ChooseTravelTargetAction::getNewTarget(TravelTarget* newTarget, TravelTarge
|
||||
foundTarget = SetNpcFlagTarget(newTarget, { UNIT_NPC_FLAG_BANKER,UNIT_NPC_FLAG_BATTLEMASTER,UNIT_NPC_FLAG_AUCTIONEER });
|
||||
|
||||
//Grind for money
|
||||
if (!foundTarget && AI_VALUE(bool, "should get money"))
|
||||
if (!foundTarget && AI_VALUE(bool, "should get money")) {
|
||||
if (urand(1, 100) > 66)
|
||||
{
|
||||
foundTarget = SetQuestTarget(newTarget, true); //Turn in quests for money.
|
||||
|
||||
if (!foundTarget)
|
||||
foundTarget = SetQuestTarget(newTarget); //Do low level quests
|
||||
}
|
||||
else if (urand(1, 100) > 50)
|
||||
} else if (urand(1, 100) > 50) {
|
||||
foundTarget = SetGrindTarget(newTarget); //Go grind mobs for money
|
||||
else
|
||||
} else {
|
||||
foundTarget = SetNewQuestTarget(newTarget); //Find a low level quest to do
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Continue
|
||||
if (!foundTarget && urand(1, 100) > 10) //90% chance
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
bool CustomStrategyEditAction::Execute(Event event)
|
||||
{
|
||||
std::string text = event.getParam();
|
||||
uint32 pos = text.find(" ");
|
||||
size_t pos = text.find(" ");
|
||||
if (pos == std::string::npos)
|
||||
return PrintHelp();
|
||||
|
||||
|
||||
@@ -147,6 +147,8 @@ RollVote LootRollAction::CalculateRollVote(ItemTemplate const* proto)
|
||||
case ITEM_USAGE_VENDOR:
|
||||
needVote = GREED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return StoreLootAction::IsLootAllowed(proto->ItemId, GET_PLAYERBOT_AI(bot)) ? needVote : PASS;
|
||||
|
||||
@@ -17,7 +17,7 @@ bool RangeAction::Execute(Event event)
|
||||
PrintRange("flee");
|
||||
}
|
||||
|
||||
uint32 pos = param.find(" ");
|
||||
size_t pos = param.find(" ");
|
||||
if (pos == std::string::npos)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ void TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver
|
||||
case QUEST_STATUS_FAILED:
|
||||
out << "|cffff0000Failed|r";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out << ": " << chat->FormatQuest(quest);
|
||||
@@ -257,6 +259,8 @@ bool TurnInQueryQuestAction::Execute(Event event)
|
||||
case QUEST_STATUS_REWARDED:
|
||||
out << "|cffff0000Rewarded|r";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out << ": " << chat->FormatQuest(quest);
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#ifndef WIN32
|
||||
inline int strcmpi(char const* s1, char const* s2)
|
||||
{
|
||||
for (; *s1 && *s2 && (toupper(*s1) == toupper(*s2)); ++s1, ++s2);
|
||||
return *s1 - *s2;
|
||||
for (; *s1 && *s2 && (toupper(*s1) == toupper(*s2)); ++s1, ++s2) {}
|
||||
return *s1 - *s2;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class DeathKnightTriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
DeathKnightTriggerFactoryInternal()
|
||||
{
|
||||
creators["bone shield"] = &DeathKnightTriggerFactoryInternal::bone_shield;
|
||||
creators["pestilence"] = &DeathKnightTriggerFactoryInternal::pestilence;
|
||||
creators["pestilence glyph"] = &DeathKnightTriggerFactoryInternal::pestilence_glyph;
|
||||
creators["blood strike"] = &DeathKnightTriggerFactoryInternal::blood_strike;
|
||||
creators["plague strike"] = &DeathKnightTriggerFactoryInternal::plague_strike;
|
||||
creators["plague strike on attacker"] = &DeathKnightTriggerFactoryInternal::plague_strike_on_attacker;
|
||||
@@ -94,7 +94,7 @@ class DeathKnightTriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
|
||||
private:
|
||||
static Trigger* bone_shield(PlayerbotAI* botAI) { return new BoneShieldTrigger(botAI); }
|
||||
static Trigger* pestilence(PlayerbotAI* botAI) { return new PestilenceTrigger(botAI); }
|
||||
static Trigger* pestilence_glyph(PlayerbotAI* botAI) { return new PestilenceGlyphTrigger(botAI); }
|
||||
static Trigger* blood_strike(PlayerbotAI* botAI) { return new BloodStrikeTrigger(botAI); }
|
||||
static Trigger* plague_strike(PlayerbotAI* botAI) { return new PlagueStrikeDebuffTrigger(botAI); }
|
||||
static Trigger* plague_strike_on_attacker(PlayerbotAI* botAI) { return new PlagueStrikeDebuffOnAttackerTrigger(botAI); }
|
||||
|
||||
@@ -14,7 +14,7 @@ bool DKPresenceTrigger::IsActive()
|
||||
return !botAI->HasAura("blood presence", target) && !botAI->HasAura("unholy presence", target) && !botAI->HasAura("frost presence", target);
|
||||
}
|
||||
|
||||
bool PestilenceTrigger::IsActive() {
|
||||
bool PestilenceGlyphTrigger::IsActive() {
|
||||
if (!SpellTrigger::IsActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -71,10 +71,10 @@ class DeathCoilTrigger : public SpellCanBeCastTrigger
|
||||
DeathCoilTrigger(PlayerbotAI* botAI) : SpellCanBeCastTrigger(botAI, "death coil") { }
|
||||
};
|
||||
|
||||
class PestilenceTrigger : public DebuffTrigger
|
||||
class PestilenceGlyphTrigger : public SpellTrigger
|
||||
{
|
||||
public:
|
||||
PestilenceTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "pestilence") { }
|
||||
PestilenceGlyphTrigger(PlayerbotAI* botAI) : SpellTrigger(botAI, "pestilence") { }
|
||||
virtual bool IsActive() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -192,5 +192,5 @@ void GenericDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("light aoe", NextAction::array(0,
|
||||
// new NextAction("pestilence", ACTION_NORMAL + 4),
|
||||
// nullptr)));
|
||||
triggers.push_back(new TriggerNode("pestilence", NextAction::array(0, new NextAction("pestilence", ACTION_HIGH + 9), NULL)));
|
||||
triggers.push_back(new TriggerNode("pestilence glyph", NextAction::array(0, new NextAction("pestilence", ACTION_HIGH + 9), NULL)));
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
void CombatStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell", ACTION_MOVE + 11), nullptr)));
|
||||
triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell", ACTION_HIGH), nullptr)));
|
||||
triggers.push_back(new TriggerNode("invalid target", NextAction::array(0, new NextAction("drop target", 100), nullptr)));
|
||||
triggers.push_back(new TriggerNode("mounted", NextAction::array(0, new NextAction("check mount state", 54), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("out of react range", NextAction::array(0, new NextAction("flee to master", 55), nullptr)));
|
||||
@@ -24,44 +24,44 @@ AvoidAoeStrategy::AvoidAoeStrategy(PlayerbotAI* botAI) : Strategy(botAI)
|
||||
}
|
||||
|
||||
|
||||
class AvoidAoeStrategyMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
AvoidAoeStrategyMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "run away on area debuff") {}
|
||||
// class AvoidAoeStrategyMultiplier : public Multiplier
|
||||
// {
|
||||
// public:
|
||||
// AvoidAoeStrategyMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "run away on area debuff") {}
|
||||
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
// public:
|
||||
// virtual float GetValue(Action* action);
|
||||
|
||||
private:
|
||||
};
|
||||
// private:
|
||||
// };
|
||||
|
||||
float AvoidAoeStrategyMultiplier::GetValue(Action* action)
|
||||
{
|
||||
if (!action)
|
||||
return 1.0f;
|
||||
// float AvoidAoeStrategyMultiplier::GetValue(Action* action)
|
||||
// {
|
||||
// if (!action)
|
||||
// return 1.0f;
|
||||
|
||||
std::string name = action->getName();
|
||||
if (name == "follow" || name == "co" || name == "nc" || name == "drop target")
|
||||
return 1.0f;
|
||||
// std::string name = action->getName();
|
||||
// if (name == "follow" || name == "co" || name == "nc" || name == "drop target")
|
||||
// return 1.0f;
|
||||
|
||||
uint32 spellId = AI_VALUE2(uint32, "spell id", name);
|
||||
const SpellInfo* const pSpellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||
if (!pSpellInfo) return 1.0f;
|
||||
// uint32 spellId = AI_VALUE2(uint32, "spell id", name);
|
||||
// const SpellInfo* const pSpellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||
// if (!pSpellInfo) return 1.0f;
|
||||
|
||||
if (spellId && pSpellInfo->Targets & TARGET_FLAG_DEST_LOCATION)
|
||||
return 1.0f;
|
||||
else if (spellId && pSpellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION)
|
||||
return 1.0f;
|
||||
// if (spellId && pSpellInfo->Targets & TARGET_FLAG_DEST_LOCATION)
|
||||
// return 1.0f;
|
||||
// else if (spellId && pSpellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION)
|
||||
// return 1.0f;
|
||||
|
||||
uint32 castTime = pSpellInfo->CalcCastTime(bot);
|
||||
// uint32 castTime = pSpellInfo->CalcCastTime(bot);
|
||||
|
||||
if (AI_VALUE2(bool, "has area debuff", "self target") && spellId && castTime > 0)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
// if (AI_VALUE2(bool, "has area debuff", "self target") && spellId && castTime > 0)
|
||||
// {
|
||||
// return 0.0f;
|
||||
// }
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
// return 1.0f;
|
||||
// }
|
||||
|
||||
NextAction** AvoidAoeStrategy::getDefaultActions()
|
||||
{
|
||||
@@ -86,6 +86,6 @@ void AvoidAoeStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||
NextAction** CombatFormationStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("combat formation move", ACTION_EMERGENCY),
|
||||
new NextAction("combat formation move", ACTION_NORMAL),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -37,9 +37,10 @@ void WorldPacketHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
||||
triggers.push_back(new TriggerNode("bg status", NextAction::array(0, new NextAction("bg status", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("xpgain", NextAction::array(0, new NextAction("xp gain", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("levelup", NextAction::array(0,
|
||||
new NextAction("auto talents", relevance),
|
||||
new NextAction("auto learn spell", relevance),
|
||||
new NextAction("auto teleport for level", relevance),
|
||||
new NextAction("auto teleport for level", relevance + 3),
|
||||
new NextAction("auto talents", relevance + 2),
|
||||
new NextAction("auto learn spell", relevance + 1),
|
||||
new NextAction("auto upgrade equip", relevance),
|
||||
nullptr)));
|
||||
// triggers.push_back(new TriggerNode("group destroyed", NextAction::array(0, new NextAction("reset botAI", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("questgiver quest details", NextAction::array(0, new NextAction("turn in query quest", relevance), nullptr)));
|
||||
|
||||
@@ -153,7 +153,7 @@ bool CastMeleeConsecrationAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
// float dis = distance + CONTACT_DISTANCE;
|
||||
return target && bot->IsWithinCombatRange(target, sPlayerbotAIConfig->meleeDistance); // sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", GetTargetName()), distance);
|
||||
return target && bot->IsWithinMeleeRange(target); // sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", GetTargetName()), distance);
|
||||
}
|
||||
|
||||
bool CastDivineSacrificeAction::isUseful()
|
||||
|
||||
@@ -94,6 +94,9 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode(
|
||||
"medium group heal occasion",
|
||||
NextAction::array(0, new NextAction("divine sacrifice", ACTION_HIGH + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enough mana",
|
||||
NextAction::array(0, new NextAction("melee consecration", ACTION_HIGH + 4), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"not facing target",
|
||||
NextAction::array(0, new NextAction("set facing", ACTION_NORMAL + 7), nullptr)));
|
||||
|
||||
@@ -52,6 +52,7 @@ void CasterShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode("shaman weapon", NextAction::array(0, new NextAction("flametongue weapon", 23.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("searing totem", NextAction::array(0, new NextAction("searing totem", 19.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("flame shock", NextAction::array(0, new NextAction("flame shock", 20.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("elemental mastery", NextAction::array(0, new NextAction("elemental mastery", 27.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("frost shock snare", NextAction::array(0, new NextAction("frost shock", 21.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"no fire totem",
|
||||
|
||||
@@ -350,6 +350,12 @@ class CastBloodlustAction : public CastBuffSpellAction
|
||||
CastBloodlustAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "bloodlust") { }
|
||||
};
|
||||
|
||||
class CastElementalMasteryAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastElementalMasteryAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "elemental mastery") { }
|
||||
};
|
||||
|
||||
class CastWindShearOnEnemyHealerAction : public CastSpellOnEnemyHealerAction
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -96,6 +96,7 @@ class ShamanATriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
creators["frost shock snare"] = &ShamanATriggerFactoryInternal::frost_shock_snare;
|
||||
creators["heroism"] = &ShamanATriggerFactoryInternal::heroism;
|
||||
creators["bloodlust"] = &ShamanATriggerFactoryInternal::bloodlust;
|
||||
creators["elemental mastery"] = &ShamanATriggerFactoryInternal::elemental_mastery;
|
||||
creators["wind shear on enemy healer"] = &ShamanATriggerFactoryInternal::wind_shear_on_enemy_healer;
|
||||
creators["cure poison"] = &ShamanATriggerFactoryInternal::cure_poison;
|
||||
creators["party member cure poison"] = &ShamanATriggerFactoryInternal::party_member_cure_poison;
|
||||
@@ -114,6 +115,7 @@ class ShamanATriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
static Trigger* maelstrom_weapon(PlayerbotAI* botAI) { return new MaelstromWeaponTrigger(botAI); }
|
||||
static Trigger* heroism(PlayerbotAI* botAI) { return new HeroismTrigger(botAI); }
|
||||
static Trigger* bloodlust(PlayerbotAI* botAI) { return new BloodlustTrigger(botAI); }
|
||||
static Trigger* elemental_mastery(PlayerbotAI* botAI) { return new ElementalMasteryTrigger(botAI); }
|
||||
static Trigger* party_member_cleanse_disease(PlayerbotAI* botAI) { return new PartyMemberCleanseSpiritDiseaseTrigger(botAI); }
|
||||
static Trigger* party_member_cleanse_curse(PlayerbotAI* botAI) { return new PartyMemberCleanseSpiritCurseTrigger(botAI); }
|
||||
static Trigger* party_member_cleanse_poison(PlayerbotAI* botAI) { return new PartyMemberCleanseSpiritPoisonTrigger(botAI); }
|
||||
@@ -206,6 +208,7 @@ class ShamanAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
creators["thunderstorm"] = &ShamanAiObjectContextInternal::thunderstorm;
|
||||
creators["heroism"] = &ShamanAiObjectContextInternal::heroism;
|
||||
creators["bloodlust"] = &ShamanAiObjectContextInternal::bloodlust;
|
||||
creators["elemental mastery"] = &ShamanAiObjectContextInternal::elemental_mastery;
|
||||
// creators["cure disease"] = &ShamanAiObjectContextInternal::cure_disease;
|
||||
// creators["cure disease on party"] = &ShamanAiObjectContextInternal::cure_disease_on_party;
|
||||
// creators["cure poison"] = &ShamanAiObjectContextInternal::cure_poison;
|
||||
@@ -222,6 +225,7 @@ class ShamanAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
private:
|
||||
static Action* heroism(PlayerbotAI* botAI) { return new CastHeroismAction(botAI); }
|
||||
static Action* bloodlust(PlayerbotAI* botAI) { return new CastBloodlustAction(botAI); }
|
||||
static Action* elemental_mastery(PlayerbotAI* botAI) { return new CastElementalMasteryAction(botAI); }
|
||||
static Action* thunderstorm(PlayerbotAI* botAI) { return new CastThunderstormAction(botAI); }
|
||||
static Action* lightning_bolt(PlayerbotAI* botAI) { return new CastLightningBoltAction(botAI); }
|
||||
static Action* chain_lightning(PlayerbotAI* botAI) { return new CastChainLightningAction(botAI); }
|
||||
|
||||
@@ -201,6 +201,12 @@ class BloodlustTrigger : public BoostTrigger
|
||||
BloodlustTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "bloodlust") { }
|
||||
};
|
||||
|
||||
class ElementalMasteryTrigger : public BoostTrigger
|
||||
{
|
||||
public:
|
||||
ElementalMasteryTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "elemental mastery") { }
|
||||
};
|
||||
|
||||
class MaelstromWeaponTrigger : public HasAuraStackTrigger
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -64,6 +64,11 @@ bool AlmostFullManaTrigger::IsActive()
|
||||
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") > 85;
|
||||
}
|
||||
|
||||
bool EnoughManaTrigger::IsActive()
|
||||
{
|
||||
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") > 65;
|
||||
}
|
||||
|
||||
bool RageAvailable::IsActive()
|
||||
{
|
||||
return AI_VALUE2(uint8, "rage", "self target") >= amount;
|
||||
|
||||
@@ -30,6 +30,14 @@ class HighManaTrigger : public Trigger
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class EnoughManaTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
EnoughManaTrigger(PlayerbotAI* botAI) : Trigger(botAI, "enough mana") { }
|
||||
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class AlmostFullManaTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -45,6 +45,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
|
||||
creators["medium mana"] = &TriggerContext::MediumMana;
|
||||
creators["high mana"] = &TriggerContext::HighMana;
|
||||
creators["almost full mana"] = &TriggerContext::AlmostFullMana;
|
||||
creators["enough mana"] = &TriggerContext::EnoughMana;
|
||||
|
||||
creators["party member critical health"] = &TriggerContext::PartyMemberCriticalHealth;
|
||||
creators["party member low health"] = &TriggerContext::PartyMemberLowHealth;
|
||||
@@ -253,6 +254,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
|
||||
static Trigger* MediumMana(PlayerbotAI* botAI) { return new MediumManaTrigger(botAI); }
|
||||
static Trigger* HighMana(PlayerbotAI* botAI) { return new HighManaTrigger(botAI); }
|
||||
static Trigger* AlmostFullMana(PlayerbotAI* botAI) { return new AlmostFullManaTrigger(botAI); }
|
||||
static Trigger* EnoughMana(PlayerbotAI* botAI) { return new EnoughManaTrigger(botAI); }
|
||||
static Trigger* LightRageAvailable(PlayerbotAI* botAI) { return new LightRageAvailableTrigger(botAI); }
|
||||
static Trigger* MediumRageAvailable(PlayerbotAI* botAI) { return new MediumRageAvailableTrigger(botAI); }
|
||||
static Trigger* HighRageAvailable(PlayerbotAI* botAI) { return new HighRageAvailableTrigger(botAI); }
|
||||
|
||||
@@ -172,7 +172,7 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float range)
|
||||
// (inCannon || !attacker->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) && attacker->CanSeeOrDetect(bot) &&
|
||||
// !(attacker->HasUnitState(UNIT_STATE_STUNNED) && botAI->HasAura("shackle undead", attacker)) && !((attacker->IsPolymorphed() || botAI->HasAura("sap", attacker) || /*attacker->IsCharmed() ||*/ attacker->isFeared()) && !rti) &&
|
||||
/*!sServerFacade->IsInRoots(attacker) &&*/
|
||||
!attacker->IsFriendlyTo(bot) && bot->IsWithinDistInMap(attacker, range) &&
|
||||
!attacker->IsFriendlyTo(bot) &&
|
||||
!attacker->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION) &&
|
||||
// !(attacker->GetGUID().IsPet() && enemy) &&
|
||||
!(attacker->GetCreatureType() == CREATURE_TYPE_CRITTER && !attacker->IsInCombat()) &&
|
||||
|
||||
@@ -180,6 +180,8 @@ uint32 MoneyNeededForValue::Calculate()
|
||||
case NeedMoneyFor::tradeskill:
|
||||
moneyWanted = (level * level * level); //Or level^3 (10s @ lvl10, 3g @ lvl30, 20g @ lvl60, 50g @ lvl80): Todo replace (Should be buyable reagents that combined allow crafting of usefull items)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return moneyWanted;
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#ifndef WIN32
|
||||
inline int strcmpi(char const* s1, char const* s2)
|
||||
{
|
||||
for (; *s1 && *s2 && (toupper(*s1) == toupper(*s2)); ++s1, ++s2);
|
||||
return *s1 - *s2;
|
||||
for (; *s1 && *s2 && (toupper(*s1) == toupper(*s2)); ++s1, ++s2) {}
|
||||
return *s1 - *s2;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class Unit;
|
||||
class PartyMemberToDispel : public PartyMemberValue, public Qualified
|
||||
{
|
||||
public:
|
||||
PartyMemberToDispel(PlayerbotAI* botAI, std::string const name = "party member to dispel") : PartyMemberValue(botAI, name, 2 * 1000), Qualified() { }
|
||||
PartyMemberToDispel(PlayerbotAI* botAI, std::string const name = "party member to dispel") : PartyMemberValue(botAI, name, 1000), Qualified() { }
|
||||
|
||||
protected:
|
||||
Unit* Calculate() override;
|
||||
|
||||
@@ -32,7 +32,9 @@ ArmsWarriorStrategy::ArmsWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr
|
||||
|
||||
NextAction** ArmsWarriorStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("heroic strike", ACTION_DEFAULT), nullptr);
|
||||
return NextAction::array(0,
|
||||
new NextAction("bladestorm", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT), nullptr);
|
||||
}
|
||||
|
||||
void ArmsWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
@@ -56,4 +58,5 @@ void ArmsWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode("rend", NextAction::array(0, new NextAction("rend", ACTION_HIGH + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rend on attacker", NextAction::array(0, new NextAction("rend on attacker", ACTION_HIGH + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("intimidating shout", ACTION_EMERGENCY), nullptr)));
|
||||
triggers.push_back(new TriggerNode("medium rage available", NextAction::array(0, new NextAction("thunder clap", ACTION_HIGH + 1), nullptr)));
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ void FuryWarriorStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
|
||||
triggers.push_back(new TriggerNode("bloodthirst", NextAction::array(0, new NextAction("bloodthirst", ACTION_HIGH + 7), nullptr)));
|
||||
triggers.push_back(new TriggerNode("instant slam", NextAction::array(0, new NextAction("slam", ACTION_HIGH + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode("bloodrage", NextAction::array(0, new NextAction("bloodrage", ACTION_HIGH + 2), nullptr)));
|
||||
triggers.push_back(new TriggerNode("high rage available", NextAction::array(0, new NextAction("heroic strike", ACTION_HIGH + 1), NULL)));
|
||||
triggers.push_back(new TriggerNode("medium rage available", NextAction::array(0, new NextAction("heroic strike", ACTION_HIGH + 1), NULL)));
|
||||
// triggers.push_back(new TriggerNode("berserker rage", NextAction::array(0, new NextAction("berserker rage", ACTION_HIGH + 2), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("light aoe", NextAction::array(0,
|
||||
// new NextAction("whirlwind", ACTION_HIGH + 2),
|
||||
|
||||
@@ -88,4 +88,6 @@ void TankWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode("rend", NextAction::array(0, new NextAction("rend", ACTION_NORMAL + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rend on attacker", NextAction::array(0, new NextAction("rend on attacker", ACTION_NORMAL + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("protect party member", NextAction::array(0, new NextAction("intervene", ACTION_EMERGENCY), nullptr)));
|
||||
triggers.push_back(new TriggerNode("high rage available", NextAction::array(0, new NextAction("heroic strike", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("medium rage available", NextAction::array(0, new NextAction("thunder clap", ACTION_HIGH + 1), nullptr)));
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ class WarriorTriggerFactoryInternal : public NamedObjectContext<Trigger>
|
||||
static Trigger* SwordAndBoard(PlayerbotAI* botAI) { return new SwordAndBoardTrigger(botAI); }
|
||||
static Trigger* shield_bash_on_enemy_healer(PlayerbotAI* botAI) { return new ShieldBashInterruptEnemyHealerSpellTrigger(botAI); }
|
||||
|
||||
static Trigger* thunderclap_and_rage(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "thunderclap", "light rage available"); }
|
||||
static Trigger* thunderclap_and_rage(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "thunder clap", "light rage available"); }
|
||||
static Trigger* intercept_can_cast(PlayerbotAI* botAI) { return new InterceptCanCastTrigger(botAI); }
|
||||
static Trigger* intercept_and_far_enemy(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "enemy is out of melee", "intercept can cast"); }
|
||||
static Trigger* intercept_and_rage(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "intercept and far enemy", "light rage available"); }
|
||||
|
||||
Reference in New Issue
Block a user