mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge pull request #506 from liyunfan1223/estimated_group_dps
Improve estimated group dps
This commit is contained in:
@@ -342,6 +342,7 @@ AiPlayerbot.MediumHealth = 65
|
||||
AiPlayerbot.AlmostFullHealth = 85
|
||||
AiPlayerbot.LowMana = 15
|
||||
AiPlayerbot.MediumMana = 40
|
||||
AiPlayerbot.HighMana = 65
|
||||
|
||||
#
|
||||
#
|
||||
|
||||
@@ -4326,7 +4326,7 @@ void PlayerbotAI::_fillGearScoreData(Player* player, Item* item, std::vector<uin
|
||||
return;
|
||||
|
||||
uint8 type = proto->InventoryType;
|
||||
uint32 level = mixed ? proto->ItemLevel * (1 + proto->Quality) : proto->ItemLevel;
|
||||
uint32 level = mixed ? proto->ItemLevel * PlayerbotAI::GetItemScoreMultiplier(ItemQualities(proto->Quality)) : proto->ItemLevel;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -5838,3 +5838,32 @@ void PlayerbotAI::PetFollow()
|
||||
charmInfo->SetForcedSpell(0);
|
||||
charmInfo->SetForcedTargetGUID();
|
||||
}
|
||||
|
||||
float PlayerbotAI::GetItemScoreMultiplier(ItemQualities quality)
|
||||
{
|
||||
switch (quality)
|
||||
{
|
||||
// each quality increase 1.1x
|
||||
case ITEM_QUALITY_POOR:
|
||||
return 1.0f;
|
||||
break;
|
||||
case ITEM_QUALITY_NORMAL:
|
||||
return 1.1f;
|
||||
break;
|
||||
case ITEM_QUALITY_UNCOMMON:
|
||||
return 1.21f;
|
||||
break;
|
||||
case ITEM_QUALITY_RARE:
|
||||
return 1.331f;
|
||||
break;
|
||||
case ITEM_QUALITY_EPIC:
|
||||
return 1.4641f;
|
||||
break;
|
||||
case ITEM_QUALITY_LEGENDARY:
|
||||
return 1.61051f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
@@ -569,6 +569,7 @@ public:
|
||||
std::set<uint32> GetAllCurrentQuestIds();
|
||||
std::set<uint32> GetCurrentIncompleteQuestIds();
|
||||
void PetFollow();
|
||||
static float GetItemScoreMultiplier(ItemQualities quality);
|
||||
|
||||
private:
|
||||
static void _fillGearScoreData(Player* player, Item* item, std::vector<uint32>* gearScore, uint32& twoHandScore,
|
||||
|
||||
@@ -94,6 +94,7 @@ bool PlayerbotAIConfig::Initialize()
|
||||
almostFullHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.AlmostFullHealth", 85);
|
||||
lowMana = sConfigMgr->GetOption<int32>("AiPlayerbot.LowMana", 15);
|
||||
mediumMana = sConfigMgr->GetOption<int32>("AiPlayerbot.MediumMana", 40);
|
||||
highMana = sConfigMgr->GetOption<int32>("AiPlayerbot.HighMana", 65);
|
||||
autoSaveMana = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoSaveMana", true);
|
||||
saveManaThreshold = sConfigMgr->GetOption<int32>("AiPlayerbot.SaveManaThreshold", 60);
|
||||
autoAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoAvoidAoe", true);
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
tooCloseDistance, meleeDistance, followDistance, whisperDistance, contactDistance, aoeRadius, rpgDistance,
|
||||
targetPosRecalcDistance, farDistance, healDistance, aggroDistance;
|
||||
uint32 criticalHealth, lowHealth, mediumHealth, almostFullHealth;
|
||||
uint32 lowMana, mediumMana;
|
||||
uint32 lowMana, mediumMana, highMana;
|
||||
bool autoSaveMana;
|
||||
uint32 saveManaThreshold;
|
||||
bool autoAvoidAoe;
|
||||
|
||||
@@ -1217,7 +1217,7 @@ bool PlayerbotFactory::CanEquipWeapon(ItemTemplate const* proto)
|
||||
{
|
||||
case CLASS_PRIEST:
|
||||
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF && proto->SubClass != ITEM_SUBCLASS_WEAPON_WAND &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE)
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER)
|
||||
return false;
|
||||
break;
|
||||
case CLASS_MAGE:
|
||||
@@ -1231,15 +1231,12 @@ bool PlayerbotFactory::CanEquipWeapon(ItemTemplate const* proto)
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_GUN && proto->SubClass != ITEM_SUBCLASS_WEAPON_CROSSBOW &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_THROWN)
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_THROWN &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF)
|
||||
return false;
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD)
|
||||
return false;
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 &&
|
||||
@@ -1251,28 +1248,30 @@ bool PlayerbotFactory::CanEquipWeapon(ItemTemplate const* proto)
|
||||
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF)
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF)
|
||||
return false;
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF)
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM)
|
||||
return false;
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM &&
|
||||
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && proto->SubClass != ITEM_SUBCLASS_WEAPON_GUN &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_CROSSBOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW)
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM)
|
||||
return false;
|
||||
break;
|
||||
case CLASS_ROGUE:
|
||||
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_GUN && proto->SubClass != ITEM_SUBCLASS_WEAPON_CROSSBOW &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_THROWN)
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_THROWN &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -2646,7 +2645,7 @@ void PlayerbotFactory::InitAmmo()
|
||||
bot->SetAmmo(entry);
|
||||
}
|
||||
|
||||
uint32 PlayerbotFactory::CalcMixedGearScore(uint32 gs, uint32 quality) { return gs * (quality + 1); }
|
||||
uint32 PlayerbotFactory::CalcMixedGearScore(uint32 gs, uint32 quality) { return gs * PlayerbotAI::GetItemScoreMultiplier(ItemQualities(quality)); }
|
||||
|
||||
void PlayerbotFactory::InitMounts()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "ItemTemplate.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "PlayerbotFactory.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "StatsCollector.h"
|
||||
#include "Unit.h"
|
||||
@@ -72,7 +73,7 @@ float StatsWeightCalculator::CalculateItem(uint32 itemId)
|
||||
|
||||
if (enable_quality_blend_)
|
||||
// Blend with item quality and level
|
||||
weight_ *= (proto->Quality + 1) * proto->ItemLevel;
|
||||
weight_ *= PlayerbotFactory::CalcMixedGearScore(proto->ItemLevel, proto->Quality);
|
||||
|
||||
return weight_;
|
||||
}
|
||||
@@ -223,7 +224,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
|
||||
stats_weights_[STATS_TYPE_INTELLECT] += 0.15f;
|
||||
stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f;
|
||||
stats_weights_[STATS_TYPE_SPELL_POWER] += 0.3f;
|
||||
stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 0.8f;
|
||||
stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 0.5f;
|
||||
stats_weights_[STATS_TYPE_HIT] += 1.9f;
|
||||
stats_weights_[STATS_TYPE_CRIT] += 1.2f;
|
||||
stats_weights_[STATS_TYPE_HASTE] += 1.3f;
|
||||
@@ -244,8 +245,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
|
||||
stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f;
|
||||
stats_weights_[STATS_TYPE_MELEE_DPS] += 8.5f;
|
||||
}
|
||||
else if (cls == CLASS_WARLOCK ||
|
||||
cls == CLASS_MAGE ||
|
||||
else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE ||
|
||||
(cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW) || // shadow
|
||||
(cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ELEMENTAL) || // element
|
||||
(cls == CLASS_DRUID && tab == DRUID_TAB_BALANCE)) // balance
|
||||
@@ -272,7 +272,8 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
|
||||
stats_weights_[STATS_TYPE_HASTE] += 1.0f;
|
||||
stats_weights_[STATS_TYPE_RANGED_DPS] += 1.0f;
|
||||
}
|
||||
else if ((cls == CLASS_WARRIOR && tab == WARRIOR_TAB_PROTECTION) || (cls == CLASS_PALADIN && tab == PALADIN_TAB_PROTECTION))
|
||||
else if ((cls == CLASS_WARRIOR && tab == WARRIOR_TAB_PROTECTION) ||
|
||||
(cls == CLASS_PALADIN && tab == PALADIN_TAB_PROTECTION))
|
||||
{
|
||||
stats_weights_[STATS_TYPE_AGILITY] += 2.0f;
|
||||
stats_weights_[STATS_TYPE_STRENGTH] += 1.0f;
|
||||
@@ -366,7 +367,7 @@ void StatsWeightCalculator::CalculateItemSetBonus(Player* player, ItemTemplate c
|
||||
if (itemSet != setId)
|
||||
continue;
|
||||
|
||||
const ItemSetEntry *setEntry = sItemSetStore.LookupEntry(setId);
|
||||
const ItemSetEntry* setEntry = sItemSetStore.LookupEntry(setId);
|
||||
if (!setEntry)
|
||||
continue;
|
||||
|
||||
@@ -395,7 +396,8 @@ void StatsWeightCalculator::CalculateItemSetBonus(Player* player, ItemTemplate c
|
||||
void StatsWeightCalculator::CalculateSocketBonus(Player* player, ItemTemplate const* proto)
|
||||
{
|
||||
uint32 socketNum = 0;
|
||||
for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
|
||||
for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS;
|
||||
++enchant_slot)
|
||||
{
|
||||
uint8 socketColor = proto->Socket[enchant_slot - SOCK_ENCHANTMENT_SLOT].Color;
|
||||
|
||||
@@ -469,13 +471,13 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
|
||||
{
|
||||
weight_ *= 0.1;
|
||||
}
|
||||
if (cls == CLASS_ROGUE && player_->HasAura(13964)
|
||||
&& (proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE))
|
||||
if (cls == CLASS_ROGUE && player_->HasAura(13964) &&
|
||||
(proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE))
|
||||
{
|
||||
weight_ *= 1.1;
|
||||
}
|
||||
if (cls == CLASS_WARRIOR && player_->HasAura(12785)
|
||||
&& (proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2))
|
||||
if (cls == CLASS_WARRIOR && player_->HasAura(12785) &&
|
||||
(proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2))
|
||||
{
|
||||
weight_ *= 1.1;
|
||||
}
|
||||
|
||||
@@ -245,6 +245,8 @@ bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chat
|
||||
GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::GENERAL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 25));
|
||||
@@ -309,6 +311,8 @@ bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatC
|
||||
GET_PLAYERBOT_AI(bot)->SayToGuild(BOT_TEXT2("suggest_toxic_links", placeholders));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 60));
|
||||
@@ -404,6 +408,8 @@ bool ChatReplyAction::HandleWTBItemsReply(Player* bot, ChatChannelSource chatCha
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 60));
|
||||
}
|
||||
@@ -490,6 +496,8 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh
|
||||
GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 25));
|
||||
}
|
||||
|
||||
@@ -122,8 +122,7 @@ CatDpsDruidStrategy::CatDpsDruidStrategy(PlayerbotAI* botAI) : FeralDruidStrateg
|
||||
|
||||
NextAction** CatDpsDruidStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("shred", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("tiger's fury", ACTION_DEFAULT + 0.1f), nullptr);
|
||||
return NextAction::array(0, new NextAction("tiger's fury", ACTION_DEFAULT + 0.1f), nullptr);
|
||||
}
|
||||
|
||||
void CatDpsDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
@@ -131,9 +130,17 @@ void CatDpsDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
FeralDruidStrategy::InitTriggers(triggers);
|
||||
|
||||
// Default priority
|
||||
triggers.push_back(new TriggerNode("high energy available",
|
||||
triggers.push_back(new TriggerNode("almost full energy available",
|
||||
NextAction::array(0, new NextAction("shred", ACTION_DEFAULT + 0.4f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("combo points not full",
|
||||
NextAction::array(0, new NextAction("shred", ACTION_DEFAULT + 0.4f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("almost full energy available",
|
||||
NextAction::array(0, new NextAction("mangle (cat)", ACTION_DEFAULT + 0.3f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("high energy available",
|
||||
triggers.push_back(new TriggerNode("combo points not full and high energy",
|
||||
NextAction::array(0, new NextAction("mangle (cat)", ACTION_DEFAULT + 0.3f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("almost full energy available",
|
||||
NextAction::array(0, new NextAction("claw", ACTION_DEFAULT + 0.2f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("combo points not full and high energy",
|
||||
NextAction::array(0, new NextAction("claw", ACTION_DEFAULT + 0.2f), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("faerie fire (feral)",
|
||||
|
||||
@@ -22,8 +22,6 @@ bool ThornsOnPartyTrigger::IsActive()
|
||||
return BuffOnPartyTrigger::IsActive() && !botAI->HasAura("thorns", GetTarget());
|
||||
}
|
||||
|
||||
bool MoonfireTrigger::IsActive() { return DebuffTrigger::IsActive() && !GetTarget()->HasUnitState(UNIT_STATE_ROOT); }
|
||||
|
||||
bool EntanglingRootsKiteTrigger::IsActive()
|
||||
{
|
||||
return DebuffTrigger::IsActive() && AI_VALUE(uint8, "attacker count") < 3 && !GetTarget()->GetPower(POWER_MANA);
|
||||
|
||||
@@ -75,8 +75,6 @@ class MoonfireTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
MoonfireTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "moonfire", 1, true) {}
|
||||
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class FaerieFireTrigger : public DebuffTrigger
|
||||
@@ -252,12 +250,12 @@ public:
|
||||
return false;
|
||||
|
||||
Aura* roar = botAI->GetAura("savage roar", bot);
|
||||
bool roarCheck = !roar || roar->GetDuration() > 8000;
|
||||
bool roarCheck = !roar || roar->GetDuration() > 10000;
|
||||
if (!roarCheck)
|
||||
return false;
|
||||
|
||||
Aura* rip = botAI->GetAura("rip", target, true);
|
||||
bool ripCheck = !rip || rip->GetDuration() > 8000;
|
||||
bool ripCheck = !rip || rip->GetDuration() > 10000;
|
||||
if (!ripCheck)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -5,12 +5,19 @@
|
||||
|
||||
#include "UseFoodStrategy.h"
|
||||
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
void UseFoodStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
Strategy::InitTriggers(triggers);
|
||||
|
||||
if (sPlayerbotAIConfig->freeFood)
|
||||
triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("food", 3.0f), nullptr)));
|
||||
else
|
||||
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("food", 3.0f), nullptr)));
|
||||
|
||||
if (sPlayerbotAIConfig->freeFood)
|
||||
triggers.push_back(new TriggerNode("high mana", NextAction::array(0, new NextAction("drink", 3.0f), nullptr)));
|
||||
else
|
||||
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("drink", 3.0f), nullptr)));
|
||||
}
|
||||
|
||||
@@ -82,9 +82,11 @@ DpsPaladinStrategy::DpsPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStrat
|
||||
|
||||
NextAction** DpsPaladinStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("crusader strike", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("judgement of wisdom", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("divine storm", ACTION_DEFAULT + 0.2f),
|
||||
return NextAction::array(0,
|
||||
new NextAction("crusader strike", ACTION_DEFAULT + 0.6f),
|
||||
new NextAction("hammer of wrath", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("judgement of wisdom", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("divine storm", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("consecration", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT), NULL);
|
||||
}
|
||||
@@ -93,12 +95,17 @@ void DpsPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
GenericPaladinStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("art of war", NextAction::array(0, new NextAction("exorcism", ACTION_DEFAULT + 0.2f), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("seal", NextAction::array(0, new NextAction("seal of corruption", ACTION_HIGH), NULL)));
|
||||
// triggers.push_back(new TriggerNode("seal", NextAction::array(0, new NextAction("seal of command", 90.0f),
|
||||
// nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("low mana", NextAction::array(0, new NextAction("seal of wisdom", ACTION_HIGH + 5), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"avenging wrath", NextAction::array(0, new NextAction("avenging wrath", ACTION_HIGH + 2), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("sanctity aura", NextAction::array(0, new NextAction("sanctity aura", 90.0f),
|
||||
// nullptr))); triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("repentance or
|
||||
// shield", ACTION_CRITICAL_HEAL + 3), new NextAction("holy light", ACTION_CRITICAL_HEAL + 2), nullptr)));
|
||||
@@ -112,11 +119,11 @@ void DpsPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("repentance", NextAction::array(0, new NextAction("repentance",
|
||||
// ACTION_INTERRUPT + 2), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 3), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("art of war", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 2), nullptr)));
|
||||
triggers.push_back(new TriggerNode("target critical health",
|
||||
NextAction::array(0, new NextAction("hammer of wrath", ACTION_HIGH), nullptr)));
|
||||
"medium aoe", NextAction::array(0,
|
||||
new NextAction("divine storm", ACTION_HIGH + 4),
|
||||
new NextAction("consecration", ACTION_HIGH + 3), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("target critical health",
|
||||
// NextAction::array(0, new NextAction("hammer of wrath", ACTION_HIGH), nullptr)));
|
||||
// triggers.push_back(new TriggerNode(
|
||||
// "not facing target",
|
||||
// NextAction::array(0, new NextAction("set facing", ACTION_NORMAL + 7), NULL)));
|
||||
|
||||
@@ -37,7 +37,7 @@ void GenericPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
"protect party member",
|
||||
NextAction::array(0, new NextAction("blessing of protection on party", ACTION_EMERGENCY + 2), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium mana", NextAction::array(0, new NextAction("divine plea", ACTION_HIGH), NULL)));
|
||||
new TriggerNode("high mana", NextAction::array(0, new NextAction("divine plea", ACTION_HIGH), NULL)));
|
||||
}
|
||||
|
||||
void PaladinCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
@@ -61,8 +61,7 @@ void PaladinCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
void PaladinBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode(
|
||||
"avenging wrath", NextAction::array(0, new NextAction("avenging wrath", ACTION_HIGH + 2), nullptr)));
|
||||
|
||||
// triggers.push_back(new TriggerNode("divine favor", NextAction::array(0, new NextAction("divine favor",
|
||||
// ACTION_HIGH + 1), nullptr)));
|
||||
}
|
||||
|
||||
@@ -50,7 +50,9 @@ void HealPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium group heal occasion",
|
||||
NextAction::array(0, new NextAction("divine sacrifice", ACTION_CRITICAL_HEAL + 5), nullptr)));
|
||||
NextAction::array(0, new NextAction("divine sacrifice", ACTION_CRITICAL_HEAL + 5),
|
||||
new NextAction("avenging wrath", ACTION_HIGH + 4),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member critical health",
|
||||
|
||||
@@ -98,6 +98,8 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
NextAction::array(0, new NextAction("holy shield", ACTION_HIGH + 4), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of sanctuary",
|
||||
// ACTION_HIGH + 9), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"avenging wrath", NextAction::array(0, new NextAction("avenging wrath", ACTION_HIGH + 2), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("target critical health",
|
||||
NextAction::array(0, new NextAction("hammer of wrath", ACTION_CRITICAL_HEAL), nullptr)));
|
||||
|
||||
@@ -51,8 +51,8 @@ void CasterShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell",
|
||||
// ACTION_NORMAL + 9), nullptr))); triggers.push_back(new TriggerNode("shaman weapon", NextAction::array(0, new
|
||||
// NextAction("flametongue weapon", 23.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enough mana", NextAction::array(0, new NextAction("chain lightning", ACTION_DEFAULT + 0.1f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode(
|
||||
// "enough mana", NextAction::array(0, new NextAction("chain lightning", ACTION_DEFAULT + 0.1f), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("main hand weapon no imbue",
|
||||
NextAction::array(0, new NextAction("flametongue weapon", 22.0f), nullptr)));
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "BattlegroundWS.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Playerbots.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TemporarySummon.h"
|
||||
@@ -64,7 +65,7 @@ bool PetAttackTrigger::IsActive()
|
||||
|
||||
bool HighManaTrigger::IsActive()
|
||||
{
|
||||
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < 65;
|
||||
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->highMana;
|
||||
}
|
||||
|
||||
bool AlmostFullManaTrigger::IsActive()
|
||||
@@ -83,6 +84,8 @@ bool EnergyAvailable::IsActive() { return AI_VALUE2(uint8, "energy", "self targe
|
||||
|
||||
bool ComboPointsAvailableTrigger::IsActive() { return AI_VALUE2(uint8, "combo", "current target") >= amount; }
|
||||
|
||||
bool ComboPointsNotFullTrigger::IsActive() { return AI_VALUE2(uint8, "combo", "current target") < amount; }
|
||||
|
||||
bool TargetWithComboPointsLowerHealTrigger::IsActive()
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
|
||||
@@ -126,6 +126,17 @@ private:
|
||||
float lifeTime;
|
||||
};
|
||||
|
||||
class ComboPointsNotFullTrigger : public StatAvailable
|
||||
{
|
||||
public:
|
||||
ComboPointsNotFullTrigger(PlayerbotAI* botAI, int32 amount = 5, std::string const name = "combo points not full")
|
||||
: StatAvailable(botAI, amount, name)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class LoseAggroTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
creators["light energy available"] = &TriggerContext::LightEnergyAvailable;
|
||||
creators["medium energy available"] = &TriggerContext::MediumEnergyAvailable;
|
||||
creators["high energy available"] = &TriggerContext::HighEnergyAvailable;
|
||||
creators["almost full energy available"] = &TriggerContext::AlmostFullEnergyAvailable;
|
||||
|
||||
creators["loot available"] = &TriggerContext::LootAvailable;
|
||||
creators["no attackers"] = &TriggerContext::NoAttackers;
|
||||
@@ -97,6 +98,8 @@ public:
|
||||
creators["combo points available"] = &TriggerContext::ComboPointsAvailable;
|
||||
creators["combo points 3 available"] = &TriggerContext::ComboPoints3Available;
|
||||
creators["target with combo points almost dead"] = &TriggerContext::target_with_combo_points_almost_dead;
|
||||
creators["combo points not full"] = &TriggerContext::ComboPointsNotFull;
|
||||
creators["combo points not full and high energy"] = &TriggerContext::ComboPointsNotFullAndHighEnergy;
|
||||
|
||||
creators["medium threat"] = &TriggerContext::MediumThreat;
|
||||
|
||||
@@ -280,6 +283,7 @@ private:
|
||||
static Trigger* LightEnergyAvailable(PlayerbotAI* botAI) { return new LightEnergyAvailableTrigger(botAI); }
|
||||
static Trigger* MediumEnergyAvailable(PlayerbotAI* botAI) { return new MediumEnergyAvailableTrigger(botAI); }
|
||||
static Trigger* HighEnergyAvailable(PlayerbotAI* botAI) { return new HighEnergyAvailableTrigger(botAI); }
|
||||
static Trigger* AlmostFullEnergyAvailable(PlayerbotAI* botAI) { return new EnergyAvailable(botAI, 90); }
|
||||
static Trigger* LootAvailable(PlayerbotAI* botAI) { return new LootAvailableTrigger(botAI); }
|
||||
static Trigger* NoAttackers(PlayerbotAI* botAI) { return new NoAttackersTrigger(botAI); }
|
||||
static Trigger* TankAssist(PlayerbotAI* botAI) { return new TankAssistTrigger(botAI); }
|
||||
@@ -314,6 +318,8 @@ private:
|
||||
{
|
||||
return new TargetWithComboPointsLowerHealTrigger(ai, 3, 3.0f);
|
||||
}
|
||||
static Trigger* ComboPointsNotFull(PlayerbotAI* botAI) { return new ComboPointsNotFullTrigger(botAI); }
|
||||
static Trigger* ComboPointsNotFullAndHighEnergy(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "combo points not full", "high energy available"); }
|
||||
static Trigger* MediumThreat(PlayerbotAI* botAI) { return new MediumThreatTrigger(botAI); }
|
||||
static Trigger* Dead(PlayerbotAI* botAI) { return new DeadTrigger(botAI); }
|
||||
static Trigger* corpse_near(PlayerbotAI* botAI) { return new CorpseNearTrigger(botAI); }
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "AiFactory.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "PlayerbotFactory.h"
|
||||
#include "Playerbots.h"
|
||||
#include "SharedDefines.h"
|
||||
|
||||
@@ -26,7 +27,7 @@ float EstimatedGroupDpsValue::Calculate()
|
||||
{
|
||||
float totalDps;
|
||||
|
||||
std::vector<Player*> groupPlayer={bot};
|
||||
std::vector<Player*> groupPlayer = {bot};
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
@@ -59,16 +60,25 @@ float EstimatedGroupDpsValue::Calculate()
|
||||
float basicDps = GetBasicDps(player->GetLevel());
|
||||
float basicGs = GetBasicGs(player->GetLevel());
|
||||
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(player, true, false, 12);
|
||||
|
||||
float gap = (float)mixedGearScore / basicGs - 1;
|
||||
float gs_modifier = gap * 3 + 1;
|
||||
float gs_modifier = (float)mixedGearScore / basicGs;
|
||||
// bonus for wotlk epic gear
|
||||
if (mixedGearScore >= 300)
|
||||
{
|
||||
gs_modifier *= 1 + (mixedGearScore - 300) * 0.01;
|
||||
}
|
||||
if (gs_modifier < 0.75)
|
||||
gs_modifier = 0.75;
|
||||
if (gs_modifier > 4)
|
||||
gs_modifier = 4;
|
||||
totalDps += basicDps * roleMultiplier * gs_modifier;
|
||||
}
|
||||
|
||||
// Group buff bonus
|
||||
if (groupPlayer.size() >= 25)
|
||||
totalDps *= 1.2;
|
||||
else if (groupPlayer.size() >= 10)
|
||||
totalDps *= 1.1;
|
||||
else if (groupPlayer.size() >= 5)
|
||||
totalDps *= 1.05;
|
||||
return totalDps;
|
||||
}
|
||||
|
||||
@@ -98,11 +108,11 @@ float EstimatedGroupDpsValue::GetBasicDps(uint32 level)
|
||||
}
|
||||
else if (level <= 70)
|
||||
{
|
||||
basic_dps = 450 + (level - 60) * 40;
|
||||
basic_dps = 550 + (level - 60) * 65;
|
||||
}
|
||||
else
|
||||
{
|
||||
basic_dps = 750 + (level - 70) * 175;
|
||||
basic_dps = 1200 + (level - 70) * 200;
|
||||
}
|
||||
return basic_dps;
|
||||
}
|
||||
@@ -113,23 +123,23 @@ float EstimatedGroupDpsValue::GetBasicGs(uint32 level)
|
||||
|
||||
if (level <= 8)
|
||||
{
|
||||
basic_gs = (level + 5) * 2;
|
||||
basic_gs = PlayerbotFactory::CalcMixedGearScore(level + 5, ITEM_QUALITY_NORMAL);
|
||||
}
|
||||
else if (level <= 15)
|
||||
{
|
||||
basic_gs = (level + 5) * 3;
|
||||
basic_gs = PlayerbotFactory::CalcMixedGearScore(level + 5, ITEM_QUALITY_UNCOMMON);
|
||||
}
|
||||
else if (level <= 60)
|
||||
{
|
||||
basic_gs = (level + 5) * 4;
|
||||
basic_gs = PlayerbotFactory::CalcMixedGearScore(level + 5, ITEM_QUALITY_RARE);
|
||||
}
|
||||
else if (level <= 70)
|
||||
{
|
||||
basic_gs = (85 + (level - 60) * 3) * 4;
|
||||
basic_gs = PlayerbotFactory::CalcMixedGearScore(85 + (level - 60) * 3, ITEM_QUALITY_RARE);
|
||||
}
|
||||
else
|
||||
{
|
||||
basic_gs = (155 + (level - 70) * 4) * 4;
|
||||
basic_gs = PlayerbotFactory::CalcMixedGearScore(155 + (level - 70) * 4, ITEM_QUALITY_RARE);
|
||||
}
|
||||
return basic_gs;
|
||||
}
|
||||
Reference in New Issue
Block a user