smarter dps target and tank target

This commit is contained in:
Yunfan Li
2023-10-22 01:27:37 +08:00
parent f303a9e83a
commit a63c6b6709
14 changed files with 184 additions and 53 deletions

View File

@@ -21,7 +21,8 @@ bool HasAggroValue::Calculate()
if (!victim) {
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 false;

View File

@@ -58,13 +58,70 @@ class FindMaxThreatGapTargetStrategy : public FindTargetStrategy
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* rti = RtiTargetValue::Calculate();
if (rti)
return rti;
FindLeastHpTargetStrategy strategy(botAI);
// FindLeastHpTargetStrategy strategy(botAI);
float dps = AI_VALUE(float, "expected group dps");
FindTargetSmartStrategy strategy(botAI, dps);
// FindMaxThreatGapTargetStrategy strategy(botAI);
return TargetValue::FindTarget(&strategy);
}

View File

@@ -21,11 +21,11 @@ float ExpectedGroupDpsValue::Calculate()
float dps_num;
Group* group = bot->GetGroup();
if (!group) {
dps_num = 1;
dps_num = 0.7;
} else {
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?
// float dps_efficiency = 1;
float basic_dps;

View File

@@ -3,6 +3,7 @@
*/
#include "AttackersValue.h"
#include "PlayerbotAIConfig.h"
#include "TankTargetValue.h"
#include "Playerbots.h"
@@ -41,8 +42,53 @@ class FindTargetForTankStrategy : public FindNonCcTargetStrategy
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()
{
FindTargetForTankStrategy strategy(botAI);
// FindTargetForTankStrategy strategy(botAI);
FindTankTargetSmartStrategy strategy(botAI);
return FindTarget(&strategy);
}