diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 88cffdce..77c00a10 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -125,7 +125,7 @@ AiPlayerbot.MinEnchantingBotLevel = 60 AiPlayerbot.LimitEnchantExpansion = 1 # Randombots checking players gear score level and deny the group invite if it's too low -# Default: 1 (enabled) +# Default: 0 (disabled) AiPlayerbot.GearScoreCheck = 0 # Quest that will be completed and rewarded to all random bots diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 7ab12027..9eb05039 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1645,16 +1645,23 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura() return false; } -bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name) +Position AvoidAoeAction::BestPositionForMelee(Position pos, float radius) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); std::vector possibleAngles; if (currentTarget) { // Normally, move to left or right is the best position - float angleLeft = bot->GetAngle(currentTarget) + M_PI / 2; - float angleRight = bot->GetAngle(currentTarget) - M_PI / 2; + bool isTanking = (currentTarget->CanFreeMove()) && (currentTarget->GetVictim() == bot); + float angle = bot->GetAngle(currentTarget); + float angleLeft = angle + M_PI / 2; + float angleRight = angle - M_PI / 2; possibleAngles.push_back(angleLeft); possibleAngles.push_back(angleRight); + if (isTanking) { + possibleAngles.push_back(angle + M_PI); + possibleAngles.push_back(angle); + possibleAngles.push_back(bot->GetAngle(&pos) - M_PI); + } } else { float angleTo = bot->GetAngle(&pos) - M_PI; possibleAngles.push_back(angleTo); @@ -1673,6 +1680,67 @@ bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name) } } if (farestDis > 0.0f) { + return bestPos; + } + return Position(); +} + +Position AvoidAoeAction::BestPositionForRanged(Position pos, float radius) +{ + Unit* currentTarget = AI_VALUE(Unit*, "current target"); + std::vector possibleAngles; + float angleToTarget = 0.0f; + float angleFleeFromCenter = bot->GetAngle(&pos) - M_PI; + if (currentTarget) { + // Normally, move to left or right is the best position + angleToTarget = bot->GetAngle(currentTarget); + float angleLeft = angleToTarget + M_PI / 2; + float angleRight = angleToTarget - M_PI / 2; + possibleAngles.push_back(angleLeft); + possibleAngles.push_back(angleRight); + possibleAngles.push_back(angleToTarget + M_PI); + possibleAngles.push_back(angleToTarget); + possibleAngles.push_back(angleFleeFromCenter); + } else { + possibleAngles.push_back(angleFleeFromCenter); + } + float farestDis = 0.0f; + Position bestPos; + for (float &angle : possibleAngles) { + float fleeDis = sPlayerbotAIConfig->fleeDistance; + Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis, + bot->GetPositionY() + sin(angle) * fleeDis, + bot->GetPositionZ()}; + // backward, flee + if (currentTarget && (angle == angleToTarget + M_PI || angle == angleFleeFromCenter) + && fleePos.GetExactDist(currentTarget) > sPlayerbotAIConfig->spellDistance) { + continue; + } + // forward, flee + if (currentTarget && (angle == angleToTarget || angle == angleFleeFromCenter) + && fleePos.GetExactDist(currentTarget) < (sPlayerbotAIConfig->tooCloseDistance + 5.0f)) { + continue; + } + if (pos.GetExactDist(fleePos) > farestDis) { + farestDis = pos.GetExactDist(fleePos); + bestPos = fleePos; + } + } + if (farestDis > 0.0f) { + return bestPos; + } + return Position(); +} + +bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name) +{ + Position bestPos; + if (botAI->IsMelee(bot)) { + bestPos = BestPositionForMelee(pos, radius); + } else if (botAI->IsRanged(bot)) { + bestPos = BestPositionForRanged(pos, radius); + } + if (bestPos != Position()) { if (MoveTo(bot->GetMapId(), bestPos.GetPositionX(), bestPos.GetPositionY(), bestPos.GetPositionZ(), false, false, true)) { if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) { lastTellTimer = time(NULL); diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index c53bf25e..3cfdc685 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -78,9 +78,8 @@ class AvoidAoeAction : public MovementAction bool AvoidAuraWithDynamicObj(); bool AvoidGameObjectWithDamage(); bool AvoidUnitWithDamageAura(); - // Position PositionForTank(Position pos, float radius); - // Position PositionForMelee(Position pos, float radius); - // Position PositionForRanged(Position pos, float radius); + Position BestPositionForMelee(Position pos, float radius); + Position BestPositionForRanged(Position pos, float radius); bool FleePosition(Position pos, float radius, std::string name); time_t lastTellTimer = 0; };