mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-13 00:58:33 +00:00
@@ -292,9 +292,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
if (tab == 2)
|
||||
engine->addStrategies("tank", "tank assist", "aoe", "mark rti", nullptr);
|
||||
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
|
||||
engine->addStrategies("fury", "aoe", "dps assist", "threat", "behind", nullptr);
|
||||
engine->addStrategies("fury", "aoe", "dps assist", "threat", /*"behind",*/ nullptr);
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
if (tab == 0)
|
||||
@@ -302,7 +302,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
else if (tab == 2)
|
||||
engine->addStrategies("heal", "bmana", nullptr);
|
||||
else
|
||||
engine->addStrategies("melee", "melee aoe", "bmana", "threat", nullptr);
|
||||
engine->addStrategies("melee", "melee aoe", "bdps", "threat", nullptr);
|
||||
|
||||
engine->addStrategies("dps assist", "cure", "totems", nullptr);
|
||||
break;
|
||||
@@ -335,9 +335,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
break;
|
||||
case CLASS_ROGUE:
|
||||
if (tab == ROGUE_TAB_ASSASSINATION) {
|
||||
engine->addStrategies("melee", "threat", "dps assist", "aoe", "behind", nullptr);
|
||||
engine->addStrategies("melee", "threat", "dps assist", "aoe", /*"behind",*/ nullptr);
|
||||
} else {
|
||||
engine->addStrategies("dps", "threat", "dps assist", "aoe", "behind", nullptr);
|
||||
engine->addStrategies("dps", "threat", "dps assist", "aoe", /*"behind",*/ nullptr);
|
||||
}
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
@@ -436,10 +436,10 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
engine->addStrategies("caster", "caster aoe", nullptr);
|
||||
|
||||
if (player->getClass() == CLASS_DRUID && tab == 1)
|
||||
engine->addStrategies("behind", "dps", nullptr);
|
||||
engine->addStrategies(/*"behind",*/ "dps", nullptr);
|
||||
|
||||
if (player->getClass() == CLASS_ROGUE)
|
||||
engine->addStrategies("behind", "stealth", nullptr);
|
||||
engine->addStrategies(/*"behind",*/ "stealth", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,10 +473,10 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
||||
nonCombatEngine->addStrategies("bdps", "dps assist", "pet", nullptr);
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
// if (tab == 0 || tab == 2)
|
||||
nonCombatEngine->addStrategy("bmana");
|
||||
// else
|
||||
// nonCombatEngine->addStrategy("bdps");
|
||||
if (tab == 0 || tab == 2)
|
||||
nonCombatEngine->addStrategy("bmana");
|
||||
else
|
||||
nonCombatEngine->addStrategy("bdps");
|
||||
|
||||
nonCombatEngine->addStrategies("dps assist", "cure", nullptr);
|
||||
break;
|
||||
|
||||
@@ -1399,6 +1399,19 @@ bool PlayerbotAI::IsRangedDpsAssistantOfIndex(Player* player, int index)
|
||||
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)
|
||||
{
|
||||
Group* group = bot->GetGroup();
|
||||
|
||||
@@ -338,6 +338,7 @@ class PlayerbotAI : public PlayerbotAIBase
|
||||
bool IsAssistTankOfIndex(Player* player, int index);
|
||||
bool IsHealAssistantOfIndex(Player* player, int index);
|
||||
bool IsRangedDpsAssistantOfIndex(Player* player, int index);
|
||||
bool HasAggro(Unit* unit);
|
||||
int32 GetGroupSlotIndex(Player* player);
|
||||
int32 GetRangedIndex(Player* player);
|
||||
int32 GetClassIndex(Player* player, uint8_t cls);
|
||||
|
||||
@@ -1335,7 +1335,7 @@ void PlayerbotFactory::InitEquipment(bool incremental)
|
||||
|
||||
float bestScoreForSlot = -1;
|
||||
uint32 bestItemForSlot = 0;
|
||||
for (int attempts = 0; attempts < std::min((int)ids.size(), 25); attempts++)
|
||||
for (int attempts = 0; attempts < std::max((int)(ids.size() * 0.75), 1); attempts++)
|
||||
{
|
||||
uint32 index = urand(0, ids.size() - 1);
|
||||
uint32 newItemId = ids[index];
|
||||
|
||||
@@ -443,7 +443,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
|
||||
if (master && isRandomAccount && master->GetLevel() < bot->GetLevel()) {
|
||||
// PlayerbotFactory factory(bot, master->getLevel());
|
||||
// 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);
|
||||
factory.Randomize(false);
|
||||
}
|
||||
@@ -584,14 +584,13 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
|
||||
}
|
||||
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);
|
||||
factory.Randomize(false);
|
||||
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)
|
||||
{
|
||||
// uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
|
||||
PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, gs);
|
||||
factory.Randomize(false);
|
||||
return "ok, gear score limit: " + std::to_string(gs / (ITEM_QUALITY_EPIC + 1)) + "(for epic)";
|
||||
|
||||
@@ -206,11 +206,11 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls
|
||||
player->setCinematic(2);
|
||||
player->SetAtLoginFlag(AT_LOGIN_NONE);
|
||||
|
||||
player->SaveToDB(true, false);
|
||||
if (player->getClass() == CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
player->learnSpell(50977, false);
|
||||
}
|
||||
// player->SaveToDB(true, false);
|
||||
// player->RewardQuest(const Quest *quest, uint32 reward, Object *questGiver)
|
||||
LOG_DEBUG("playerbots", "Random bot created for account {} - name: \"{}\"; race: {}; class: {}", accountId, name.c_str(), race, cls);
|
||||
|
||||
@@ -274,12 +274,14 @@ void RandomPlayerbotFactory::CreateRandomBots()
|
||||
|
||||
LOG_INFO("playerbots", "Deleting all random bot characters, {} accounts collected...", botAccounts.size());
|
||||
QueryResult results = LoginDatabase.Query("SELECT id FROM account WHERE username LIKE '{}%%'", sPlayerbotAIConfig->randomBotAccountPrefix.c_str());
|
||||
int32 deletion_count = 0;
|
||||
if (results)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = results->Fetch();
|
||||
uint32 accId = fields[0].Get<uint32>();
|
||||
LOG_INFO("playerbots", "Deleting account accID: {}({})...", accId, ++deletion_count);
|
||||
AccountMgr::DeleteAccount(accId);
|
||||
} while (results->NextRow());
|
||||
}
|
||||
@@ -288,8 +290,11 @@ void RandomPlayerbotFactory::CreateRandomBots()
|
||||
CharacterDatabase.Execute("UPDATE playerbots_names SET in_use=0 WHERE in_use=1");
|
||||
/* TODO(yunfan): we need to sleep here to wait for async account deleted, or the newly account won't be created correctly
|
||||
the better way is turning the async db operation to sync db operation */
|
||||
std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount);
|
||||
LOG_INFO("playerbots", "Random bot characters deleted");
|
||||
std::this_thread::sleep_for(100ms * sPlayerbotAIConfig->randomBotAccountCount);
|
||||
LOG_INFO("playerbots", "Random bot characters deleted.");
|
||||
LOG_INFO("playerbots", "Please reset the AiPlayerbot.DeleteRandomBotAccounts to 0 and restart the server...");
|
||||
World::StopNow(SHUTDOWN_EXIT_CODE);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 totalAccCount = sPlayerbotAIConfig->randomBotAccountCount;
|
||||
@@ -330,7 +335,7 @@ void RandomPlayerbotFactory::CreateRandomBots()
|
||||
|
||||
if (account_creation) {
|
||||
/* wait for async accounts create to make character create correctly, same as account delete */
|
||||
std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount);
|
||||
std::this_thread::sleep_for(100ms * sPlayerbotAIConfig->randomBotAccountCount);
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Creating random bot characters...");
|
||||
|
||||
@@ -146,7 +146,8 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
|
||||
time_t currentTime = time(nullptr);
|
||||
aiObjectContext->Update();
|
||||
ProcessTriggers(minimal);
|
||||
|
||||
PushDefaultActions();
|
||||
|
||||
uint32 iterations = 0;
|
||||
uint32 iterationsPerTick = queue.Size() * (minimal ? 2 : sPlayerbotAIConfig->iterationsPerTick);
|
||||
do
|
||||
@@ -265,15 +266,15 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
|
||||
}
|
||||
while (basket && ++iterations <= iterationsPerTick);
|
||||
|
||||
if (!basket)
|
||||
{
|
||||
lastRelevance = 0.0f;
|
||||
PushDefaultActions();
|
||||
// if (!basket)
|
||||
// {
|
||||
// lastRelevance = 0.0f;
|
||||
// PushDefaultActions();
|
||||
|
||||
// prevent the delay after pushing default actions
|
||||
if (queue.Peek() && depth < 1 && !minimal)
|
||||
return DoNextAction(unit, depth + 1, minimal);
|
||||
}
|
||||
// // prevent the delay after pushing default actions
|
||||
// if (queue.Peek() && depth < 1 && !minimal)
|
||||
// return DoNextAction(unit, depth + 1, minimal);
|
||||
// }
|
||||
|
||||
// MEMORY FIX TEST
|
||||
/*
|
||||
|
||||
@@ -23,20 +23,34 @@ enum StrategyType : uint32
|
||||
STRATEGY_TYPE_MELEE = 64
|
||||
};
|
||||
|
||||
enum ActionPriority
|
||||
{
|
||||
ACTION_IDLE = 0,
|
||||
ACTION_NORMAL = 10,
|
||||
ACTION_HIGH = 20,
|
||||
ACTION_MOVE = 30,
|
||||
ACTION_INTERRUPT = 40,
|
||||
ACTION_DISPEL = 50,
|
||||
ACTION_RAID = 60,
|
||||
ACTION_LIGHT_HEAL = 10,
|
||||
ACTION_MEDIUM_HEAL = 20,
|
||||
ACTION_CRITICAL_HEAL = 30,
|
||||
ACTION_EMERGENCY = 90
|
||||
};
|
||||
// enum ActionPriority
|
||||
// {
|
||||
// ACTION_IDLE = 0,
|
||||
// ACTION_DEFAULT = 5,
|
||||
// ACTION_NORMAL = 10,
|
||||
// ACTION_HIGH = 20,
|
||||
// ACTION_MOVE = 30,
|
||||
// ACTION_INTERRUPT = 40,
|
||||
// ACTION_DISPEL = 50,
|
||||
// ACTION_RAID = 60,
|
||||
// ACTION_LIGHT_HEAL = 10,
|
||||
// ACTION_MEDIUM_HEAL = 20,
|
||||
// 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
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "ObjectGuid.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Random.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TargetedMovementGenerator.h"
|
||||
#include "Event.h"
|
||||
@@ -132,7 +133,7 @@ bool MovementAction::MoveToLOS(WorldObject* target, bool ranged)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react)
|
||||
bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react, bool normal_only)
|
||||
{
|
||||
UpdateMovementState();
|
||||
if (!IsMovingAllowed(mapId, x, y, z)) {
|
||||
@@ -166,7 +167,11 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
MotionMaster &mm = *bot->GetMotionMaster();
|
||||
|
||||
mm.Clear();
|
||||
mm.MovePoint(mapId, x, y, SearchBestGroundZForPath(x, y, z, generatePath), generatePath);
|
||||
float modifiedZ = SearchBestGroundZForPath(x, y, z, generatePath, normal_only);
|
||||
if (modifiedZ == INVALID_HEIGHT) {
|
||||
return false;
|
||||
}
|
||||
mm.MovePoint(mapId, x, y, modifiedZ, generatePath);
|
||||
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation());
|
||||
return true;
|
||||
}
|
||||
@@ -1253,11 +1258,27 @@ bool MovementAction::MoveAway(Unit* target)
|
||||
if (!target) {
|
||||
return false;
|
||||
}
|
||||
float angle = target->GetAngle(bot);
|
||||
float dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
|
||||
float dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
|
||||
float dz = bot->GetPositionZ();
|
||||
return MoveTo(target->GetMapId(), dx, dy, dz);
|
||||
float init_angle = target->GetAngle(bot);
|
||||
for (float delta = 0; delta <= M_PI / 2; delta += M_PI / 8) {
|
||||
float angle = init_angle + delta;
|
||||
float dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
|
||||
float dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
|
||||
float dz = bot->GetPositionZ();
|
||||
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true)) {
|
||||
return true;
|
||||
}
|
||||
if (delta == 0) {
|
||||
continue;
|
||||
}
|
||||
angle = init_angle - delta;
|
||||
dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
|
||||
dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
|
||||
dz = bot->GetPositionZ();
|
||||
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float distance)
|
||||
@@ -1268,7 +1289,7 @@ bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float d
|
||||
return MoveNear(mapId, x, y, z, distance);
|
||||
}
|
||||
|
||||
float MovementAction::SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range)
|
||||
float MovementAction::SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range, bool normal_only)
|
||||
{
|
||||
if (!generatePath) {
|
||||
return z;
|
||||
@@ -1299,6 +1320,9 @@ float MovementAction::SearchBestGroundZForPath(float x, float y, float z, bool g
|
||||
return modified_z;
|
||||
}
|
||||
}
|
||||
if (normal_only) {
|
||||
return INVALID_HEIGHT;
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
@@ -1449,14 +1473,15 @@ bool MoveRandomAction::Execute(Event event)
|
||||
float x = bot->GetPositionX();
|
||||
float y = bot->GetPositionY();
|
||||
float z = bot->GetPositionZ();
|
||||
x += urand(0, distance) - distance / 2;
|
||||
y += urand(0, distance) - distance / 2;
|
||||
float angle = (float)rand_norm() * static_cast<float>(M_PI);
|
||||
x += urand(0, distance) * cos(angle);
|
||||
y += urand(0, distance) * sin(angle);
|
||||
bot->UpdateGroundPositionZ(x, y, z);
|
||||
|
||||
if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight()))
|
||||
continue;
|
||||
|
||||
bool moved = MoveTo(bot->GetMapId(), x, y, z);
|
||||
bool moved = MoveTo(bot->GetMapId(), x, y, z, false, false, true);
|
||||
if (moved)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class MovementAction : public Action
|
||||
protected:
|
||||
bool MoveNear(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->contactDistance);
|
||||
bool MoveToLOS(WorldObject* target, bool ranged = false);
|
||||
bool MoveTo(uint32 mapId, float x, float y, float z, bool idle = false, bool react = false);
|
||||
bool MoveTo(uint32 mapId, float x, float y, float z, bool idle = false, bool react = false, bool normal_only = false);
|
||||
bool MoveTo(Unit* target, float distance = 0.0f);
|
||||
bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig->contactDistance);
|
||||
float GetFollowAngle();
|
||||
@@ -41,7 +41,7 @@ class MovementAction : public Action
|
||||
bool MoveInside(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->followDistance);
|
||||
void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false);
|
||||
private:
|
||||
float SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range = 10.0f);
|
||||
float SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range = 10.0f, bool normal_only = false);
|
||||
};
|
||||
|
||||
class FleeAction : public MovementAction
|
||||
|
||||
@@ -80,15 +80,15 @@ BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
|
||||
NextAction** BloodDKStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("rune strike", ACTION_NORMAL + 8),
|
||||
new NextAction("icy touch", ACTION_NORMAL + 7),
|
||||
new NextAction("heart strike", ACTION_NORMAL + 6),
|
||||
new NextAction("blood strike", ACTION_NORMAL + 5),
|
||||
new NextAction("dancing rune weapon", ACTION_NORMAL + 4),
|
||||
new NextAction("death coil", ACTION_NORMAL + 3),
|
||||
new NextAction("plague strike", ACTION_NORMAL + 2),
|
||||
new NextAction("horn of winter", ACTION_NORMAL + 1),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("rune strike", ACTION_DEFAULT + 0.8f),
|
||||
new NextAction("icy touch", ACTION_DEFAULT + 0.7f),
|
||||
new NextAction("heart strike", ACTION_DEFAULT + 0.6f),
|
||||
new NextAction("blood strike", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("dancing rune weapon", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("death coil", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("plague strike", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,12 +78,12 @@ FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI)
|
||||
NextAction** FrostDKStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("obliterate", ACTION_NORMAL + 5),
|
||||
new NextAction("frost strike", ACTION_NORMAL + 4),
|
||||
new NextAction("obliterate", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("frost strike", ACTION_DEFAULT + 0.4f),
|
||||
// new NextAction("death strike", ACTION_NORMAL + 3),
|
||||
new NextAction("empower rune weapon", ACTION_NORMAL + 2),
|
||||
new NextAction("horn of winter", ACTION_NORMAL),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("empower rune weapon", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
@@ -72,15 +72,15 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI
|
||||
NextAction** UnholyDKStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("scourge strike", ACTION_NORMAL + 7),
|
||||
new NextAction("blood strike", ACTION_NORMAL + 6),
|
||||
new NextAction("ghoul frenzy", ACTION_NORMAL + 5),
|
||||
new NextAction("summon gargoyle", ACTION_NORMAL + 4),
|
||||
new NextAction("death coil", ACTION_NORMAL + 3),
|
||||
new NextAction("plague strike", ACTION_NORMAL + 2),
|
||||
new NextAction("icy touch", ACTION_NORMAL + 1),
|
||||
new NextAction("horn of winter", ACTION_NORMAL),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("scourge strike", ACTION_DEFAULT + 0.8f),
|
||||
new NextAction("blood strike", ACTION_DEFAULT + 0.7f),
|
||||
new NextAction("ghoul frenzy", ACTION_DEFAULT + 0.6f),
|
||||
new NextAction("summon gargoyle", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("death coil", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("plague strike", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("icy touch", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("horn of winter", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -140,12 +140,12 @@ BearTankDruidStrategy::BearTankDruidStrategy(PlayerbotAI* botAI) : FeralDruidStr
|
||||
NextAction** BearTankDruidStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("mangle (bear)", ACTION_NORMAL + 5),
|
||||
new NextAction("faerie fire (feral)", ACTION_NORMAL + 4),
|
||||
new NextAction("lacerate", ACTION_NORMAL + 3),
|
||||
new NextAction("maul", ACTION_NORMAL + 2),
|
||||
new NextAction("enrage", ACTION_NORMAL + 1),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("mangle (bear)", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("lacerate", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("maul", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("enrage", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,8 +105,8 @@ CasterDruidStrategy::CasterDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrat
|
||||
NextAction** CasterDruidStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("starfall", ACTION_NORMAL + 2),
|
||||
new NextAction("wrath", ACTION_NORMAL + 1),
|
||||
new NextAction("starfall", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("wrath", ACTION_DEFAULT + 0.1f),
|
||||
// new NextAction("starfire", ACTION_NORMAL),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ CatDpsDruidStrategy::CatDpsDruidStrategy(PlayerbotAI* botAI) : FeralDruidStrateg
|
||||
|
||||
NextAction** CatDpsDruidStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("mangle (cat)", ACTION_NORMAL + 1), nullptr);
|
||||
return NextAction::array(0, new NextAction("mangle (cat)", ACTION_DEFAULT + 0.1f), nullptr);
|
||||
}
|
||||
|
||||
void CatDpsDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -12,8 +12,8 @@ MeleeDruidStrategy::MeleeDruidStrategy(PlayerbotAI* botAI) : CombatStrategy(botA
|
||||
NextAction** MeleeDruidStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("faerie fire", ACTION_NORMAL + 1),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("faerie fire", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ NextAction** GrindingStrategy::getDefaultActions()
|
||||
|
||||
void GrindingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("drink", 7.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("food", 6.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 5.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("drink", 4.2f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("food", 4.1f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 4.0f), nullptr)));
|
||||
}
|
||||
|
||||
void MoveRandomStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -26,32 +26,33 @@ RpgStrategy::RpgStrategy(PlayerbotAI* botAI) : Strategy(botAI)
|
||||
|
||||
NextAction** RpgStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("rpg", 1.1f), nullptr);
|
||||
return NextAction::array(0, new NextAction("rpg", 1.0f), nullptr);
|
||||
}
|
||||
|
||||
void RpgStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no rpg target", NextAction::array(0, new NextAction("choose rpg target", 5.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("no rpg target", NextAction::array(0, new NextAction("move random", 1.10f), NULL)));
|
||||
triggers.push_back(new TriggerNode("far from rpg target", NextAction::array(0, new NextAction("move to rpg target", 5.0f), nullptr)));
|
||||
|
||||
//Sub actions
|
||||
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg stay", 1.001f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg work", 1.001f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg emote", 1.001f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("has rpg target", NextAction::array(0, new NextAction("rpg cancel", 1.001f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg stay", 1.101f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg work", 1.101f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg emote", 1.101f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("has rpg target", NextAction::array(0, new NextAction("rpg cancel", 1.101f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("rpg taxi", NextAction::array(0, new NextAction("rpg taxi", 1.005f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg discover", NextAction::array(0, new NextAction("rpg discover", 1.110f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg start quest", NextAction::array(0, new NextAction("rpg start quest", 1.080f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg end quest", NextAction::array(0, new NextAction("rpg end quest", 1.090f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg buy", NextAction::array(0, new NextAction("rpg buy", 1.030f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg discover", NextAction::array(0, new NextAction("rpg discover", 1.210f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg start quest", NextAction::array(0, new NextAction("rpg start quest", 1.180f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg end quest", NextAction::array(0, new NextAction("rpg end quest", 1.190f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg buy", NextAction::array(0, new NextAction("rpg buy", 1.130f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("rpg sell", NextAction::array(0, new NextAction("rpg sell", 1.100f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg repair", NextAction::array(0, new NextAction("rpg repair", 1.095f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg repair", NextAction::array(0, new NextAction("rpg repair", 1.195f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("rpg train", NextAction::array(0, new NextAction("rpg train", 1.080f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg heal", NextAction::array(0, new NextAction("rpg heal", 1.025f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg home bind", NextAction::array(0, new NextAction("rpg home bind", 1.060f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg heal", NextAction::array(0, new NextAction("rpg heal", 1.125f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg home bind", NextAction::array(0, new NextAction("rpg home bind", 1.160f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("rpg queue bg", NextAction::array(0, new NextAction("rpg queue bg", 1.085f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg buy petition", NextAction::array(0, new NextAction("rpg buy petition", 1.040f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg use", NextAction::array(0, new NextAction("rpg use", 1.002f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg buy petition", NextAction::array(0, new NextAction("rpg buy petition", 1.140f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("rpg use", NextAction::array(0, new NextAction("rpg use", 1.102f), nullptr)));
|
||||
//triggers.push_back(new TriggerNode("rpg spell", NextAction::array(0, new NextAction("rpg spell", 1.001f), nullptr)));
|
||||
//triggers.push_back(new TriggerNode("rpg craft", NextAction::array(0, new NextAction("rpg craft", 1.001f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("rpg trade useful", NextAction::array(0, new NextAction("rpg trade useful", 1.030f), nullptr)));
|
||||
|
||||
@@ -31,13 +31,13 @@ DpsHunterStrategy::DpsHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy
|
||||
NextAction** DpsHunterStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("kill shot", 16.0f),
|
||||
new NextAction("chimera shot", 15.0f),
|
||||
new NextAction("explosive shot", 15.0f),
|
||||
new NextAction("aimed shot", 14.0f),
|
||||
new NextAction("arcane shot", 13.0f),
|
||||
new NextAction("steady shot", 12.0f),
|
||||
new NextAction("auto shot", 10.0f),
|
||||
new NextAction("kill shot", ACTION_DEFAULT + 0.6f),
|
||||
new NextAction("chimera shot", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("explosive shot", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("aimed shot", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("arcane shot", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("steady shot", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("auto shot", ACTION_DEFAULT),
|
||||
nullptr);
|
||||
// return NextAction::array(0, new NextAction("explosive shot", 11.0f), new NextAction("auto shot", 10.0f), new NextAction("auto attack", 9.0f), 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("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("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)));
|
||||
|
||||
@@ -41,7 +41,7 @@ bool CastAutoShotAction::isUseful()
|
||||
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true))
|
||||
return false;
|
||||
|
||||
if (bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)) {
|
||||
if (bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_targets.GetUnitTargetGUID() == AI_VALUE(Unit*, "current target")->GetGUID()) {
|
||||
return false;
|
||||
}
|
||||
return AI_VALUE(uint32, "active spell") != AI_VALUE2(uint32, "spell id", getName());
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "HunterActions.h"
|
||||
#include "Playerbots.h"
|
||||
#include "ServerFacade.h"
|
||||
#include "SharedDefines.h"
|
||||
|
||||
bool HunterAspectOfTheHawkTrigger::IsActive()
|
||||
{
|
||||
@@ -77,3 +78,9 @@ bool SwitchToMeleeTrigger::IsActive()
|
||||
return botAI->HasStrategy("ranged", BOT_STATE_COMBAT) && target && (target->GetVictim() == bot &&
|
||||
sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), 8.0f));
|
||||
}
|
||||
|
||||
bool TargetRemoveEnrageTrigger::IsActive()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return target && (botAI->HasAuraToDispel(target, DISPEL_ENRAGE) || botAI->HasAuraToDispel(target, DISPEL_MAGIC));
|
||||
}
|
||||
@@ -160,5 +160,6 @@ class TargetRemoveEnrageTrigger : public TargetAuraDispelTrigger
|
||||
{
|
||||
public:
|
||||
TargetRemoveEnrageTrigger(PlayerbotAI* ai) : TargetAuraDispelTrigger(ai, "tranquilizing shot", DISPEL_ENRAGE) {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -57,7 +57,10 @@ ArcaneMageStrategy::ArcaneMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy
|
||||
|
||||
NextAction** ArcaneMageStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("arcane blast", 10.0f), NULL);
|
||||
return NextAction::array(0,
|
||||
new NextAction("arcane blast", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("shoot", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
void ArcaneMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
|
||||
NextAction** FireMageStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("fireball", ACTION_NORMAL + 1), NULL);
|
||||
return NextAction::array(0,
|
||||
new NextAction("fireball", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("shoot", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
void FireMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -11,7 +11,11 @@ FrostMageStrategy::FrostMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy(b
|
||||
|
||||
NextAction** FrostMageStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("frostbolt", 7.0f), nullptr);
|
||||
return NextAction::array(0,
|
||||
new NextAction("frostbolt", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("shoot", ACTION_DEFAULT),
|
||||
nullptr);
|
||||
|
||||
}
|
||||
|
||||
void FrostMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -80,11 +80,11 @@ DpsPaladinStrategy::DpsPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStrat
|
||||
NextAction** DpsPaladinStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("judgement of wisdom", ACTION_NORMAL + 6),
|
||||
new NextAction("crusader strike", ACTION_NORMAL + 5),
|
||||
new NextAction("divine storm", ACTION_NORMAL + 4),
|
||||
new NextAction("consecration", ACTION_NORMAL + 3),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("judgement of wisdom", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("crusader strike", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("divine storm", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("consecration", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ HealPaladinStrategy::HealPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr
|
||||
|
||||
NextAction** HealPaladinStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("judgement of light", ACTION_NORMAL + 2), nullptr);
|
||||
return NextAction::array(0, new NextAction("judgement of light", ACTION_DEFAULT + 2), nullptr);
|
||||
}
|
||||
|
||||
void HealPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -59,12 +59,12 @@ TankPaladinStrategy::TankPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr
|
||||
NextAction** TankPaladinStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("shield of righteousness", ACTION_NORMAL + 6),
|
||||
new NextAction("hammer of the righteous", ACTION_NORMAL + 5),
|
||||
new NextAction("judgement of wisdom", ACTION_NORMAL + 4),
|
||||
new NextAction("shield of righteousness", ACTION_DEFAULT + 0.6f),
|
||||
new NextAction("hammer of the righteous", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("judgement of wisdom", ACTION_DEFAULT + 0.4f),
|
||||
// new NextAction("avenger's shield", ACTION_NORMAL + 3),
|
||||
// new NextAction("consecration", ACTION_NORMAL + 2),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ HealPriestStrategy::HealPriestStrategy(PlayerbotAI* botAI) : GenericPriestStrate
|
||||
|
||||
NextAction** HealPriestStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("shoot", 10.0f), nullptr);
|
||||
return NextAction::array(0, new NextAction("shoot", ACTION_DEFAULT), nullptr);
|
||||
}
|
||||
|
||||
void HealPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -30,7 +30,7 @@ HolyPriestStrategy::HolyPriestStrategy(PlayerbotAI* botAI) : HealPriestStrategy(
|
||||
|
||||
NextAction** HolyPriestStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("smite", 10.0f), new NextAction("mana burn", 9.0f), new NextAction("starshards", 8.0f), nullptr);
|
||||
return NextAction::array(0, new NextAction("smite", ACTION_DEFAULT + 0.2f), new NextAction("mana burn", ACTION_DEFAULT + 0.1f), new NextAction("starshards", ACTION_DEFAULT), nullptr);
|
||||
}
|
||||
|
||||
void HolyPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -14,10 +14,10 @@ ShadowPriestStrategy::ShadowPriestStrategy(PlayerbotAI* botAI) : GenericPriestSt
|
||||
NextAction** ShadowPriestStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("mind blast", 13.0f),
|
||||
new NextAction("mind blast", ACTION_DEFAULT + 0.2f),
|
||||
// new NextAction("shadow word: death", 12.0f),
|
||||
new NextAction("mind flay", 11.0f),
|
||||
// new NextAction("shoot", 10.0f),
|
||||
new NextAction("mind flay", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("shoot", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ void ShadowPriestAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("shadow word: pain on attacker", NextAction::array(0, new NextAction("shadow word: pain on attacker", ACTION_NORMAL + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode("vampiric touch on attacker", NextAction::array(0, new NextAction("vampiric touch on attacker", ACTION_NORMAL + 4), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("mind sear", ACTION_HIGH + 4), nullptr)));
|
||||
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("mind sear", ACTION_HIGH + 4), nullptr)));
|
||||
}
|
||||
|
||||
void ShadowPriestDebuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -35,7 +35,7 @@ AssassinationRogueStrategy::AssassinationRogueStrategy(PlayerbotAI* ai) : MeleeC
|
||||
NextAction** AssassinationRogueStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,8 @@ DpsRogueStrategy::DpsRogueStrategy(PlayerbotAI* botAI) : MeleeCombatStrategy(bot
|
||||
NextAction** DpsRogueStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("killing spree", ACTION_NORMAL + 1),
|
||||
new NextAction("melee", ACTION_NORMAL), NULL);
|
||||
new NextAction("killing spree", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT), NULL);
|
||||
}
|
||||
|
||||
void DpsRogueStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -14,16 +14,6 @@ bool CastStealthAction::isPossible()
|
||||
return !botAI->HasAura(23333, bot) && !botAI->HasAura(23335, bot) && !botAI->HasAura(34976, bot);
|
||||
}
|
||||
|
||||
bool CastStealthAction::Execute(Event event)
|
||||
{
|
||||
if (botAI->CastSpell("stealth", bot))
|
||||
{
|
||||
// botAI->ChangeStrategy("-dps,+stealthed", BOT_STATE_COMBAT);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnstealthAction::Execute(Event event)
|
||||
{
|
||||
botAI->RemoveAura("stealth");
|
||||
|
||||
@@ -32,7 +32,6 @@ class CastStealthAction : public CastBuffSpellAction
|
||||
std::string const GetTargetName() override { return "self target"; }
|
||||
|
||||
bool isPossible() override;
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class UnstealthAction : public Action
|
||||
|
||||
@@ -39,8 +39,8 @@ CasterShamanStrategy::CasterShamanStrategy(PlayerbotAI* botAI) : GenericShamanSt
|
||||
NextAction** CasterShamanStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("lava burst", 11.0f),
|
||||
new NextAction("lightning bolt", 10.0f),
|
||||
new NextAction("lava burst", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("lightning bolt", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "HealShamanStrategy.h"
|
||||
#include "Playerbots.h"
|
||||
#include "Strategy.h"
|
||||
|
||||
class GenericShamanStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
@@ -116,7 +117,7 @@ void GenericShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
triggers.push_back(new TriggerNode("wind shear", NextAction::array(0, new NextAction("wind shear", 23.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("wind shear on enemy healer", NextAction::array(0, new NextAction("wind shear on enemy healer", 23.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("purge", NextAction::array(0, new NextAction("purge", 10.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("purge", NextAction::array(0, new NextAction("purge", ACTION_DISPEL), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("lesser healing wave on party", 25.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("riptide on party", 25.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("chain heal", 27.0f), nullptr)));
|
||||
|
||||
@@ -50,11 +50,11 @@ MeleeShamanStrategy::MeleeShamanStrategy(PlayerbotAI* botAI) : GenericShamanStra
|
||||
NextAction** MeleeShamanStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("stormstrike", ACTION_NORMAL + 6),
|
||||
new NextAction("earth shock", ACTION_NORMAL + 5),
|
||||
new NextAction("fire nova", ACTION_NORMAL + 4),
|
||||
new NextAction("lava lash", ACTION_NORMAL + 1),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("stormstrike", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("earth shock", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("fire nova", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("lava lash", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class Unit;
|
||||
class NeedCureTrigger : public SpellTrigger
|
||||
{
|
||||
public:
|
||||
NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 2 * 1000), dispelType(dispelType) { }
|
||||
NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 1 * 1000), dispelType(dispelType) { }
|
||||
|
||||
std::string const GetTargetName() override { return "self target"; }
|
||||
bool IsActive() override;
|
||||
|
||||
@@ -406,7 +406,7 @@ bool TankAssistTrigger::IsActive()
|
||||
if (!tankTarget || currentTarget == tankTarget)
|
||||
return false;
|
||||
|
||||
return currentTarget->GetVictim() == AI_VALUE(Unit*, "self target");
|
||||
return AI_VALUE2(bool, "has aggro", "current target");
|
||||
}
|
||||
|
||||
bool IsBehindTargetTrigger::IsActive()
|
||||
|
||||
@@ -217,7 +217,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
|
||||
static Trigger* critical_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "critical aoe heal", "critical", 2); }
|
||||
static Trigger* low_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); }
|
||||
static Trigger* medium_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); }
|
||||
static Trigger* group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.4); }
|
||||
static Trigger* group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.6); }
|
||||
static Trigger* medium_group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "medium", 0.4); }
|
||||
static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); }
|
||||
static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include "DpsTargetValue.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
class FindLeastHpTargetStrategy : public FindTargetStrategy
|
||||
@@ -58,13 +59,79 @@ 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_unit) > GetIntervalLevel(old_unit)) {
|
||||
return true;
|
||||
}
|
||||
int32_t level = GetIntervalLevel(new_unit);
|
||||
if (level % 10 == 2 || level % 10 == 0) {
|
||||
return new_time < old_time;
|
||||
}
|
||||
// dont switch targets when all of them with low health
|
||||
Unit* currentTarget = botAI->GetAiObjectContext()->GetValue<Unit*>("current target")->Get();
|
||||
if (currentTarget == new_unit) {
|
||||
return true;
|
||||
}
|
||||
if (currentTarget == old_unit) {
|
||||
return false;
|
||||
}
|
||||
return new_time > old_time;
|
||||
}
|
||||
int32_t GetIntervalLevel(Unit* unit) {
|
||||
float time = unit->GetHealth() / dps_;
|
||||
float dis = unit->GetDistance(botAI->GetBot());
|
||||
float attackRange = botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig->spellDistance : sPlayerbotAIConfig->meleeDistance;
|
||||
attackRange += 5.0f;
|
||||
int level = dis < attackRange ? 10 : 0;
|
||||
if (time >= 5 && time <= 20) {
|
||||
return level + 2;
|
||||
}
|
||||
if (time < 5) {
|
||||
return level + 1;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -45,7 +45,7 @@ float ExpectedGroupDpsValue::Calculate()
|
||||
} else if (level <= 70) {
|
||||
basic_dps = 350 + (level - 60) * 40;
|
||||
} else {
|
||||
basic_dps = 750 + (level - 70) * 100;
|
||||
basic_dps = 750 + (level - 70) * 125;
|
||||
}
|
||||
|
||||
if (level <= 8) {
|
||||
@@ -59,10 +59,12 @@ float ExpectedGroupDpsValue::Calculate()
|
||||
} else if (level <= 80) {
|
||||
basic_gs = (155 + (level - 70) * 4) * 4;
|
||||
}
|
||||
float gap = mixedGearScore - basic_gs;
|
||||
float gs_modifier = (float)mixedGearScore / basic_gs - 1;
|
||||
gs_modifier = gs_modifier * 3 + 1;
|
||||
|
||||
float gs_modifier = (float)mixedGearScore / basic_gs;
|
||||
if (gs_modifier < 0.5) gs_modifier = 0.5;
|
||||
if (gs_modifier > 3) gs_modifier = 3;
|
||||
if (gs_modifier > 4) gs_modifier = 4;
|
||||
|
||||
return dps_num * basic_dps * gs_modifier;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -47,9 +47,10 @@ DpsWarlockStrategy::DpsWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrat
|
||||
NextAction** DpsWarlockStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("haunt", 14.0f),
|
||||
new NextAction("demonic empowerment", 13.0f),
|
||||
new NextAction("shadow bolt", 10.0f),
|
||||
new NextAction("haunt", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("demonic empowerment", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("shadow bolt", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("shoot", ACTION_DEFAULT),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ TankWarlockStrategy::TankWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStr
|
||||
|
||||
NextAction** TankWarlockStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("shoot", 10.0f), nullptr);
|
||||
return NextAction::array(0, new NextAction("shoot", ACTION_DEFAULT), nullptr);
|
||||
}
|
||||
|
||||
void TankWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -32,7 +32,7 @@ ArmsWarriorStrategy::ArmsWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr
|
||||
|
||||
NextAction** ArmsWarriorStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("heroic strike", ACTION_NORMAL), nullptr);
|
||||
return NextAction::array(0, new NextAction("heroic strike", ACTION_DEFAULT), nullptr);
|
||||
}
|
||||
|
||||
void ArmsWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -35,12 +35,12 @@ FuryWarriorStrategy::FuryWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr
|
||||
NextAction** FuryWarriorStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("bloodthirst", ACTION_NORMAL + 5),
|
||||
new NextAction("whirlwind", ACTION_NORMAL + 4),
|
||||
new NextAction("sunder armor", ACTION_NORMAL + 3),
|
||||
new NextAction("execute", ACTION_NORMAL + 2),
|
||||
new NextAction("overpower", ACTION_NORMAL + 1),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("bloodthirst", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("whirlwind", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("sunder armor", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("execute", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("overpower", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ TankWarriorStrategy::TankWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr
|
||||
NextAction** TankWarriorStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0,
|
||||
new NextAction("devastate", ACTION_NORMAL + 2),
|
||||
new NextAction("revenge", ACTION_NORMAL + 1),
|
||||
new NextAction("melee", ACTION_NORMAL),
|
||||
new NextAction("devastate", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("revenge", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user