mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
smarter dps target and tank target
This commit is contained in:
@@ -292,9 +292,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
|||||||
if (tab == 2)
|
if (tab == 2)
|
||||||
engine->addStrategies("tank", "tank assist", "aoe", "mark rti", nullptr);
|
engine->addStrategies("tank", "tank assist", "aoe", "mark rti", nullptr);
|
||||||
else if (player->getLevel() < 30 || tab == 0)
|
else if (player->getLevel() < 30 || tab == 0)
|
||||||
engine->addStrategies("arms", "aoe", "dps assist", "threat", "behind", nullptr);
|
engine->addStrategies("arms", "aoe", "dps assist", "threat", /*"behind",*/ nullptr);
|
||||||
else
|
else
|
||||||
engine->addStrategies("fury", "aoe", "dps assist", "threat", "behind", nullptr);
|
engine->addStrategies("fury", "aoe", "dps assist", "threat", /*"behind",*/ nullptr);
|
||||||
break;
|
break;
|
||||||
case CLASS_SHAMAN:
|
case CLASS_SHAMAN:
|
||||||
if (tab == 0)
|
if (tab == 0)
|
||||||
@@ -335,9 +335,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
|||||||
break;
|
break;
|
||||||
case CLASS_ROGUE:
|
case CLASS_ROGUE:
|
||||||
if (tab == ROGUE_TAB_ASSASSINATION) {
|
if (tab == ROGUE_TAB_ASSASSINATION) {
|
||||||
engine->addStrategies("melee", "threat", "dps assist", "aoe", "behind", nullptr);
|
engine->addStrategies("melee", "threat", "dps assist", "aoe", /*"behind",*/ nullptr);
|
||||||
} else {
|
} else {
|
||||||
engine->addStrategies("dps", "threat", "dps assist", "aoe", "behind", nullptr);
|
engine->addStrategies("dps", "threat", "dps assist", "aoe", /*"behind",*/ nullptr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CLASS_WARLOCK:
|
case CLASS_WARLOCK:
|
||||||
@@ -436,10 +436,10 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
|||||||
engine->addStrategies("caster", "caster aoe", nullptr);
|
engine->addStrategies("caster", "caster aoe", nullptr);
|
||||||
|
|
||||||
if (player->getClass() == CLASS_DRUID && tab == 1)
|
if (player->getClass() == CLASS_DRUID && tab == 1)
|
||||||
engine->addStrategies("behind", "dps", nullptr);
|
engine->addStrategies(/*"behind",*/ "dps", nullptr);
|
||||||
|
|
||||||
if (player->getClass() == CLASS_ROGUE)
|
if (player->getClass() == CLASS_ROGUE)
|
||||||
engine->addStrategies("behind", "stealth", nullptr);
|
engine->addStrategies(/*"behind",*/ "stealth", nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1399,6 +1399,19 @@ bool PlayerbotAI::IsRangedDpsAssistantOfIndex(Player* player, int index)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlayerbotAI::HasAggro(Unit* unit)
|
||||||
|
{
|
||||||
|
if (!unit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool isMT = IsMainTank(bot);
|
||||||
|
Unit* victim = unit->GetVictim();
|
||||||
|
if (victim && (victim->GetGUID() == bot->GetGUID() || (!isMT && victim->ToPlayer() && IsTank(victim->ToPlayer())))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int32 PlayerbotAI::GetGroupSlotIndex(Player* player)
|
int32 PlayerbotAI::GetGroupSlotIndex(Player* player)
|
||||||
{
|
{
|
||||||
Group* group = bot->GetGroup();
|
Group* group = bot->GetGroup();
|
||||||
|
|||||||
@@ -338,6 +338,7 @@ class PlayerbotAI : public PlayerbotAIBase
|
|||||||
bool IsAssistTankOfIndex(Player* player, int index);
|
bool IsAssistTankOfIndex(Player* player, int index);
|
||||||
bool IsHealAssistantOfIndex(Player* player, int index);
|
bool IsHealAssistantOfIndex(Player* player, int index);
|
||||||
bool IsRangedDpsAssistantOfIndex(Player* player, int index);
|
bool IsRangedDpsAssistantOfIndex(Player* player, int index);
|
||||||
|
bool HasAggro(Unit* unit);
|
||||||
int32 GetGroupSlotIndex(Player* player);
|
int32 GetGroupSlotIndex(Player* player);
|
||||||
int32 GetRangedIndex(Player* player);
|
int32 GetRangedIndex(Player* player);
|
||||||
int32 GetClassIndex(Player* player, uint8_t cls);
|
int32 GetClassIndex(Player* player, uint8_t cls);
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
|
|||||||
if (master && isRandomAccount && master->GetLevel() < bot->GetLevel()) {
|
if (master && isRandomAccount && master->GetLevel() < bot->GetLevel()) {
|
||||||
// PlayerbotFactory factory(bot, master->getLevel());
|
// PlayerbotFactory factory(bot, master->getLevel());
|
||||||
// factory.Randomize(false);
|
// factory.Randomize(false);
|
||||||
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
|
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
|
||||||
PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore);
|
PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore);
|
||||||
factory.Randomize(false);
|
factory.Randomize(false);
|
||||||
}
|
}
|
||||||
@@ -584,14 +584,13 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
|
|||||||
}
|
}
|
||||||
else if (cmd == "init=auto")
|
else if (cmd == "init=auto")
|
||||||
{
|
{
|
||||||
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
|
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
|
||||||
PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore);
|
PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore);
|
||||||
factory.Randomize(false);
|
factory.Randomize(false);
|
||||||
return "ok, gear score limit: " + std::to_string(mixedGearScore / (ITEM_QUALITY_EPIC + 1)) + "(for epic)";
|
return "ok, gear score limit: " + std::to_string(mixedGearScore / (ITEM_QUALITY_EPIC + 1)) + "(for epic)";
|
||||||
}
|
}
|
||||||
else if (cmd.starts_with("init=") && sscanf(cmd.c_str(), "init=%d", &gs) != -1)
|
else if (cmd.starts_with("init=") && sscanf(cmd.c_str(), "init=%d", &gs) != -1)
|
||||||
{
|
{
|
||||||
// uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
|
|
||||||
PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, gs);
|
PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, gs);
|
||||||
factory.Randomize(false);
|
factory.Randomize(false);
|
||||||
return "ok, gear score limit: " + std::to_string(gs / (ITEM_QUALITY_EPIC + 1)) + "(for epic)";
|
return "ok, gear score limit: " + std::to_string(gs / (ITEM_QUALITY_EPIC + 1)) + "(for epic)";
|
||||||
|
|||||||
@@ -23,20 +23,34 @@ enum StrategyType : uint32
|
|||||||
STRATEGY_TYPE_MELEE = 64
|
STRATEGY_TYPE_MELEE = 64
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ActionPriority
|
// enum ActionPriority
|
||||||
{
|
// {
|
||||||
ACTION_IDLE = 0,
|
// ACTION_IDLE = 0,
|
||||||
ACTION_NORMAL = 10,
|
// ACTION_DEFAULT = 5,
|
||||||
ACTION_HIGH = 20,
|
// ACTION_NORMAL = 10,
|
||||||
ACTION_MOVE = 30,
|
// ACTION_HIGH = 20,
|
||||||
ACTION_INTERRUPT = 40,
|
// ACTION_MOVE = 30,
|
||||||
ACTION_DISPEL = 50,
|
// ACTION_INTERRUPT = 40,
|
||||||
ACTION_RAID = 60,
|
// ACTION_DISPEL = 50,
|
||||||
ACTION_LIGHT_HEAL = 10,
|
// ACTION_RAID = 60,
|
||||||
ACTION_MEDIUM_HEAL = 20,
|
// ACTION_LIGHT_HEAL = 10,
|
||||||
ACTION_CRITICAL_HEAL = 30,
|
// ACTION_MEDIUM_HEAL = 20,
|
||||||
ACTION_EMERGENCY = 90
|
// ACTION_CRITICAL_HEAL = 30,
|
||||||
};
|
// ACTION_EMERGENCY = 90
|
||||||
|
// };
|
||||||
|
|
||||||
|
static float ACTION_IDLE = 0.0f;
|
||||||
|
static float ACTION_DEFAULT = 5.0f;
|
||||||
|
static float ACTION_NORMAL = 10.0f;
|
||||||
|
static float ACTION_HIGH = 20.0f;
|
||||||
|
static float ACTION_MOVE = 30.0f;
|
||||||
|
static float ACTION_INTERRUPT = 40.0f;
|
||||||
|
static float ACTION_DISPEL = 50.0f;
|
||||||
|
static float ACTION_RAID = 60.0f;
|
||||||
|
static float ACTION_LIGHT_HEAL = 10.0f;
|
||||||
|
static float ACTION_MEDIUM_HEAL = 20.0f;
|
||||||
|
static float ACTION_CRITICAL_HEAL = 30.0f;
|
||||||
|
static float ACTION_EMERGENCY = 90.0f;
|
||||||
|
|
||||||
class Strategy : public PlayerbotAIAware
|
class Strategy : public PlayerbotAIAware
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,15 +80,15 @@ BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
|
|||||||
NextAction** BloodDKStrategy::getDefaultActions()
|
NextAction** BloodDKStrategy::getDefaultActions()
|
||||||
{
|
{
|
||||||
return NextAction::array(0,
|
return NextAction::array(0,
|
||||||
new NextAction("rune strike", ACTION_NORMAL + 8),
|
new NextAction("rune strike", ACTION_DEFAULT + 0.8f),
|
||||||
new NextAction("icy touch", ACTION_NORMAL + 7),
|
new NextAction("icy touch", ACTION_DEFAULT + 0.7f),
|
||||||
new NextAction("heart strike", ACTION_NORMAL + 6),
|
new NextAction("heart strike", ACTION_DEFAULT + 0.6f),
|
||||||
new NextAction("blood strike", ACTION_NORMAL + 5),
|
new NextAction("blood strike", ACTION_DEFAULT + 0.5f),
|
||||||
new NextAction("dancing rune weapon", ACTION_NORMAL + 4),
|
new NextAction("dancing rune weapon", ACTION_DEFAULT + 0.4f),
|
||||||
new NextAction("death coil", ACTION_NORMAL + 3),
|
new NextAction("death coil", ACTION_DEFAULT + 0.3f),
|
||||||
new NextAction("plague strike", ACTION_NORMAL + 2),
|
new NextAction("plague strike", ACTION_DEFAULT + 0.2f),
|
||||||
new NextAction("horn of winter", ACTION_NORMAL + 1),
|
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
|
||||||
new NextAction("melee", ACTION_NORMAL),
|
new NextAction("melee", ACTION_DEFAULT),
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,12 +78,12 @@ FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
|
|||||||
NextAction** FrostDKStrategy::getDefaultActions()
|
NextAction** FrostDKStrategy::getDefaultActions()
|
||||||
{
|
{
|
||||||
return NextAction::array(0,
|
return NextAction::array(0,
|
||||||
new NextAction("obliterate", ACTION_NORMAL + 5),
|
new NextAction("obliterate", ACTION_DEFAULT + 0.5f),
|
||||||
new NextAction("frost strike", ACTION_NORMAL + 4),
|
new NextAction("frost strike", ACTION_DEFAULT + 0.4f),
|
||||||
// new NextAction("death strike", ACTION_NORMAL + 3),
|
// new NextAction("death strike", ACTION_NORMAL + 3),
|
||||||
new NextAction("empower rune weapon", ACTION_NORMAL + 2),
|
new NextAction("empower rune weapon", ACTION_DEFAULT + 0.2f),
|
||||||
new NextAction("horn of winter", ACTION_NORMAL),
|
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
|
||||||
new NextAction("melee", ACTION_NORMAL),
|
new NextAction("melee", ACTION_DEFAULT),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,15 +72,15 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI
|
|||||||
NextAction** UnholyDKStrategy::getDefaultActions()
|
NextAction** UnholyDKStrategy::getDefaultActions()
|
||||||
{
|
{
|
||||||
return NextAction::array(0,
|
return NextAction::array(0,
|
||||||
new NextAction("scourge strike", ACTION_NORMAL + 7),
|
new NextAction("scourge strike", ACTION_DEFAULT + 0.8f),
|
||||||
new NextAction("blood strike", ACTION_NORMAL + 6),
|
new NextAction("blood strike", ACTION_DEFAULT + 0.7f),
|
||||||
new NextAction("ghoul frenzy", ACTION_NORMAL + 5),
|
new NextAction("ghoul frenzy", ACTION_DEFAULT + 0.6f),
|
||||||
new NextAction("summon gargoyle", ACTION_NORMAL + 4),
|
new NextAction("summon gargoyle", ACTION_DEFAULT + 0.5f),
|
||||||
new NextAction("death coil", ACTION_NORMAL + 3),
|
new NextAction("death coil", ACTION_DEFAULT + 0.4f),
|
||||||
new NextAction("plague strike", ACTION_NORMAL + 2),
|
new NextAction("plague strike", ACTION_DEFAULT + 0.3f),
|
||||||
new NextAction("icy touch", ACTION_NORMAL + 1),
|
new NextAction("icy touch", ACTION_DEFAULT + 0.2f),
|
||||||
new NextAction("horn of winter", ACTION_NORMAL),
|
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
|
||||||
new NextAction("melee", ACTION_NORMAL),
|
new NextAction("melee", ACTION_DEFAULT),
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ void DpsHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
|
|
||||||
triggers.push_back(new TriggerNode("black arrow", NextAction::array(0, new NextAction("black arrow", 15.0f), nullptr)));
|
triggers.push_back(new TriggerNode("black arrow", NextAction::array(0, new NextAction("black arrow", 15.0f), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23.0f), nullptr)));
|
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23.0f), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 11.0f), nullptr)));
|
triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 31.0f), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("concussive shot on snare target", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr)));
|
triggers.push_back(new TriggerNode("concussive shot on snare target", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr)));
|
||||||
// triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 21.0f), NULL)));
|
// triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 21.0f), NULL)));
|
||||||
triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", 21.0f), NULL)));
|
triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", 21.0f), NULL)));
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ bool TankAssistTrigger::IsActive()
|
|||||||
if (!tankTarget || currentTarget == tankTarget)
|
if (!tankTarget || currentTarget == tankTarget)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return currentTarget->GetVictim() == AI_VALUE(Unit*, "self target");
|
return AI_VALUE2(bool, "has aggro", "current target");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsBehindTargetTrigger::IsActive()
|
bool IsBehindTargetTrigger::IsActive()
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ bool HasAggroValue::Calculate()
|
|||||||
if (!victim) {
|
if (!victim) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (victim && (victim->GetGUID() == bot->GetGUID() || (victim->ToPlayer() && botAI->IsMainTank(victim->ToPlayer())))) {
|
bool isMT = botAI->IsMainTank(bot);
|
||||||
|
if (victim && (victim->GetGUID() == bot->GetGUID() || (!isMT && victim->ToPlayer() && botAI->IsTank(victim->ToPlayer())))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -58,13 +58,70 @@ class FindMaxThreatGapTargetStrategy : public FindTargetStrategy
|
|||||||
float minThreat;
|
float minThreat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FindTargetSmartStrategy : public FindTargetStrategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FindTargetSmartStrategy(PlayerbotAI* botAI, float dps) : FindTargetStrategy(botAI), dps_(dps), targetExpectedLifeTime(1000000) { }
|
||||||
|
|
||||||
|
void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override
|
||||||
|
{
|
||||||
|
if (Group* group = botAI->GetBot()->GetGroup())
|
||||||
|
{
|
||||||
|
ObjectGuid guid = group->GetTargetIcon(4);
|
||||||
|
if (guid && attacker->GetGUID() == guid)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!attacker->IsAlive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float expectedLifeTime = attacker->GetHealth() / dps_;
|
||||||
|
// Unit* victim = attacker->GetVictim();
|
||||||
|
if (!result || IsBetter(attacker, result)) {
|
||||||
|
targetExpectedLifeTime = expectedLifeTime;
|
||||||
|
result = attacker;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool IsBetter(Unit* new_unit, Unit* old_unit) {
|
||||||
|
float new_time = new_unit->GetHealth() / dps_;
|
||||||
|
float old_time = old_unit->GetHealth() / dps_;
|
||||||
|
// [5-20] > (5-0] > (20-inf)
|
||||||
|
if (GetIntervalLevel(new_time) > GetIntervalLevel(old_time)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int32_t interval = GetIntervalLevel(new_time);
|
||||||
|
if (interval == 2 || interval == 0) {
|
||||||
|
return new_time < old_time;
|
||||||
|
}
|
||||||
|
// dont switch targets when all of them with low health
|
||||||
|
if (botAI->GetAiObjectContext()->GetValue<Unit*>("current target")->Get() == old_unit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return new_time > old_time;
|
||||||
|
}
|
||||||
|
int32_t GetIntervalLevel(float time) {
|
||||||
|
if (time >= 5 && time <= 20) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (time < 5) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float dps_;
|
||||||
|
float targetExpectedLifeTime;
|
||||||
|
};
|
||||||
|
|
||||||
Unit* DpsTargetValue::Calculate()
|
Unit* DpsTargetValue::Calculate()
|
||||||
{
|
{
|
||||||
Unit* rti = RtiTargetValue::Calculate();
|
Unit* rti = RtiTargetValue::Calculate();
|
||||||
if (rti)
|
if (rti)
|
||||||
return rti;
|
return rti;
|
||||||
|
|
||||||
FindLeastHpTargetStrategy strategy(botAI);
|
// FindLeastHpTargetStrategy strategy(botAI);
|
||||||
|
float dps = AI_VALUE(float, "expected group dps");
|
||||||
|
FindTargetSmartStrategy strategy(botAI, dps);
|
||||||
// FindMaxThreatGapTargetStrategy strategy(botAI);
|
// FindMaxThreatGapTargetStrategy strategy(botAI);
|
||||||
return TargetValue::FindTarget(&strategy);
|
return TargetValue::FindTarget(&strategy);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ float ExpectedGroupDpsValue::Calculate()
|
|||||||
float dps_num;
|
float dps_num;
|
||||||
Group* group = bot->GetGroup();
|
Group* group = bot->GetGroup();
|
||||||
if (!group) {
|
if (!group) {
|
||||||
dps_num = 1;
|
dps_num = 0.7;
|
||||||
} else {
|
} else {
|
||||||
dps_num = group->GetMembersCount() * 0.7;
|
dps_num = group->GetMembersCount() * 0.7;
|
||||||
}
|
}
|
||||||
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(bot, false, false, 12);
|
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(bot, true, false, 12);
|
||||||
// efficiency record based on rare gear level, is there better calculation method?
|
// efficiency record based on rare gear level, is there better calculation method?
|
||||||
// float dps_efficiency = 1;
|
// float dps_efficiency = 1;
|
||||||
float basic_dps;
|
float basic_dps;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AttackersValue.h"
|
#include "AttackersValue.h"
|
||||||
|
#include "PlayerbotAIConfig.h"
|
||||||
#include "TankTargetValue.h"
|
#include "TankTargetValue.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
|
||||||
@@ -41,8 +42,53 @@ class FindTargetForTankStrategy : public FindNonCcTargetStrategy
|
|||||||
float minThreat;
|
float minThreat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FindTankTargetSmartStrategy : public FindTargetStrategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FindTankTargetSmartStrategy(PlayerbotAI* botAI) : FindTargetStrategy(botAI) { }
|
||||||
|
|
||||||
|
void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override
|
||||||
|
{
|
||||||
|
if (Group* group = botAI->GetBot()->GetGroup())
|
||||||
|
{
|
||||||
|
ObjectGuid guid = group->GetTargetIcon(4);
|
||||||
|
if (guid && attacker->GetGUID() == guid)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!attacker->IsAlive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!result || IsBetter(attacker, result)) {
|
||||||
|
result = attacker;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool IsBetter(Unit* new_unit, Unit* old_unit) {
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
float new_threat = new_unit->GetThreatMgr().GetThreat(bot);
|
||||||
|
float old_threat = old_unit->GetThreatMgr().GetThreat(bot);
|
||||||
|
float new_dis = bot->GetDistance(new_unit);
|
||||||
|
float old_dis = bot->GetDistance(old_unit);
|
||||||
|
// hasAggro? -> withinMelee? -> threat
|
||||||
|
if (GetIntervalLevel(new_unit) > GetIntervalLevel(old_unit)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int32_t interval = GetIntervalLevel(new_unit);
|
||||||
|
if (interval == 1) {
|
||||||
|
return new_dis < old_dis;
|
||||||
|
}
|
||||||
|
return new_threat < old_threat;
|
||||||
|
}
|
||||||
|
int32_t GetIntervalLevel(Unit* unit) {
|
||||||
|
if (!botAI->HasAggro(unit)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Unit* TankTargetValue::Calculate()
|
Unit* TankTargetValue::Calculate()
|
||||||
{
|
{
|
||||||
FindTargetForTankStrategy strategy(botAI);
|
// FindTargetForTankStrategy strategy(botAI);
|
||||||
|
FindTankTargetSmartStrategy strategy(botAI);
|
||||||
return FindTarget(&strategy);
|
return FindTarget(&strategy);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user