mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-12-01 21:12:50 +08:00
Merge pull request #549 from liyunfan1223/combat_formation
[WIP] Tank face and dps behind
This commit is contained in:
@@ -279,11 +279,11 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
|||||||
}
|
}
|
||||||
if (sPlayerbotAIConfig->autoSaveMana)
|
if (sPlayerbotAIConfig->autoSaveMana)
|
||||||
{
|
{
|
||||||
engine->addStrategy("smana", false);
|
engine->addStrategy("save mana", false);
|
||||||
}
|
}
|
||||||
if (sPlayerbotAIConfig->autoAvoidAoe && facade->HasRealPlayerMaster())
|
if (sPlayerbotAIConfig->autoAvoidAoe && facade->HasRealPlayerMaster())
|
||||||
{
|
{
|
||||||
engine->addStrategy("aaoe", false);
|
engine->addStrategy("avoid aoe", false);
|
||||||
}
|
}
|
||||||
engine->addStrategy("formation", false);
|
engine->addStrategy("formation", false);
|
||||||
switch (player->getClass())
|
switch (player->getClass())
|
||||||
@@ -388,6 +388,12 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (PlayerbotAI::IsTank(player, true)) {
|
||||||
|
engine->addStrategy("tank face", false);
|
||||||
|
}
|
||||||
|
if (PlayerbotAI::IsMelee(player, true) && PlayerbotAI::IsDps(player, true)) {
|
||||||
|
engine->addStrategy("behind", false);
|
||||||
|
}
|
||||||
|
|
||||||
if (facade->IsRealPlayer() || sRandomPlayerbotMgr->IsRandomBot(player))
|
if (facade->IsRealPlayer() || sRandomPlayerbotMgr->IsRandomBot(player))
|
||||||
{
|
{
|
||||||
@@ -599,7 +605,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
|||||||
|
|
||||||
if (sPlayerbotAIConfig->autoSaveMana)
|
if (sPlayerbotAIConfig->autoSaveMana)
|
||||||
{
|
{
|
||||||
nonCombatEngine->addStrategy("smana", false);
|
nonCombatEngine->addStrategy("save mana", false);
|
||||||
}
|
}
|
||||||
if ((sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground())
|
if ((sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -314,6 +314,8 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal)
|
|||||||
AllowActivity();
|
AllowActivity();
|
||||||
|
|
||||||
Spell* currentSpell = bot->GetCurrentSpell(CURRENT_GENERIC_SPELL);
|
Spell* currentSpell = bot->GetCurrentSpell(CURRENT_GENERIC_SPELL);
|
||||||
|
if (!currentSpell)
|
||||||
|
currentSpell = bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
|
||||||
if (currentSpell && currentSpell->getState() == SPELL_STATE_PREPARING)
|
if (currentSpell && currentSpell->getState() == SPELL_STATE_PREPARING)
|
||||||
{
|
{
|
||||||
if (currentSpell->m_targets.GetUnitTarget() && !currentSpell->m_targets.GetUnitTarget()->IsAlive() &&
|
if (currentSpell->m_targets.GetUnitTarget() && !currentSpell->m_targets.GetUnitTarget()->IsAlive() &&
|
||||||
@@ -326,9 +328,9 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nextTransportCheck > elapsed)
|
if (nextTransportCheck > elapsed)
|
||||||
nextTransportCheck -= elapsed;
|
nextTransportCheck -= elapsed;
|
||||||
else
|
else
|
||||||
nextTransportCheck = 0;
|
nextTransportCheck = 0;
|
||||||
|
|
||||||
if (!nextTransportCheck)
|
if (!nextTransportCheck)
|
||||||
{
|
{
|
||||||
@@ -1093,7 +1095,9 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet)
|
|||||||
horizontalSpeed = 0.11f;
|
horizontalSpeed = 0.11f;
|
||||||
}
|
}
|
||||||
verticalSpeed = -verticalSpeed;
|
verticalSpeed = -verticalSpeed;
|
||||||
|
// high vertical may result in stuck as bot can not handle gravity
|
||||||
|
if (verticalSpeed > 35.0f)
|
||||||
|
break;
|
||||||
// stop casting
|
// stop casting
|
||||||
InterruptSpell();
|
InterruptSpell();
|
||||||
|
|
||||||
@@ -1102,7 +1106,7 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet)
|
|||||||
bot->GetMotionMaster()->Clear();
|
bot->GetMotionMaster()->Clear();
|
||||||
|
|
||||||
Unit* currentTarget = GetAiObjectContext()->GetValue<Unit*>("current target")->Get();
|
Unit* currentTarget = GetAiObjectContext()->GetValue<Unit*>("current target")->Get();
|
||||||
bot->GetMotionMaster()->MoveKnockbackFromForPlayer(bot->GetPositionX() + vcos, bot->GetPositionY() + vsin,
|
bot->GetMotionMaster()->MoveKnockbackFromForPlayer(bot->GetPositionX() - vcos, bot->GetPositionY() - vsin,
|
||||||
horizontalSpeed, verticalSpeed);
|
horizontalSpeed, verticalSpeed);
|
||||||
|
|
||||||
// bot->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
|
// bot->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
|
||||||
@@ -2023,7 +2027,7 @@ bool PlayerbotAI::IsDps(Player* player, bool bySpec)
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (tab == DRUID_TAB_FERAL && !IsTank(player))
|
if (tab == DRUID_TAB_FERAL && !IsTank(player, bySpec))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2088,6 +2092,25 @@ bool PlayerbotAI::IsMainTank(Player* player)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 PlayerbotAI::GetGroupTankNum(Player* player)
|
||||||
|
{
|
||||||
|
Group* group = player->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32 result = 0;
|
||||||
|
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||||
|
{
|
||||||
|
Player* member = ref->GetSource();
|
||||||
|
if (IsTank(member) && member->IsAlive())
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool PlayerbotAI::IsAssistTank(Player* player) { return IsTank(player) && !IsMainTank(player); }
|
bool PlayerbotAI::IsAssistTank(Player* player) { return IsTank(player) && !IsMainTank(player); }
|
||||||
|
|
||||||
bool PlayerbotAI::IsAssistTankOfIndex(Player* player, int index)
|
bool PlayerbotAI::IsAssistTankOfIndex(Player* player, int index)
|
||||||
|
|||||||
@@ -410,6 +410,7 @@ public:
|
|||||||
static bool IsCombo(Player* player, bool bySpec = false);
|
static bool IsCombo(Player* player, bool bySpec = false);
|
||||||
static bool IsRangedDps(Player* player, bool bySpec = false);
|
static bool IsRangedDps(Player* player, bool bySpec = false);
|
||||||
static bool IsMainTank(Player* player);
|
static bool IsMainTank(Player* player);
|
||||||
|
static uint32 GetGroupTankNum(Player* player);
|
||||||
bool IsAssistTank(Player* player);
|
bool IsAssistTank(Player* player);
|
||||||
bool IsAssistTankOfIndex(Player* player, int index);
|
bool IsAssistTankOfIndex(Player* player, int index);
|
||||||
bool IsHealAssistantOfIndex(Player* player, int index);
|
bool IsHealAssistantOfIndex(Player* player, int index);
|
||||||
|
|||||||
@@ -525,7 +525,10 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
|
|||||||
sGroupMgr->AddGroup(newGroup);
|
sGroupMgr->AddGroup(newGroup);
|
||||||
newGroup->AddMember(bot);
|
newGroup->AddMember(bot);
|
||||||
}
|
}
|
||||||
|
// if (master)
|
||||||
|
// {
|
||||||
|
// // bot->TeleportTo(master);
|
||||||
|
// }
|
||||||
uint32 accountId = bot->GetSession()->GetAccountId();
|
uint32 accountId = bot->GetSession()->GetAccountId();
|
||||||
bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(accountId);
|
bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(accountId);
|
||||||
|
|
||||||
|
|||||||
@@ -60,8 +60,7 @@ public:
|
|||||||
creators["gather"] = &StrategyContext::gather;
|
creators["gather"] = &StrategyContext::gather;
|
||||||
creators["emote"] = &StrategyContext::emote;
|
creators["emote"] = &StrategyContext::emote;
|
||||||
creators["passive"] = &StrategyContext::passive;
|
creators["passive"] = &StrategyContext::passive;
|
||||||
// creators["conserve mana"] = &StrategyContext::conserve_mana;
|
creators["save mana"] = &StrategyContext::auto_save_mana;
|
||||||
creators["smana"] = &StrategyContext::auto_save_mana;
|
|
||||||
creators["food"] = &StrategyContext::food;
|
creators["food"] = &StrategyContext::food;
|
||||||
creators["chat"] = &StrategyContext::chat;
|
creators["chat"] = &StrategyContext::chat;
|
||||||
creators["default"] = &StrategyContext::world_packet;
|
creators["default"] = &StrategyContext::world_packet;
|
||||||
@@ -113,7 +112,8 @@ public:
|
|||||||
creators["group"] = &StrategyContext::group;
|
creators["group"] = &StrategyContext::group;
|
||||||
creators["guild"] = &StrategyContext::guild;
|
creators["guild"] = &StrategyContext::guild;
|
||||||
creators["grind"] = &StrategyContext::grind;
|
creators["grind"] = &StrategyContext::grind;
|
||||||
creators["aaoe"] = &StrategyContext::avoid_aoe;
|
creators["avoid aoe"] = &StrategyContext::avoid_aoe;
|
||||||
|
creators["tank face"] = &StrategyContext::tank_face;
|
||||||
creators["move random"] = &StrategyContext::move_random;
|
creators["move random"] = &StrategyContext::move_random;
|
||||||
creators["formation"] = &StrategyContext::combat_formation;
|
creators["formation"] = &StrategyContext::combat_formation;
|
||||||
creators["move from group"] = &StrategyContext::move_from_group;
|
creators["move from group"] = &StrategyContext::move_from_group;
|
||||||
@@ -179,6 +179,7 @@ private:
|
|||||||
static Strategy* guild (PlayerbotAI* botAI) { return new GuildStrategy(botAI); }
|
static Strategy* guild (PlayerbotAI* botAI) { return new GuildStrategy(botAI); }
|
||||||
static Strategy* grind(PlayerbotAI* botAI) { return new GrindingStrategy(botAI); }
|
static Strategy* grind(PlayerbotAI* botAI) { return new GrindingStrategy(botAI); }
|
||||||
static Strategy* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeStrategy(botAI); }
|
static Strategy* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeStrategy(botAI); }
|
||||||
|
static Strategy* tank_face(PlayerbotAI* botAI) { return new TankFaceStrategy(botAI); }
|
||||||
static Strategy* move_random(PlayerbotAI* ai) { return new MoveRandomStrategy(ai); }
|
static Strategy* move_random(PlayerbotAI* ai) { return new MoveRandomStrategy(ai); }
|
||||||
static Strategy* combat_formation(PlayerbotAI* ai) { return new CombatFormationStrategy(ai); }
|
static Strategy* combat_formation(PlayerbotAI* ai) { return new CombatFormationStrategy(ai); }
|
||||||
static Strategy* move_from_group(PlayerbotAI* botAI) { return new MoveFromGroupStrategy(botAI); }
|
static Strategy* move_from_group(PlayerbotAI* botAI) { return new MoveFromGroupStrategy(botAI); }
|
||||||
|
|||||||
@@ -91,8 +91,9 @@ public:
|
|||||||
creators["reach party member to resurrect"] = &ActionContext::reach_party_member_to_resurrect;
|
creators["reach party member to resurrect"] = &ActionContext::reach_party_member_to_resurrect;
|
||||||
creators["flee"] = &ActionContext::flee;
|
creators["flee"] = &ActionContext::flee;
|
||||||
creators["flee with pet"] = &ActionContext::flee_with_pet;
|
creators["flee with pet"] = &ActionContext::flee_with_pet;
|
||||||
creators["aaoe"] = &ActionContext::avoid_aoe;
|
creators["avoid aoe"] = &ActionContext::avoid_aoe;
|
||||||
creators["combat formation move"] = &ActionContext::combat_formation_move;
|
creators["combat formation move"] = &ActionContext::combat_formation_move;
|
||||||
|
creators["tank face"] = &ActionContext::tank_face;
|
||||||
creators["disperse set"] = &ActionContext::disperse_set;
|
creators["disperse set"] = &ActionContext::disperse_set;
|
||||||
creators["gift of the naaru"] = &ActionContext::gift_of_the_naaru;
|
creators["gift of the naaru"] = &ActionContext::gift_of_the_naaru;
|
||||||
creators["shoot"] = &ActionContext::shoot;
|
creators["shoot"] = &ActionContext::shoot;
|
||||||
@@ -276,6 +277,7 @@ private:
|
|||||||
static Action* flee_with_pet(PlayerbotAI* botAI) { return new FleeWithPetAction(botAI); }
|
static Action* flee_with_pet(PlayerbotAI* botAI) { return new FleeWithPetAction(botAI); }
|
||||||
static Action* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeAction(botAI); }
|
static Action* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeAction(botAI); }
|
||||||
static Action* combat_formation_move(PlayerbotAI* botAI) { return new CombatFormationMoveAction(botAI); }
|
static Action* combat_formation_move(PlayerbotAI* botAI) { return new CombatFormationMoveAction(botAI); }
|
||||||
|
static Action* tank_face(PlayerbotAI* botAI) { return new TankFaceAction(botAI); }
|
||||||
static Action* disperse_set(PlayerbotAI* botAI) { return new DisperseSetAction(botAI); }
|
static Action* disperse_set(PlayerbotAI* botAI) { return new DisperseSetAction(botAI); }
|
||||||
static Action* gift_of_the_naaru(PlayerbotAI* botAI) { return new CastGiftOfTheNaaruAction(botAI); }
|
static Action* gift_of_the_naaru(PlayerbotAI* botAI) { return new CastGiftOfTheNaaruAction(botAI); }
|
||||||
static Action* lifeblood(PlayerbotAI* botAI) { return new CastLifeBloodAction(botAI); }
|
static Action* lifeblood(PlayerbotAI* botAI) { return new CastLifeBloodAction(botAI); }
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "ObjectDefines.h"
|
#include "ObjectDefines.h"
|
||||||
#include "ObjectGuid.h"
|
#include "ObjectGuid.h"
|
||||||
#include "PathGenerator.h"
|
#include "PathGenerator.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
#include "PlayerbotAIConfig.h"
|
#include "PlayerbotAIConfig.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "Position.h"
|
#include "Position.h"
|
||||||
@@ -202,7 +203,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
float distance = vehicleBase->GetExactDist(x, y, z); // use vehicle distance, not bot
|
float distance = vehicleBase->GetExactDist(x, y, z); // use vehicle distance, not bot
|
||||||
if (distance > sPlayerbotAIConfig->contactDistance)
|
if (distance > 0.01f)
|
||||||
{
|
{
|
||||||
MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot
|
MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot
|
||||||
mm.Clear();
|
mm.Clear();
|
||||||
@@ -217,7 +218,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
|||||||
else if (exact_waypoint || disableMoveSplinePath || !generatePath)
|
else if (exact_waypoint || disableMoveSplinePath || !generatePath)
|
||||||
{
|
{
|
||||||
float distance = bot->GetExactDist(x, y, z);
|
float distance = bot->GetExactDist(x, y, z);
|
||||||
if (distance > sPlayerbotAIConfig->contactDistance)
|
if (distance > 0.01f)
|
||||||
{
|
{
|
||||||
if (bot->IsSitState())
|
if (bot->IsSitState())
|
||||||
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
||||||
@@ -247,7 +248,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
float distance = bot->GetExactDist(x, y, modifiedZ);
|
float distance = bot->GetExactDist(x, y, modifiedZ);
|
||||||
if (distance > sPlayerbotAIConfig->contactDistance)
|
if (distance > 0.01f)
|
||||||
{
|
{
|
||||||
if (bot->IsSitState())
|
if (bot->IsSitState())
|
||||||
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
||||||
@@ -1882,16 +1883,7 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage()
|
|||||||
float radius = (float)goInfo->trap.diameter / 2 + go->GetCombatReach();
|
float radius = (float)goInfo->trap.diameter / 2 + go->GetCombatReach();
|
||||||
if (!radius || radius > sPlayerbotAIConfig->maxAoeAvoidRadius)
|
if (!radius || radius > sPlayerbotAIConfig->maxAoeAvoidRadius)
|
||||||
continue;
|
continue;
|
||||||
// for (int i = 0; i < MAX_SPELL_EFFECTS; i++) {
|
|
||||||
// if (spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) {
|
|
||||||
// if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE) {
|
|
||||||
// radius = spellInfo->Effects[i].CalcRadius();
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// } else if (spellInfo->Effects[i].Effect == SPELL_EFFECT_SCHOOL_DAMAGE) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if (bot->GetDistance(go) > radius)
|
if (bot->GetDistance(go) > radius)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -2140,7 +2132,7 @@ bool MovementAction::FleePosition(Position pos, float radius)
|
|||||||
bool MovementAction::CheckLastFlee(float curAngle, std::list<FleeInfo>& infoList)
|
bool MovementAction::CheckLastFlee(float curAngle, std::list<FleeInfo>& infoList)
|
||||||
{
|
{
|
||||||
uint32 curTS = getMSTime();
|
uint32 curTS = getMSTime();
|
||||||
curAngle = fmod(curAngle, 2 * M_PI);
|
curAngle = Position::NormalizeOrientation(curAngle);
|
||||||
while (!infoList.empty())
|
while (!infoList.empty())
|
||||||
{
|
{
|
||||||
if (infoList.size() > 10 || infoList.front().timestamp + 5000 < curTS)
|
if (infoList.size() > 10 || infoList.front().timestamp + 5000 < curTS)
|
||||||
@@ -2159,7 +2151,7 @@ bool MovementAction::CheckLastFlee(float curAngle, std::list<FleeInfo>& infoList
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
float revAngle = fmod(info.angle + M_PI, 2 * M_PI);
|
float revAngle = Position::NormalizeOrientation(info.angle + M_PI);
|
||||||
// angle too close
|
// angle too close
|
||||||
if (fabs(revAngle - curAngle) < M_PI / 4)
|
if (fabs(revAngle - curAngle) < M_PI / 4)
|
||||||
{
|
{
|
||||||
@@ -2179,13 +2171,14 @@ bool CombatFormationMoveAction::isUseful()
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
float dis = AI_VALUE(float, "disperse distance");
|
return true;
|
||||||
return dis > 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CombatFormationMoveAction::Execute(Event event)
|
bool CombatFormationMoveAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
float dis = AI_VALUE(float, "disperse distance");
|
float dis = AI_VALUE(float, "disperse distance");
|
||||||
|
if (dis <= 0.0f)
|
||||||
|
return false;
|
||||||
Player* playerToLeave = NearestGroupMember(dis);
|
Player* playerToLeave = NearestGroupMember(dis);
|
||||||
if (playerToLeave && bot->GetExactDist(playerToLeave) < dis)
|
if (playerToLeave && bot->GetExactDist(playerToLeave) < dis)
|
||||||
{
|
{
|
||||||
@@ -2197,7 +2190,7 @@ bool CombatFormationMoveAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Position CombatFormationMoveAction::AverageGroupPos(float dis)
|
Position CombatFormationMoveAction::AverageGroupPos(float dis, bool ranged, bool self)
|
||||||
{
|
{
|
||||||
float averageX = 0, averageY = 0, averageZ = 0;
|
float averageX = 0, averageY = 0, averageZ = 0;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
@@ -2210,10 +2203,19 @@ Position CombatFormationMoveAction::AverageGroupPos(float dis)
|
|||||||
for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++)
|
for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++)
|
||||||
{
|
{
|
||||||
Player* member = ObjectAccessor::FindPlayer(itr->guid);
|
Player* member = ObjectAccessor::FindPlayer(itr->guid);
|
||||||
if (!member || !member->IsAlive() || member->GetMapId() != bot->GetMapId() || member->IsCharmed() ||
|
if (!member)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!self && member == bot)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ranged && !PlayerbotAI::IsRanged(member))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!member->IsAlive() || member->GetMapId() != bot->GetMapId() || member->IsCharmed() ||
|
||||||
sServerFacade->GetDistance2d(bot, member) > dis)
|
sServerFacade->GetDistance2d(bot, member) > dis)
|
||||||
continue;
|
continue;
|
||||||
cnt++;
|
|
||||||
averageX += member->GetPositionX();
|
averageX += member->GetPositionX();
|
||||||
averageY += member->GetPositionY();
|
averageY += member->GetPositionY();
|
||||||
averageZ += member->GetPositionZ();
|
averageZ += member->GetPositionZ();
|
||||||
@@ -2224,6 +2226,59 @@ Position CombatFormationMoveAction::AverageGroupPos(float dis)
|
|||||||
return Position(averageX, averageY, averageZ);
|
return Position(averageX, averageY, averageZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CombatFormationMoveAction::AverageGroupAngle(Unit* from, bool ranged, bool self)
|
||||||
|
{
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!from || !group)
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
// float average = 0.0f;
|
||||||
|
float sumX = 0.0f;
|
||||||
|
float sumY = 0.0f;
|
||||||
|
int cnt = 0;
|
||||||
|
Group::MemberSlotList const& groupSlot = group->GetMemberSlots();
|
||||||
|
for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++)
|
||||||
|
{
|
||||||
|
Player* member = ObjectAccessor::FindPlayer(itr->guid);
|
||||||
|
if (!member)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!self && member == bot)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ranged && !PlayerbotAI::IsRanged(member))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!member->IsAlive() || member->GetMapId() != bot->GetMapId() || member->IsCharmed() ||
|
||||||
|
sServerFacade->GetDistance2d(bot, member) > sPlayerbotAIConfig->sightDistance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cnt++;
|
||||||
|
sumX += member->GetPositionX() - from->GetPositionX();
|
||||||
|
sumY += member->GetPositionY() - from->GetPositionY();
|
||||||
|
}
|
||||||
|
if (cnt == 0)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
// unnecessary division
|
||||||
|
// sumX /= cnt;
|
||||||
|
// sumY /= cnt;
|
||||||
|
|
||||||
|
return atan2(sumY, sumX);
|
||||||
|
}
|
||||||
|
|
||||||
|
Position CombatFormationMoveAction::GetNearestPosition(const std::vector<Position>& positions)
|
||||||
|
{
|
||||||
|
Position result;
|
||||||
|
for (const Position& pos : positions)
|
||||||
|
{
|
||||||
|
if (bot->GetExactDist(pos) < bot->GetExactDist(result))
|
||||||
|
result = pos;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Player* CombatFormationMoveAction::NearestGroupMember(float dis)
|
Player* CombatFormationMoveAction::NearestGroupMember(float dis)
|
||||||
{
|
{
|
||||||
float nearestDis = 10000.0f;
|
float nearestDis = 10000.0f;
|
||||||
@@ -2249,6 +2304,74 @@ Player* CombatFormationMoveAction::NearestGroupMember(float dis)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TankFaceAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Unit* target = AI_VALUE(Unit*, "current target");
|
||||||
|
if (!target)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!bot->GetGroup())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!bot->IsWithinMeleeRange(target))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!AI_VALUE2(bool, "has aggro", "current target"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float averageAngle = AverageGroupAngle(target, true);
|
||||||
|
|
||||||
|
if (averageAngle == 0.0f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float deltaAngle = Position::NormalizeOrientation(averageAngle - target->GetAngle(bot));
|
||||||
|
if (deltaAngle > M_PI)
|
||||||
|
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||||
|
|
||||||
|
float tolerable = M_PI_2;
|
||||||
|
|
||||||
|
if (fabs(deltaAngle) > tolerable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float goodAngle1 = Position::NormalizeOrientation(averageAngle + M_PI * 3 / 5);
|
||||||
|
float goodAngle2 = Position::NormalizeOrientation(averageAngle - M_PI * 3 / 5);
|
||||||
|
|
||||||
|
// if dist < bot->GetMeleeRange(target) / 2, target will move backward
|
||||||
|
float dist = std::max(bot->GetExactDist(target), bot->GetMeleeRange(target) / 2) - bot->GetCombatReach() - target->GetCombatReach();
|
||||||
|
std::vector<Position> availablePos;
|
||||||
|
float x, y, z;
|
||||||
|
target->GetNearPoint(bot, x, y, z, 0.0f, dist, goodAngle1);
|
||||||
|
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||||
|
x, y, z))
|
||||||
|
{
|
||||||
|
/// @todo: movement control now is a mess, prepare to rewrite
|
||||||
|
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
|
||||||
|
Position pos(x, y, z);
|
||||||
|
float angle = bot->GetAngle(&pos);
|
||||||
|
if (CheckLastFlee(angle, infoList))
|
||||||
|
{
|
||||||
|
availablePos.push_back(Position(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target->GetNearPoint(bot, x, y, z, 0.0f, dist, goodAngle2);
|
||||||
|
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||||
|
x, y, z))
|
||||||
|
{
|
||||||
|
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
|
||||||
|
Position pos(x, y, z);
|
||||||
|
float angle = bot->GetAngle(&pos);
|
||||||
|
if (CheckLastFlee(angle, infoList))
|
||||||
|
{
|
||||||
|
availablePos.push_back(Position(x, y, z));
|
||||||
|
}
|
||||||
|
availablePos.push_back(Position(x, y, z));
|
||||||
|
}
|
||||||
|
if (availablePos.empty())
|
||||||
|
return false;
|
||||||
|
Position nearest = GetNearestPosition(availablePos);
|
||||||
|
return MoveTo(bot->GetMapId(), nearest.GetPositionX(), nearest.GetPositionY(), nearest.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT);
|
||||||
|
}
|
||||||
|
|
||||||
bool DisperseSetAction::Execute(Event event)
|
bool DisperseSetAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
std::string const text = event.getParam();
|
std::string const text = event.getParam();
|
||||||
@@ -2388,25 +2511,58 @@ bool SetBehindTargetAction::Execute(Event event)
|
|||||||
if (!target)
|
if (!target)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float angle = GetFollowAngle() / 3 + target->GetOrientation() + M_PI;
|
if (target->GetVictim() == bot)
|
||||||
|
return false;
|
||||||
|
|
||||||
// return ChaseTo(target, 0.f, angle);
|
if (!bot->IsWithinMeleeRange(target))
|
||||||
|
return false;
|
||||||
|
|
||||||
float distance = sPlayerbotAIConfig->contactDistance;
|
float deltaAngle = Position::NormalizeOrientation(target->GetOrientation() - target->GetAngle(bot));
|
||||||
float x = target->GetPositionX() + cos(angle) * distance;
|
if (deltaAngle > M_PI)
|
||||||
float y = target->GetPositionY() + sin(angle) * distance;
|
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||||
float z = target->GetPositionZ();
|
|
||||||
bot->UpdateGroundPositionZ(x, y, z);
|
|
||||||
|
|
||||||
return MoveTo(bot->GetMapId(), x, y, z);
|
float tolerable = M_PI_2;
|
||||||
}
|
|
||||||
|
|
||||||
bool SetBehindTargetAction::isUseful() { return !AI_VALUE2(bool, "behind", "current target"); }
|
if (fabs(deltaAngle) > tolerable)
|
||||||
|
return false;
|
||||||
|
|
||||||
bool SetBehindTargetAction::isPossible()
|
float goodAngle1 = Position::NormalizeOrientation(target->GetOrientation() + M_PI * 3 / 5);
|
||||||
{
|
float goodAngle2 = Position::NormalizeOrientation(target->GetOrientation() - M_PI * 3 / 5);
|
||||||
Unit* target = AI_VALUE(Unit*, "current target");
|
|
||||||
return target && !(target->GetVictim() && target->GetVictim()->GetGUID() == bot->GetGUID());
|
float dist = std::max(bot->GetExactDist(target), bot->GetMeleeRange(target) / 2) - bot->GetCombatReach() - target->GetCombatReach();
|
||||||
|
std::vector<Position> availablePos;
|
||||||
|
float x, y, z;
|
||||||
|
target->GetNearPoint(bot, x, y, z, 0.0f, dist, goodAngle1);
|
||||||
|
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||||
|
x, y, z))
|
||||||
|
{
|
||||||
|
/// @todo: movement control now is a mess, prepare to rewrite
|
||||||
|
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
|
||||||
|
Position pos(x, y, z);
|
||||||
|
float angle = bot->GetAngle(&pos);
|
||||||
|
if (CheckLastFlee(angle, infoList))
|
||||||
|
{
|
||||||
|
availablePos.push_back(Position(x, y, z));
|
||||||
|
}
|
||||||
|
availablePos.push_back(Position(x, y, z));
|
||||||
|
}
|
||||||
|
target->GetNearPoint(bot, x, y, z, 0.0f, dist, goodAngle2);
|
||||||
|
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||||
|
x, y, z))
|
||||||
|
{
|
||||||
|
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
|
||||||
|
Position pos(x, y, z);
|
||||||
|
float angle = bot->GetAngle(&pos);
|
||||||
|
if (CheckLastFlee(angle, infoList))
|
||||||
|
{
|
||||||
|
availablePos.push_back(Position(x, y, z));
|
||||||
|
}
|
||||||
|
availablePos.push_back(Position(x, y, z));
|
||||||
|
}
|
||||||
|
if (availablePos.empty())
|
||||||
|
return false;
|
||||||
|
Position nearest = GetNearestPosition(availablePos);
|
||||||
|
return MoveTo(bot->GetMapId(), nearest.GetPositionX(), nearest.GetPositionY(), nearest.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MoveOutOfCollisionAction::Execute(Event event)
|
bool MoveOutOfCollisionAction::Execute(Event event)
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ class AvoidAoeAction : public MovementAction
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AvoidAoeAction(PlayerbotAI* botAI, int moveInterval = 1000)
|
AvoidAoeAction(PlayerbotAI* botAI, int moveInterval = 1000)
|
||||||
: MovementAction(botAI, "aaoe"), moveInterval(moveInterval)
|
: MovementAction(botAI, "avoid aoe"), moveInterval(moveInterval)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,11 +115,12 @@ protected:
|
|||||||
int moveInterval;
|
int moveInterval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CombatFormationMoveAction : public MovementAction
|
class CombatFormationMoveAction : public MovementAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CombatFormationMoveAction(PlayerbotAI* botAI, int moveInterval = 1000)
|
CombatFormationMoveAction(PlayerbotAI* botAI, std::string name = "combat formation move", int moveInterval = 1000)
|
||||||
: MovementAction(botAI, "combat formation move"), moveInterval(moveInterval)
|
: MovementAction(botAI, name), moveInterval(moveInterval)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,12 +128,22 @@ public:
|
|||||||
bool Execute(Event event) override;
|
bool Execute(Event event) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Position AverageGroupPos(float dis = sPlayerbotAIConfig->sightDistance);
|
Position AverageGroupPos(float dis = sPlayerbotAIConfig->sightDistance, bool ranged = false, bool self = false);
|
||||||
Player* NearestGroupMember(float dis = sPlayerbotAIConfig->sightDistance);
|
Player* NearestGroupMember(float dis = sPlayerbotAIConfig->sightDistance);
|
||||||
|
float AverageGroupAngle(Unit* from, bool ranged = false, bool self = false);
|
||||||
|
Position GetNearestPosition(const std::vector<Position>& positions);
|
||||||
int lastMoveTimer = 0;
|
int lastMoveTimer = 0;
|
||||||
int moveInterval;
|
int moveInterval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TankFaceAction : public CombatFormationMoveAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TankFaceAction(PlayerbotAI* botAI) : CombatFormationMoveAction(botAI, "tank face") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
class DisperseSetAction : public Action
|
class DisperseSetAction : public Action
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -178,14 +189,12 @@ public:
|
|||||||
bool isPossible() override;
|
bool isPossible() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SetBehindTargetAction : public MovementAction
|
class SetBehindTargetAction : public CombatFormationMoveAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetBehindTargetAction(PlayerbotAI* botAI) : MovementAction(botAI, "set behind") {}
|
SetBehindTargetAction(PlayerbotAI* botAI) : CombatFormationMoveAction(botAI, "set behind") {}
|
||||||
|
|
||||||
bool Execute(Event event) override;
|
bool Execute(Event event) override;
|
||||||
bool isUseful() override;
|
|
||||||
bool isPossible() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MoveOutOfCollisionAction : public MovementAction
|
class MoveOutOfCollisionAction : public MovementAction
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ AvoidAoeStrategy::AvoidAoeStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
|||||||
|
|
||||||
NextAction** AvoidAoeStrategy::getDefaultActions()
|
NextAction** AvoidAoeStrategy::getDefaultActions()
|
||||||
{
|
{
|
||||||
return NextAction::array(0, new NextAction("aaoe", ACTION_EMERGENCY), nullptr);
|
return NextAction::array(0, new NextAction("avoid aoe", ACTION_EMERGENCY), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvoidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void AvoidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
@@ -85,6 +85,17 @@ void AvoidAoeStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
|||||||
// multipliers.push_back(new AvoidAoeStrategyMultiplier(botAI));
|
// multipliers.push_back(new AvoidAoeStrategyMultiplier(botAI));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TankFaceStrategy::TankFaceStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||||
|
|
||||||
|
NextAction** TankFaceStrategy::getDefaultActions()
|
||||||
|
{
|
||||||
|
return NextAction::array(0, new NextAction("tank face", ACTION_MOVE), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TankFaceStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
NextAction** CombatFormationStrategy::getDefaultActions()
|
NextAction** CombatFormationStrategy::getDefaultActions()
|
||||||
{
|
{
|
||||||
return NextAction::array(0, new NextAction("combat formation move", ACTION_NORMAL), nullptr);
|
return NextAction::array(0, new NextAction("combat formation move", ACTION_NORMAL), nullptr);
|
||||||
|
|||||||
@@ -23,12 +23,21 @@ class AvoidAoeStrategy : public Strategy
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AvoidAoeStrategy(PlayerbotAI* ai);
|
explicit AvoidAoeStrategy(PlayerbotAI* ai);
|
||||||
const std::string getName() override { return "aaoe"; }
|
const std::string getName() override { return "avoid aoe"; }
|
||||||
NextAction** getDefaultActions() override;
|
NextAction** getDefaultActions() override;
|
||||||
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
||||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TankFaceStrategy : public Strategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TankFaceStrategy(PlayerbotAI* ai);
|
||||||
|
const std::string getName() override { return "tank face"; }
|
||||||
|
NextAction** getDefaultActions() override;
|
||||||
|
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||||
|
};
|
||||||
|
|
||||||
class CombatFormationStrategy : public Strategy
|
class CombatFormationStrategy : public Strategy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -10,46 +10,10 @@
|
|||||||
|
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
|
|
||||||
// Yunfan: deprecate old save mana method.
|
|
||||||
|
|
||||||
// class ConserveManaMultiplier : public Multiplier
|
|
||||||
// {
|
|
||||||
// public:
|
|
||||||
// ConserveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "conserve mana") { }
|
|
||||||
|
|
||||||
// float GetValue(Action* action) override;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// class SaveManaMultiplier : public Multiplier
|
|
||||||
// {
|
|
||||||
// public:
|
|
||||||
// SaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "save mana") { }
|
|
||||||
|
|
||||||
// float GetValue(Action* action) override;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// class ConserveManaStrategy : public Strategy
|
|
||||||
// {
|
|
||||||
// public:
|
|
||||||
// ConserveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) { }
|
|
||||||
|
|
||||||
// void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
|
||||||
// std::string const getName() override { return "conserve mana"; }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// class HealerSaveManaStrategy : public Strategy
|
|
||||||
// {
|
|
||||||
// public:
|
|
||||||
// HealerSaveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) { }
|
|
||||||
|
|
||||||
// void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
|
||||||
// std::string const getName() override { return "healer save mana"; }
|
|
||||||
// };
|
|
||||||
|
|
||||||
class HealerAutoSaveManaMultiplier : public Multiplier
|
class HealerAutoSaveManaMultiplier : public Multiplier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HealerAutoSaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "smana") {}
|
HealerAutoSaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "save mana") {}
|
||||||
|
|
||||||
float GetValue(Action* action) override;
|
float GetValue(Action* action) override;
|
||||||
};
|
};
|
||||||
@@ -60,7 +24,7 @@ public:
|
|||||||
HealerAutoSaveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
HealerAutoSaveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||||
|
|
||||||
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
||||||
std::string const getName() override { return "smana"; }
|
std::string const getName() override { return "save mana"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ float GrobbulusMultiplier::GetValue(Action* action)
|
|||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
if (dynamic_cast<AvoidAoeAction*>(action))
|
if (dynamic_cast<AvoidAoeAction*>(action) || dynamic_cast<CombatFormationMoveAction*>(action))
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ float HeiganDanceMultiplier::GetValue(Action* action)
|
|||||||
uint32 curr_dance = eventMap->GetNextEventTime(4);
|
uint32 curr_dance = eventMap->GetNextEventTime(4);
|
||||||
uint32 curr_timer = eventMap->GetTimer();
|
uint32 curr_timer = eventMap->GetTimer();
|
||||||
uint32 curr_erupt = eventMap->GetNextEventTime(3);
|
uint32 curr_erupt = eventMap->GetNextEventTime(3);
|
||||||
if (dynamic_cast<SetBehindTargetAction*>(action))
|
if (dynamic_cast<CombatFormationMoveAction*>(action))
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,8 @@ float LoathebGenericMultiplier::GetValue(Action* action)
|
|||||||
context->GetValue<bool>("neglect threat")->Set(true);
|
context->GetValue<bool>("neglect threat")->Set(true);
|
||||||
if (botAI->GetState() == BOT_STATE_COMBAT &&
|
if (botAI->GetState() == BOT_STATE_COMBAT &&
|
||||||
(dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
(dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
||||||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) || dynamic_cast<FleeAction*>(action)))
|
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) || dynamic_cast<FleeAction*>(action) ||
|
||||||
|
dynamic_cast<CombatFormationMoveAction*>(action)))
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,8 @@ float ThaddiusGenericMultiplier::GetValue(Action* action)
|
|||||||
if (helper.IsPhasePet() &&
|
if (helper.IsPhasePet() &&
|
||||||
(dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
(dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
|
||||||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
|
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
|
||||||
dynamic_cast<ReachPartyMemberToHealAction*>(action) || dynamic_cast<BuffOnMainTankAction*>(action)))
|
dynamic_cast<ReachPartyMemberToHealAction*>(action) || dynamic_cast<BuffOnMainTankAction*>(action) ||
|
||||||
|
dynamic_cast<CombatFormationMoveAction*>(action)))
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
@@ -151,7 +153,8 @@ float SapphironGenericMultiplier::GetValue(Action* action)
|
|||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
if (dynamic_cast<FollowAction*>(action) || dynamic_cast<CastDeathGripAction*>(action))
|
if (dynamic_cast<FollowAction*>(action) || dynamic_cast<CastDeathGripAction*>(action) ||
|
||||||
|
dynamic_cast<CombatFormationMoveAction*>(action))
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "IsBehindValue.h"
|
#include "IsBehindValue.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
|
||||||
@@ -14,8 +15,10 @@ bool IsBehindValue::Calculate()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
float targetOrientation = target->GetOrientation();
|
float targetOrientation = target->GetOrientation();
|
||||||
float orientation = bot->GetOrientation();
|
|
||||||
float distance = bot->GetDistance(target);
|
|
||||||
|
|
||||||
return distance <= ATTACK_DISTANCE && abs(targetOrientation - orientation) < M_PI / 2;
|
float deltaAngle = Position::NormalizeOrientation(targetOrientation - target->GetAngle(bot));
|
||||||
|
if (deltaAngle > M_PI)
|
||||||
|
deltaAngle -= 2.0f * M_PI; // -PI..PI
|
||||||
|
|
||||||
|
return fabs(deltaAngle) > M_PI_2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "IsFacingValue.h"
|
#include "IsFacingValue.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
|
||||||
@@ -13,5 +14,5 @@ bool IsFacingValue::Calculate()
|
|||||||
if (!target)
|
if (!target)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return bot->HasInArc(CAST_ANGLE_IN_FRONT, target);
|
return bot->HasInArc(M_PI_2, target);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "RtiTargetValue.h"
|
#include "RtiTargetValue.h"
|
||||||
|
|
||||||
|
#include "AttackersValue.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "ServerFacade.h"
|
#include "ServerFacade.h"
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ Unit* RtiTargetValue::Calculate()
|
|||||||
//////////////////////////////////////////////////////end: delete below check
|
//////////////////////////////////////////////////////end: delete below check
|
||||||
|
|
||||||
Unit* unit = botAI->GetUnit(guid);
|
Unit* unit = botAI->GetUnit(guid);
|
||||||
if (!unit || unit->isDead() || !bot->IsWithinLOSInMap(unit) ||
|
if (!unit || unit->isDead() || !bot->IsWithinLOSInMap(unit) || !AttackersValue::IsValidTarget(unit, bot) ||
|
||||||
sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, unit),
|
sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, unit),
|
||||||
sPlayerbotAIConfig->sightDistance))
|
sPlayerbotAIConfig->sightDistance))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -73,6 +73,15 @@ public:
|
|||||||
bool IsBetter(Unit* new_unit, Unit* old_unit)
|
bool IsBetter(Unit* new_unit, Unit* old_unit)
|
||||||
{
|
{
|
||||||
Player* bot = botAI->GetBot();
|
Player* bot = botAI->GetBot();
|
||||||
|
// if group has multiple tanks, main tank just focus on the current target
|
||||||
|
Unit* currentTarget = botAI->GetAiObjectContext()->GetValue<Unit*>("current target")->Get();
|
||||||
|
if (currentTarget && botAI->IsMainTank(bot) && botAI->GetGroupTankNum(bot) > 1)
|
||||||
|
{
|
||||||
|
if (old_unit == currentTarget)
|
||||||
|
return false;
|
||||||
|
if (new_unit == currentTarget)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
float new_threat = new_unit->GetThreatMgr().GetThreat(bot);
|
float new_threat = new_unit->GetThreatMgr().GetThreat(bot);
|
||||||
float old_threat = old_unit->GetThreatMgr().GetThreat(bot);
|
float old_threat = old_unit->GetThreatMgr().GetThreat(bot);
|
||||||
float new_dis = bot->GetDistance(new_unit);
|
float new_dis = bot->GetDistance(new_unit);
|
||||||
|
|||||||
Reference in New Issue
Block a user