diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index 33b320a56..e2fb5d1c3 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -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; diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 863416937..65d5612c5 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -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(); diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index 0f618cfd9..e268914f4 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -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); diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 577357107..9c84de08d 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -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]; diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 9c82eeea7..4083938a4 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -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)"; diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index e00eef84c..d303360c5 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -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(); + 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..."); diff --git a/src/strategy/Engine.cpp b/src/strategy/Engine.cpp index 55bd712a6..12328b6dc 100644 --- a/src/strategy/Engine.cpp +++ b/src/strategy/Engine.cpp @@ -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 /* diff --git a/src/strategy/Strategy.h b/src/strategy/Strategy.h index 854a7b899..4de7b6713 100644 --- a/src/strategy/Strategy.h +++ b/src/strategy/Strategy.h @@ -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 { diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 3919df3f3..126395090 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -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(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; } diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index b442c3f18..ce437e9c0 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -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 diff --git a/src/strategy/deathknight/BloodDKStrategy.cpp b/src/strategy/deathknight/BloodDKStrategy.cpp index 079d4ad9e..b63908cb0 100644 --- a/src/strategy/deathknight/BloodDKStrategy.cpp +++ b/src/strategy/deathknight/BloodDKStrategy.cpp @@ -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); } diff --git a/src/strategy/deathknight/FrostDKStrategy.cpp b/src/strategy/deathknight/FrostDKStrategy.cpp index 8966fa694..8feba4136 100644 --- a/src/strategy/deathknight/FrostDKStrategy.cpp +++ b/src/strategy/deathknight/FrostDKStrategy.cpp @@ -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 ); } diff --git a/src/strategy/deathknight/UnholyDKStrategy.cpp b/src/strategy/deathknight/UnholyDKStrategy.cpp index 4369689fb..638a9967f 100644 --- a/src/strategy/deathknight/UnholyDKStrategy.cpp +++ b/src/strategy/deathknight/UnholyDKStrategy.cpp @@ -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); } diff --git a/src/strategy/druid/BearTankDruidStrategy.cpp b/src/strategy/druid/BearTankDruidStrategy.cpp index 7f0ed5bf3..d3d49ce5f 100644 --- a/src/strategy/druid/BearTankDruidStrategy.cpp +++ b/src/strategy/druid/BearTankDruidStrategy.cpp @@ -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); } diff --git a/src/strategy/druid/CasterDruidStrategy.cpp b/src/strategy/druid/CasterDruidStrategy.cpp index 03e1ffd54..51c2692ee 100644 --- a/src/strategy/druid/CasterDruidStrategy.cpp +++ b/src/strategy/druid/CasterDruidStrategy.cpp @@ -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); } diff --git a/src/strategy/druid/CatDpsDruidStrategy.cpp b/src/strategy/druid/CatDpsDruidStrategy.cpp index a3f15140c..5b9dc1700 100644 --- a/src/strategy/druid/CatDpsDruidStrategy.cpp +++ b/src/strategy/druid/CatDpsDruidStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/druid/MeleeDruidStrategy.cpp b/src/strategy/druid/MeleeDruidStrategy.cpp index 39b3b0279..7a0178216 100644 --- a/src/strategy/druid/MeleeDruidStrategy.cpp +++ b/src/strategy/druid/MeleeDruidStrategy.cpp @@ -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); } diff --git a/src/strategy/generic/GrindingStrategy.cpp b/src/strategy/generic/GrindingStrategy.cpp index a7cf3bbdb..ffbe8300d 100644 --- a/src/strategy/generic/GrindingStrategy.cpp +++ b/src/strategy/generic/GrindingStrategy.cpp @@ -12,9 +12,9 @@ NextAction** GrindingStrategy::getDefaultActions() void GrindingStrategy::InitTriggers(std::vector& 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& triggers) diff --git a/src/strategy/generic/RpgStrategy.cpp b/src/strategy/generic/RpgStrategy.cpp index d0b8b0c8d..986c11d46 100644 --- a/src/strategy/generic/RpgStrategy.cpp +++ b/src/strategy/generic/RpgStrategy.cpp @@ -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& 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))); diff --git a/src/strategy/hunter/DpsHunterStrategy.cpp b/src/strategy/hunter/DpsHunterStrategy.cpp index 7ec2220a1..891190daa 100644 --- a/src/strategy/hunter/DpsHunterStrategy.cpp +++ b/src/strategy/hunter/DpsHunterStrategy.cpp @@ -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& 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))); diff --git a/src/strategy/hunter/HunterActions.cpp b/src/strategy/hunter/HunterActions.cpp index ee20b83d7..10ef0a313 100644 --- a/src/strategy/hunter/HunterActions.cpp +++ b/src/strategy/hunter/HunterActions.cpp @@ -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()); diff --git a/src/strategy/hunter/HunterTriggers.cpp b/src/strategy/hunter/HunterTriggers.cpp index db6c77952..f56065b1c 100644 --- a/src/strategy/hunter/HunterTriggers.cpp +++ b/src/strategy/hunter/HunterTriggers.cpp @@ -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)); +} \ No newline at end of file diff --git a/src/strategy/hunter/HunterTriggers.h b/src/strategy/hunter/HunterTriggers.h index 6096bca75..c904732e8 100644 --- a/src/strategy/hunter/HunterTriggers.h +++ b/src/strategy/hunter/HunterTriggers.h @@ -160,5 +160,6 @@ class TargetRemoveEnrageTrigger : public TargetAuraDispelTrigger { public: TargetRemoveEnrageTrigger(PlayerbotAI* ai) : TargetAuraDispelTrigger(ai, "tranquilizing shot", DISPEL_ENRAGE) {} + bool IsActive() override; }; #endif diff --git a/src/strategy/mage/ArcaneMageStrategy.cpp b/src/strategy/mage/ArcaneMageStrategy.cpp index c5c46aa4c..db97a4daa 100644 --- a/src/strategy/mage/ArcaneMageStrategy.cpp +++ b/src/strategy/mage/ArcaneMageStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/mage/FireMageStrategy.cpp b/src/strategy/mage/FireMageStrategy.cpp index 565031751..8382c3b15 100644 --- a/src/strategy/mage/FireMageStrategy.cpp +++ b/src/strategy/mage/FireMageStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/mage/FrostMageStrategy.cpp b/src/strategy/mage/FrostMageStrategy.cpp index 77ee30eb9..39822aa12 100644 --- a/src/strategy/mage/FrostMageStrategy.cpp +++ b/src/strategy/mage/FrostMageStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/paladin/DpsPaladinStrategy.cpp b/src/strategy/paladin/DpsPaladinStrategy.cpp index 0662660e5..907d9411c 100644 --- a/src/strategy/paladin/DpsPaladinStrategy.cpp +++ b/src/strategy/paladin/DpsPaladinStrategy.cpp @@ -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); } diff --git a/src/strategy/paladin/HealPaladinStrategy.cpp b/src/strategy/paladin/HealPaladinStrategy.cpp index 6f6510396..15215026d 100644 --- a/src/strategy/paladin/HealPaladinStrategy.cpp +++ b/src/strategy/paladin/HealPaladinStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/paladin/TankPaladinStrategy.cpp b/src/strategy/paladin/TankPaladinStrategy.cpp index 3c03d7ace..d8b3f9a14 100644 --- a/src/strategy/paladin/TankPaladinStrategy.cpp +++ b/src/strategy/paladin/TankPaladinStrategy.cpp @@ -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); } diff --git a/src/strategy/priest/HealPriestStrategy.cpp b/src/strategy/priest/HealPriestStrategy.cpp index 7f15dd350..322de6854 100644 --- a/src/strategy/priest/HealPriestStrategy.cpp +++ b/src/strategy/priest/HealPriestStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/priest/HolyPriestStrategy.cpp b/src/strategy/priest/HolyPriestStrategy.cpp index 72b216a1e..ba24d7306 100644 --- a/src/strategy/priest/HolyPriestStrategy.cpp +++ b/src/strategy/priest/HolyPriestStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/priest/ShadowPriestStrategy.cpp b/src/strategy/priest/ShadowPriestStrategy.cpp index a4560d68b..8c00165b1 100644 --- a/src/strategy/priest/ShadowPriestStrategy.cpp +++ b/src/strategy/priest/ShadowPriestStrategy.cpp @@ -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& 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& triggers) diff --git a/src/strategy/rogue/AssassinationRogueStrategy.cpp b/src/strategy/rogue/AssassinationRogueStrategy.cpp index 990264d77..6510e72df 100644 --- a/src/strategy/rogue/AssassinationRogueStrategy.cpp +++ b/src/strategy/rogue/AssassinationRogueStrategy.cpp @@ -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); } diff --git a/src/strategy/rogue/DpsRogueStrategy.cpp b/src/strategy/rogue/DpsRogueStrategy.cpp index 8ff13bbe4..cf26ec084 100644 --- a/src/strategy/rogue/DpsRogueStrategy.cpp +++ b/src/strategy/rogue/DpsRogueStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/rogue/RogueActions.cpp b/src/strategy/rogue/RogueActions.cpp index 99ffcc643..e0ece34c3 100644 --- a/src/strategy/rogue/RogueActions.cpp +++ b/src/strategy/rogue/RogueActions.cpp @@ -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"); diff --git a/src/strategy/rogue/RogueActions.h b/src/strategy/rogue/RogueActions.h index 21b5ed572..3087f744b 100644 --- a/src/strategy/rogue/RogueActions.h +++ b/src/strategy/rogue/RogueActions.h @@ -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 diff --git a/src/strategy/shaman/CasterShamanStrategy.cpp b/src/strategy/shaman/CasterShamanStrategy.cpp index 6dfb015ab..6455dee39 100644 --- a/src/strategy/shaman/CasterShamanStrategy.cpp +++ b/src/strategy/shaman/CasterShamanStrategy.cpp @@ -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); } diff --git a/src/strategy/shaman/GenericShamanStrategy.cpp b/src/strategy/shaman/GenericShamanStrategy.cpp index e05c97540..9a0583f0f 100644 --- a/src/strategy/shaman/GenericShamanStrategy.cpp +++ b/src/strategy/shaman/GenericShamanStrategy.cpp @@ -4,6 +4,7 @@ #include "HealShamanStrategy.h" #include "Playerbots.h" +#include "Strategy.h" class GenericShamanStrategyActionNodeFactory : public NamedObjectFactory { @@ -116,7 +117,7 @@ void GenericShamanStrategy::InitTriggers(std::vector& 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))); diff --git a/src/strategy/shaman/MeleeShamanStrategy.cpp b/src/strategy/shaman/MeleeShamanStrategy.cpp index c514dc337..54db4dac8 100644 --- a/src/strategy/shaman/MeleeShamanStrategy.cpp +++ b/src/strategy/shaman/MeleeShamanStrategy.cpp @@ -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); } diff --git a/src/strategy/triggers/CureTriggers.h b/src/strategy/triggers/CureTriggers.h index 4632f1541..50bedf2fc 100644 --- a/src/strategy/triggers/CureTriggers.h +++ b/src/strategy/triggers/CureTriggers.h @@ -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; diff --git a/src/strategy/triggers/GenericTriggers.cpp b/src/strategy/triggers/GenericTriggers.cpp index be35d17bb..1e3d470b5 100644 --- a/src/strategy/triggers/GenericTriggers.cpp +++ b/src/strategy/triggers/GenericTriggers.cpp @@ -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() diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index d030a9ba3..0859d7069 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -217,7 +217,7 @@ class TriggerContext : public NamedObjectContext 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); } diff --git a/src/strategy/values/AttackerCountValues.cpp b/src/strategy/values/AttackerCountValues.cpp index 9faeeb2a4..15cb6efb6 100644 --- a/src/strategy/values/AttackerCountValues.cpp +++ b/src/strategy/values/AttackerCountValues.cpp @@ -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; diff --git a/src/strategy/values/DpsTargetValue.cpp b/src/strategy/values/DpsTargetValue.cpp index aee84ee28..644872c88 100644 --- a/src/strategy/values/DpsTargetValue.cpp +++ b/src/strategy/values/DpsTargetValue.cpp @@ -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("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); } diff --git a/src/strategy/values/ExpectedLifetimeValue.cpp b/src/strategy/values/ExpectedLifetimeValue.cpp index 3518af2e3..084593cd7 100644 --- a/src/strategy/values/ExpectedLifetimeValue.cpp +++ b/src/strategy/values/ExpectedLifetimeValue.cpp @@ -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; } \ No newline at end of file diff --git a/src/strategy/values/TankTargetValue.cpp b/src/strategy/values/TankTargetValue.cpp index 817dbd500..173c84dac 100644 --- a/src/strategy/values/TankTargetValue.cpp +++ b/src/strategy/values/TankTargetValue.cpp @@ -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); } diff --git a/src/strategy/warlock/DpsWarlockStrategy.cpp b/src/strategy/warlock/DpsWarlockStrategy.cpp index b59781980..f5247c3f8 100644 --- a/src/strategy/warlock/DpsWarlockStrategy.cpp +++ b/src/strategy/warlock/DpsWarlockStrategy.cpp @@ -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); } diff --git a/src/strategy/warlock/TankWarlockStrategy.cpp b/src/strategy/warlock/TankWarlockStrategy.cpp index ca1fae486..a828fdecb 100644 --- a/src/strategy/warlock/TankWarlockStrategy.cpp +++ b/src/strategy/warlock/TankWarlockStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/warrior/ArmsWarriorStrategy.cpp b/src/strategy/warrior/ArmsWarriorStrategy.cpp index 4643ff63c..c6314baeb 100644 --- a/src/strategy/warrior/ArmsWarriorStrategy.cpp +++ b/src/strategy/warrior/ArmsWarriorStrategy.cpp @@ -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& triggers) diff --git a/src/strategy/warrior/FuryWarriorStrategy.cpp b/src/strategy/warrior/FuryWarriorStrategy.cpp index 3894b459c..1f8c3aeec 100644 --- a/src/strategy/warrior/FuryWarriorStrategy.cpp +++ b/src/strategy/warrior/FuryWarriorStrategy.cpp @@ -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); } diff --git a/src/strategy/warrior/TankWarriorStrategy.cpp b/src/strategy/warrior/TankWarriorStrategy.cpp index 0eaf3553f..e9beec2dd 100644 --- a/src/strategy/warrior/TankWarriorStrategy.cpp +++ b/src/strategy/warrior/TankWarriorStrategy.cpp @@ -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); }