Improve combat reach and dps target, allowing spell interruption

This commit is contained in:
Yunfan Li
2024-09-06 12:33:54 +08:00
parent 73f699fe89
commit 927d893945
5 changed files with 60 additions and 73 deletions

View File

@@ -814,39 +814,25 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance)
float combatDistance = bot->GetCombatReach() + target->GetCombatReach();
distance += combatDistance;
if (target->HasUnitMovementFlag(MOVEMENTFLAG_FORWARD)) // target is moving forward, predict the position
{
float needToGo = bot->GetExactDist(target) - distance;
float timeToGo = MoveDelay(abs(needToGo)) + sPlayerbotAIConfig->reactDelay / 1000.0f;
float targetMoveDist = timeToGo * target->GetSpeed(MOVE_RUN);
targetMoveDist = std::min(5.0f, targetMoveDist);
tx += targetMoveDist * cos(target->GetOrientation());
ty += targetMoveDist * sin(target->GetOrientation());
if (!target->GetMap()->CheckCollisionAndGetValidCoords(target, target->GetPositionX(), target->GetPositionY(),
target->GetPositionZ(), tx, ty, tz))
{
// disable prediction if position is invalid
tx = target->GetPositionX();
ty = target->GetPositionY();
tz = target->GetPositionZ();
}
// Prediction may cause this, which makes ShortenPathUntilDist fail
if (bot->GetExactDist(tx, ty, tz) <= distance)
{
tx = target->GetPositionX();
ty = target->GetPositionY();
tz = target->GetPositionZ();
}
}
if (bot->GetExactDist(tx, ty, tz) <= distance)
return false;
PathGenerator path(bot);
path.CalculatePath(tx, ty, tz, false);
PathType type = path.GetPathType();
int typeOk = PATHFIND_NORMAL | PATHFIND_INCOMPLETE;
if (!(type & typeOk))
return false;
path.ShortenPathUntilDist(G3D::Vector3(tx, ty, tz), distance);
float shortenTo = distance;
// Avoid walking too far when moving towards each other
if (bot->GetDistance(tx, ty, tz) >= 10.0f)
shortenTo = std::max(distance, bot->GetDistance(tx, ty, tz) / 2);
if (bot->GetExactDist(tx, ty, tz) <= shortenTo)
return false;
path.ShortenPathUntilDist(G3D::Vector3(tx, ty, tz), shortenTo);
G3D::Vector3 endPos = path.GetPath().back();
return MoveTo(target->GetMapId(), endPos.x, endPos.y, endPos.z, false, false, false, false,
MovementPriority::MOVEMENT_COMBAT);

View File

@@ -29,13 +29,14 @@ bool TellAttackersAction::Execute(Event event)
botAI->TellMaster("--- Attackers ---");
GuidVector attackers = context->GetValue<GuidVector>("attackers")->Get();
int32 count = 0;
for (ObjectGuid const guid : attackers)
{
Unit* unit = botAI->GetUnit(guid);
if (!unit || !unit->IsAlive())
continue;
botAI->TellMaster(unit->GetName());
botAI->TellMaster(std::to_string(++count) + std::string(".") + unit->GetName());
}
botAI->TellMaster("--- Threat ---");

View File

@@ -50,6 +50,7 @@ public:
CasterFindTargetSmartStrategy(PlayerbotAI* botAI, float dps)
: FindTargetStrategy(botAI), dps_(dps), targetExpectedLifeTime(1000000)
{
result = nullptr;
}
void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override
@@ -86,13 +87,15 @@ public:
{
float new_time = new_unit->GetHealth() / dps_;
float old_time = old_unit->GetHealth() / dps_;
// [5-20] > (5-0] > (20-inf)
if (GetIntervalLevel(new_unit) > GetIntervalLevel(old_unit))
// [5-30] > (5-0] > (20-inf)
int new_level = GetIntervalLevel(new_unit);
int old_level = GetIntervalLevel(old_unit);
if (new_level != old_level)
{
return true;
return new_level > old_level;
}
int32_t level = GetIntervalLevel(new_unit);
if (level % 10 == 2 || level % 10 == 1)
int32_t level = new_level;
if (level % 10 == 2 || level % 10 == 0)
{
return new_time < old_time;
}
@@ -116,15 +119,15 @@ public:
botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig->spellDistance : sPlayerbotAIConfig->meleeDistance;
attackRange += 5.0f;
int level = dis < attackRange ? 10 : 0;
if (time >= 3 && time <= 20)
if (time >= 5 && time <= 30)
{
return level + 2;
}
if (time > 20)
if (time > 30)
{
return level + 1;
return level;
}
return level;
return level + 1;
}
protected:
@@ -176,12 +179,14 @@ public:
float new_time = new_unit->GetHealth() / dps_;
float old_time = old_unit->GetHealth() / dps_;
// [5-20] > (5-0] > (20-inf)
if (GetIntervalLevel(new_unit) > GetIntervalLevel(old_unit))
int new_level = GetIntervalLevel(new_unit);
int old_level = GetIntervalLevel(old_unit);
if (new_level != old_level)
{
return true;
return new_level > old_level;
}
// attack enemy in range and with lowest health
int level = GetIntervalLevel(new_unit);
int level = new_level;
if (level == 10)
{
return new_time < old_time;
@@ -249,12 +254,14 @@ public:
float new_time = new_unit->GetHealth() / dps_;
float old_time = old_unit->GetHealth() / dps_;
// [5-20] > (5-0] > (20-inf)
if (GetIntervalLevel(new_unit) > GetIntervalLevel(old_unit))
int new_level = GetIntervalLevel(new_unit);
int old_level = GetIntervalLevel(old_unit);
if (new_level != old_level)
{
return true;
return new_level > old_level;
}
// attack enemy in range and with lowest health
int level = GetIntervalLevel(new_unit);
int level = new_level;
Player* bot = botAI->GetBot();
if (level == 10)
{