From 593b30bbb047a080ab5dc4b8f898a935082730bd Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 6 Sep 2024 20:29:38 +0800 Subject: [PATCH] Arm warrior and dk --- conf/playerbots.conf.dist | 14 +- src/factory/StatsCollector.cpp | 14 +- src/factory/StatsCollector.h | 3 +- src/factory/StatsWeightCalculator.cpp | 126 ++++++++++-------- src/strategy/deathknight/BloodDKStrategy.cpp | 8 +- .../deathknight/DKAiObjectContext.cpp | 4 + src/strategy/deathknight/DKTriggers.cpp | 15 ++- src/strategy/deathknight/DKTriggers.h | 14 ++ src/strategy/deathknight/FrostDKStrategy.cpp | 32 +++-- .../deathknight/GenericDKStrategy.cpp | 15 +-- src/strategy/deathknight/UnholyDKStrategy.cpp | 56 +++++--- src/strategy/values/Arrow.cpp | 4 +- src/strategy/values/Formations.cpp | 20 ++- src/strategy/warrior/ArmsWarriorStrategy.cpp | 12 +- 14 files changed, 211 insertions(+), 126 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 4eabcb34..87008706 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -774,12 +774,12 @@ AiPlayerbot.RandomBotInWorldWithRotationDisabled = 31104000 AiPlayerbot.PremadeSpecName.1.0 = arms pve AiPlayerbot.PremadeSpecGlyph.1.0 = 43418,43395,43423,43399,49084,43421 -AiPlayerbot.PremadeSpecLink.1.0.60 = 3022032023335100202012013031241 -AiPlayerbot.PremadeSpecLink.1.0.80 = 3022032123335100202012013031251-32505010002 +AiPlayerbot.PremadeSpecLink.1.0.60 = 3022032023335100002012211231241 +AiPlayerbot.PremadeSpecLink.1.0.80 = 3022032023335100102012213231251-305-2033 AiPlayerbot.PremadeSpecName.1.1 = fury pve AiPlayerbot.PremadeSpecGlyph.1.1 = 43418,43395,43414,43399,49084,43432 AiPlayerbot.PremadeSpecLink.1.1.60 = -305053000500310053120501351 -AiPlayerbot.PremadeSpecLink.1.1.80 = 30202300233-305053000500310153120511351 +AiPlayerbot.PremadeSpecLink.1.1.80 = 32002300233-305053000500310153120511351 AiPlayerbot.PremadeSpecName.1.2 = prot pve AiPlayerbot.PremadeSpecGlyph.1.2 = 43424,43395,43425,43399,49084,45793 AiPlayerbot.PremadeSpecLink.1.2.60 = --053351225000210521030113321 @@ -825,8 +825,8 @@ AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112243100511351 AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112253100531351-015305021 AiPlayerbot.PremadeSpecName.3.1 = mm pve AiPlayerbot.PremadeSpecGlyph.3.1 = 42912,43350,42914,43351,43338,45732 -AiPlayerbot.PremadeSpecLink.3.1.60 = -015305101230013233125031051 -AiPlayerbot.PremadeSpecLink.3.1.80 = 502-035305101230013233135031351-5000002 +AiPlayerbot.PremadeSpecLink.3.1.60 = -025315101030013233125031051 +AiPlayerbot.PremadeSpecLink.3.1.80 = 502-025335101030013233135031351-5000002 AiPlayerbot.PremadeSpecName.3.2 = surv pve AiPlayerbot.PremadeSpecGlyph.3.2 = 42912,43350,45731,43351,43338,45732 AiPlayerbot.PremadeSpecLink.3.2.60 = --5000032500033330502135201311 @@ -910,8 +910,8 @@ AiPlayerbot.PremadeSpecLink.6.1.60 = -32003350332203012300023101351 AiPlayerbot.PremadeSpecLink.6.1.80 = -32002350352203012300033101351-230200305003 AiPlayerbot.PremadeSpecName.6.2 = unholy pve AiPlayerbot.PremadeSpecGlyph.6.2 = 43542,43673,45804,43544,43672,43549 -AiPlayerbot.PremadeSpecLink.6.2.60 = --2300303050032152000150213130051 -AiPlayerbot.PremadeSpecLink.6.2.80 = -320053500002-2300303050032152000150213130051 +AiPlayerbot.PremadeSpecLink.6.2.60 = --2301303050032151000150013113151 +AiPlayerbot.PremadeSpecLink.6.2.80 = -320033500002-2301303050032151000150013133151 AiPlayerbot.PremadeSpecName.6.3 = double aura blood pve AiPlayerbot.PremadeSpecGlyph.6.3 = 45805,43673,43827,43544,43672,43554 AiPlayerbot.PremadeSpecLink.6.3.60 = 005512153330030320102013-305 diff --git a/src/factory/StatsCollector.cpp b/src/factory/StatsCollector.cpp index 1f6c6d65..bc73fcb6 100644 --- a/src/factory/StatsCollector.cpp +++ b/src/factory/StatsCollector.cpp @@ -11,7 +11,7 @@ #include "SpellMgr.h" #include "UpdateFields.h" -StatsCollector::StatsCollector(CollectorType type) : type_(type) { Reset(); } +StatsCollector::StatsCollector(CollectorType type, int32 cls) : type_(type), cls_(cls) { Reset(); } void StatsCollector::Reset() { @@ -243,6 +243,18 @@ bool StatsCollector::SpecialSpellFilter(uint32 spellId) { case 67771: // Death's Verdict (heroic) stats[STATS_TYPE_ATTACK_POWER] += 260; return true; + case 71406: // Tiny Abomination in a Jar + if (cls_ == CLASS_PALADIN) + stats[STATS_TYPE_ATTACK_POWER] += 600; + else + stats[STATS_TYPE_ATTACK_POWER] += 150; + return true; + case 71545: // Tiny Abomination in a Jar (heroic) + if (cls_ == CLASS_PALADIN) + stats[STATS_TYPE_ATTACK_POWER] += 800; + else + stats[STATS_TYPE_ATTACK_POWER] += 200; + return true; case 71519: // Deathbringer's Will stats[STATS_TYPE_ATTACK_POWER] += 350; return true; diff --git a/src/factory/StatsCollector.h b/src/factory/StatsCollector.h index fa0634ce..b51dddf9 100644 --- a/src/factory/StatsCollector.h +++ b/src/factory/StatsCollector.h @@ -57,7 +57,7 @@ enum CollectorType : uint8 class StatsCollector { public: - StatsCollector(CollectorType type); + StatsCollector(CollectorType type, int32 cls = -1); StatsCollector(StatsCollector& stats) = default; void Reset(); void CollectItemStats(ItemTemplate const* proto); @@ -78,6 +78,7 @@ private: private: CollectorType type_; + uint32 cls_; }; #endif \ No newline at end of file diff --git a/src/factory/StatsWeightCalculator.cpp b/src/factory/StatsWeightCalculator.cpp index c3a328f0..f6270c73 100644 --- a/src/factory/StatsWeightCalculator.cpp +++ b/src/factory/StatsWeightCalculator.cpp @@ -27,10 +27,10 @@ StatsWeightCalculator::StatsWeightCalculator(Player* player) : player_(player) type_ = CollectorType::MELEE; else type_ = CollectorType::RANGED; - collector_ = std::make_unique(type_); - cls = player->getClass(); tab = AiFactory::GetPlayerSpecTab(player); + collector_ = std::make_unique(type_, cls); + if (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_UNHOLY) hitOverflowType_ = CollectorType::SPELL; @@ -128,58 +128,58 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) if (cls == CLASS_HUNTER && (tab == HUNTER_TAB_BEASTMASTER || tab == HUNTER_TAB_SURVIVAL)) { - stats_weights_[STATS_TYPE_AGILITY] += 2.4f; + stats_weights_[STATS_TYPE_AGILITY] += 2.5f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; - stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.3f; - stats_weights_[STATS_TYPE_HIT] += 1.6f; - stats_weights_[STATS_TYPE_CRIT] += 1.5f; - stats_weights_[STATS_TYPE_HASTE] += 1.4f; - stats_weights_[STATS_TYPE_RANGED_DPS] += 5.0f; + stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.5f; + stats_weights_[STATS_TYPE_HIT] += 1.7f; + stats_weights_[STATS_TYPE_CRIT] += 1.4f; + stats_weights_[STATS_TYPE_HASTE] += 1.6f; + stats_weights_[STATS_TYPE_RANGED_DPS] += 7.5f; } else if (cls == CLASS_HUNTER && tab == HUNTER_TAB_MARKSMANSHIP) { - stats_weights_[STATS_TYPE_AGILITY] += 2.2f; + stats_weights_[STATS_TYPE_AGILITY] += 2.3f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; - stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 2.2f; + stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 2.25f; stats_weights_[STATS_TYPE_HIT] += 2.1f; stats_weights_[STATS_TYPE_CRIT] += 2.0f; stats_weights_[STATS_TYPE_HASTE] += 1.8f; - stats_weights_[STATS_TYPE_RANGED_DPS] += 5.0f; + stats_weights_[STATS_TYPE_RANGED_DPS] += 10.0f; } else if (cls == CLASS_ROGUE && tab == ROGUE_TAB_COMBAT) { - stats_weights_[STATS_TYPE_AGILITY] += 1.8f; + stats_weights_[STATS_TYPE_AGILITY] += 1.9f; stats_weights_[STATS_TYPE_STRENGTH] += 1.1f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; - stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.2f; - stats_weights_[STATS_TYPE_HIT] += 2.0f; - stats_weights_[STATS_TYPE_CRIT] += 1.6f; - stats_weights_[STATS_TYPE_HASTE] += 1.4f; + stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.8f; + stats_weights_[STATS_TYPE_HIT] += 2.1f; + stats_weights_[STATS_TYPE_CRIT] += 1.4f; + stats_weights_[STATS_TYPE_HASTE] += 1.7f; stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f; - stats_weights_[STATS_TYPE_MELEE_DPS] += 5.0f; + stats_weights_[STATS_TYPE_MELEE_DPS] += 7.0f; } else if (cls == CLASS_DRUID && tab == DRUID_TAB_FERAL && !PlayerbotAI::IsTank(player)) { - stats_weights_[STATS_TYPE_AGILITY] += 2.4f; - stats_weights_[STATS_TYPE_STRENGTH] += 2.3f; + stats_weights_[STATS_TYPE_AGILITY] += 2.2f; + stats_weights_[STATS_TYPE_STRENGTH] += 2.4f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; - stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 2.1f; + stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 2.3f; stats_weights_[STATS_TYPE_HIT] += 1.9f; - stats_weights_[STATS_TYPE_CRIT] += 1.8f; - stats_weights_[STATS_TYPE_HASTE] += 1.4f; - stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f; - stats_weights_[STATS_TYPE_MELEE_DPS] += 5.0f; + stats_weights_[STATS_TYPE_CRIT] += 1.5f; + stats_weights_[STATS_TYPE_HASTE] += 2.1f; + stats_weights_[STATS_TYPE_EXPERTISE] += 2.1f; + stats_weights_[STATS_TYPE_MELEE_DPS] += 15.0f; } else if (cls == CLASS_ROGUE && (tab == ROGUE_TAB_ASSASSINATION || tab == ROGUE_TAB_SUBTLETY)) { - stats_weights_[STATS_TYPE_AGILITY] += 1.7f; + stats_weights_[STATS_TYPE_AGILITY] += 1.5f; stats_weights_[STATS_TYPE_STRENGTH] += 1.1f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; - stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.0f; - stats_weights_[STATS_TYPE_HIT] += 1.6f; - stats_weights_[STATS_TYPE_CRIT] += 1.3f; - stats_weights_[STATS_TYPE_HASTE] += 1.5f; - stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f; + stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.2f; + stats_weights_[STATS_TYPE_HIT] += 2.1f; + stats_weights_[STATS_TYPE_CRIT] += 1.1f; + stats_weights_[STATS_TYPE_HASTE] += 1.8f; + stats_weights_[STATS_TYPE_EXPERTISE] += 2.1f; stats_weights_[STATS_TYPE_MELEE_DPS] += 5.0f; } else if (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY) // fury @@ -208,70 +208,86 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player) } else if (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_FROST) // frost dk { - stats_weights_[STATS_TYPE_AGILITY] += 1.8f; - stats_weights_[STATS_TYPE_STRENGTH] += 2.6f; + stats_weights_[STATS_TYPE_AGILITY] += 1.7f; + stats_weights_[STATS_TYPE_STRENGTH] += 2.8f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; - stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 2.1f; + stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 2.7f; stats_weights_[STATS_TYPE_HIT] += 2.3f; stats_weights_[STATS_TYPE_CRIT] += 2.2f; - stats_weights_[STATS_TYPE_HASTE] += 1.8f; + stats_weights_[STATS_TYPE_HASTE] += 2.1f; stats_weights_[STATS_TYPE_EXPERTISE] += 2.5f; stats_weights_[STATS_TYPE_MELEE_DPS] += 7.0f; } else if (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_UNHOLY) { - stats_weights_[STATS_TYPE_AGILITY] += 0.5f; + stats_weights_[STATS_TYPE_AGILITY] += 0.9f; stats_weights_[STATS_TYPE_STRENGTH] += 2.5f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.0f; stats_weights_[STATS_TYPE_HIT] += 1.8f; - stats_weights_[STATS_TYPE_CRIT] += 1.0f; + stats_weights_[STATS_TYPE_CRIT] += 1.4f; stats_weights_[STATS_TYPE_HASTE] += 1.7f; - stats_weights_[STATS_TYPE_EXPERTISE] += 1.0f; + stats_weights_[STATS_TYPE_EXPERTISE] += 1.5f; stats_weights_[STATS_TYPE_MELEE_DPS] += 5.0f; } else if (cls == CLASS_PALADIN && tab == PALADIN_TAB_RETRIBUTION) // retribution { - stats_weights_[STATS_TYPE_AGILITY] += 1.3f; + stats_weights_[STATS_TYPE_AGILITY] += 1.6f; stats_weights_[STATS_TYPE_STRENGTH] += 2.5f; - stats_weights_[STATS_TYPE_INTELLECT] += 0.15f; + stats_weights_[STATS_TYPE_INTELLECT] += 0.1f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; stats_weights_[STATS_TYPE_SPELL_POWER] += 0.3f; - stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 0.7f; + stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.5f; stats_weights_[STATS_TYPE_HIT] += 1.9f; - stats_weights_[STATS_TYPE_CRIT] += 1.3f; - stats_weights_[STATS_TYPE_HASTE] += 1.2f; + stats_weights_[STATS_TYPE_CRIT] += 1.7f; + stats_weights_[STATS_TYPE_HASTE] += 1.6f; stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f; - stats_weights_[STATS_TYPE_MELEE_DPS] += 7.0f; + stats_weights_[STATS_TYPE_MELEE_DPS] += 9.0f; } else if ((cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ENHANCEMENT)) // enhancement { - stats_weights_[STATS_TYPE_AGILITY] += 1.6f; + stats_weights_[STATS_TYPE_AGILITY] += 1.4f; stats_weights_[STATS_TYPE_STRENGTH] += 1.1f; - stats_weights_[STATS_TYPE_INTELLECT] += 0.5f; + stats_weights_[STATS_TYPE_INTELLECT] += 0.3f; stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f; - stats_weights_[STATS_TYPE_SPELL_POWER] += 0.9f; - stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 1.2f; - stats_weights_[STATS_TYPE_HIT] += 1.7f; - stats_weights_[STATS_TYPE_CRIT] += 1.4f; + stats_weights_[STATS_TYPE_SPELL_POWER] += 0.95f; + stats_weights_[STATS_TYPE_ARMOR_PENETRATION] += 0.9f; + stats_weights_[STATS_TYPE_HIT] += 2.1f; + stats_weights_[STATS_TYPE_CRIT] += 1.5f; stats_weights_[STATS_TYPE_HASTE] += 1.8f; stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f; stats_weights_[STATS_TYPE_MELEE_DPS] += 8.5f; } - else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE || + else if (cls == CLASS_WARLOCK || (cls == CLASS_MAGE && tab != MAGE_TAB_FIRE) || (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW) || // shadow - (cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ELEMENTAL) || // element (cls == CLASS_DRUID && tab == DRUID_TAB_BALANCE)) // balance { - stats_weights_[STATS_TYPE_INTELLECT] += 0.5f; - stats_weights_[STATS_TYPE_SPIRIT] += 0.4f; + stats_weights_[STATS_TYPE_INTELLECT] += 0.3f; + stats_weights_[STATS_TYPE_SPIRIT] += 0.6f; stats_weights_[STATS_TYPE_SPELL_POWER] += 1.0f; - stats_weights_[STATS_TYPE_SPELL_PENETRATION] += 1.0f; stats_weights_[STATS_TYPE_HIT] += 1.1f; stats_weights_[STATS_TYPE_CRIT] += 0.8f; stats_weights_[STATS_TYPE_HASTE] += 1.0f; stats_weights_[STATS_TYPE_RANGED_DPS] += 1.0f; } + else if (cls == CLASS_MAGE && tab == MAGE_TAB_FIRE) + { + stats_weights_[STATS_TYPE_INTELLECT] += 0.3f; + stats_weights_[STATS_TYPE_SPIRIT] += 0.7f; + stats_weights_[STATS_TYPE_SPELL_POWER] += 1.0f; + stats_weights_[STATS_TYPE_HIT] += 1.2f; + stats_weights_[STATS_TYPE_CRIT] += 1.1f; + stats_weights_[STATS_TYPE_HASTE] += 0.8f; + stats_weights_[STATS_TYPE_RANGED_DPS] += 1.0f; + } + else if (cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ELEMENTAL) + { + stats_weights_[STATS_TYPE_INTELLECT] += 0.25f; + stats_weights_[STATS_TYPE_SPELL_POWER] += 1.0f; + stats_weights_[STATS_TYPE_HIT] += 1.1f; + stats_weights_[STATS_TYPE_CRIT] += 0.8f; + stats_weights_[STATS_TYPE_HASTE] += 1.0f; + } else if ((cls == CLASS_PALADIN && tab == PALADIN_TAB_HOLY) || // holy (cls == CLASS_PRIEST && tab != PRIEST_TAB_SHADOW) || // discipline / holy (cls == CLASS_SHAMAN && tab == SHAMAN_TAB_RESTORATION) || // heal @@ -349,6 +365,8 @@ void StatsWeightCalculator::GenerateAdditionalWeights(Player* player) { if (player->HasAura(34484)) stats_weights_[STATS_TYPE_INTELLECT] += 1.1f; + if (player->HasAura(56341)) + stats_weights_[STATS_TYPE_STAMINA] += 0.3f; } else if (cls == CLASS_WARRIOR) { diff --git a/src/strategy/deathknight/BloodDKStrategy.cpp b/src/strategy/deathknight/BloodDKStrategy.cpp index f76d6795..7daf494d 100644 --- a/src/strategy/deathknight/BloodDKStrategy.cpp +++ b/src/strategy/deathknight/BloodDKStrategy.cpp @@ -100,9 +100,9 @@ void BloodDKStrategy::InitTriggers(std::vector& triggers) triggers.push_back( new TriggerNode("lose aggro", NextAction::array(0, new NextAction("dark command", ACTION_HIGH + 3), nullptr))); triggers.push_back( - new TriggerNode("low health", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 5), - new NextAction("vampiric blood", ACTION_HIGH + 4), + new TriggerNode("low health", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 4), new NextAction("death strike", ACTION_HIGH + 3), nullptr))); - // triggers.push_back(new TriggerNode("army of the dead", NextAction::array(0, new NextAction("army of the dead", - // ACTION_HIGH + 6), nullptr))); + triggers.push_back( + new TriggerNode("critical health", NextAction::array(0, new NextAction("vampiric blood", ACTION_HIGH + 5), nullptr))); + } diff --git a/src/strategy/deathknight/DKAiObjectContext.cpp b/src/strategy/deathknight/DKAiObjectContext.cpp index 9023f8ac..5f7eb941 100644 --- a/src/strategy/deathknight/DKAiObjectContext.cpp +++ b/src/strategy/deathknight/DKAiObjectContext.cpp @@ -87,6 +87,8 @@ public: creators["chains of ice"] = &DeathKnightTriggerFactoryInternal::chains_of_ice; creators["unbreakable armor"] = &DeathKnightTriggerFactoryInternal::unbreakable_armor; creators["high blood rune"] = &DeathKnightTriggerFactoryInternal::high_blood_rune; + creators["high frost rune"] = &DeathKnightTriggerFactoryInternal::high_frost_rune; + creators["high unholy rune"] = &DeathKnightTriggerFactoryInternal::high_unholy_rune; creators["freezing fog"] = &DeathKnightTriggerFactoryInternal::freezing_fog; creators["no desolation"] = &DeathKnightTriggerFactoryInternal::no_desolation; creators["death and decay cooldown"] = &DeathKnightTriggerFactoryInternal::death_and_decay_cooldown; @@ -122,6 +124,8 @@ private: static Trigger* chains_of_ice(PlayerbotAI* botAI) { return new ChainsOfIceSnareTrigger(botAI); } static Trigger* unbreakable_armor(PlayerbotAI* botAI) { return new UnbreakableArmorTrigger(botAI); } static Trigger* high_blood_rune(PlayerbotAI* botAI) { return new HighBloodRuneTrigger(botAI); } + static Trigger* high_frost_rune(PlayerbotAI* botAI) { return new HighFrostRuneTrigger(botAI); } + static Trigger* high_unholy_rune(PlayerbotAI* botAI) { return new HighUnholyRuneTrigger(botAI); } static Trigger* freezing_fog(PlayerbotAI* botAI) { return new FreezingFogTrigger(botAI); } static Trigger* no_desolation(PlayerbotAI* botAI) { return new DesolationTrigger(botAI); } static Trigger* death_and_decay_cooldown(PlayerbotAI* botAI) { return new DeathAndDecayCooldownTrigger(botAI); } diff --git a/src/strategy/deathknight/DKTriggers.cpp b/src/strategy/deathknight/DKTriggers.cpp index 281ed586..ebec33cc 100644 --- a/src/strategy/deathknight/DKTriggers.cpp +++ b/src/strategy/deathknight/DKTriggers.cpp @@ -39,11 +39,18 @@ bool PestilenceGlyphTrigger::IsActive() bool HighBloodRuneTrigger::IsActive() { - // bot->Say(std::to_string(bot->GetBaseRune(0)) + "_" + std::to_string(bot->GetRuneCooldown(0)) + " " + - // std::to_string(bot->GetBaseRune(1)) + "_" + std::to_string(bot->GetRuneCooldown(1)), LANG_UNIVERSAL); return !bot->GetRuneCooldown(0) && !bot->GetRuneCooldown(1); } +bool HighFrostRuneTrigger::IsActive() +{ + return !bot->GetRuneCooldown(2) && !bot->GetRuneCooldown(3); +} + +bool HighUnholyRuneTrigger::IsActive() +{ + return !bot->GetRuneCooldown(4) && !bot->GetRuneCooldown(5); +} bool DesolationTrigger::IsActive() { return bot->HasAura(66817) && !botAI->HasAura("desolation", GetTarget(), false, true, -1, true); @@ -54,6 +61,6 @@ bool DeathAndDecayCooldownTrigger::IsActive() uint32 spellId = AI_VALUE2(uint32, "spell id", name); if (!spellId) return true; - - return bot->HasSpellCooldown(spellId); + + return bot->GetSpellCooldownDelay(spellId) >= 2000; } \ No newline at end of file diff --git a/src/strategy/deathknight/DKTriggers.h b/src/strategy/deathknight/DKTriggers.h index ecbf7964..7f6c6c81 100644 --- a/src/strategy/deathknight/DKTriggers.h +++ b/src/strategy/deathknight/DKTriggers.h @@ -139,6 +139,20 @@ public: bool IsActive() override; }; +class HighFrostRuneTrigger : public Trigger +{ +public: + HighFrostRuneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "high frost rune") {} + bool IsActive() override; +}; + +class HighUnholyRuneTrigger : public Trigger +{ +public: + HighUnholyRuneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "high unholy rune") {} + bool IsActive() override; +}; + class FreezingFogTrigger : public HasAuraTrigger { public: diff --git a/src/strategy/deathknight/FrostDKStrategy.cpp b/src/strategy/deathknight/FrostDKStrategy.cpp index 87d12b17..b05060c7 100644 --- a/src/strategy/deathknight/FrostDKStrategy.cpp +++ b/src/strategy/deathknight/FrostDKStrategy.cpp @@ -26,7 +26,7 @@ public: // creators["icebound fortitude"] = &icebound_fortitude; // creators["mind freeze"] = &mind_freeze; // creators["hungering cold"] = &hungering_cold; - // creators["unbreakable armor"] = &unbreakable_armor; + creators["unbreakable armor"] = &unbreakable_armor; // creators["improved icy talons"] = &improved_icy_talons; } @@ -70,6 +70,13 @@ private: /*A*/ nullptr, /*C*/ nullptr); } + static ActionNode* unbreakable_armor([[maybe_unused]] PlayerbotAI* botAI) + { + return new ActionNode("unbreakable armor", + /*P*/ NextAction::array(0, new NextAction("blood tap"), nullptr), + /*A*/ nullptr, + /*C*/ nullptr); + } }; FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI) @@ -80,23 +87,28 @@ FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI) NextAction** FrostDKStrategy::getDefaultActions() { return NextAction::array( - 0, 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_DEFAULT + 0.2f), + 0, new NextAction("obliterate", ACTION_DEFAULT + 0.7f), + new NextAction("frost strike", ACTION_DEFAULT + 0.4f), + new NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f), new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), new NextAction("melee", ACTION_DEFAULT), NULL); } void FrostDKStrategy::InitTriggers(std::vector& triggers) { GenericDKStrategy::InitTriggers(triggers); + + triggers.push_back(new TriggerNode( + "unbreakable armor", NextAction::array(0, new NextAction("unbreakable armor", ACTION_DEFAULT + 0.6f), nullptr))); + + triggers.push_back(new TriggerNode( + "freezing fog", NextAction::array(0, new NextAction("howling blast", ACTION_DEFAULT + 0.5f), nullptr))); + + triggers.push_back(new TriggerNode( + "high blood rune", NextAction::array(0, new NextAction("blood strike", ACTION_DEFAULT + 0.2f), nullptr))); + triggers.push_back(new TriggerNode( "army of the dead", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 6), nullptr))); - triggers.push_back(new TriggerNode( - "unbreakable armor", NextAction::array(0, new NextAction("unbreakable armor", ACTION_NORMAL + 4), nullptr))); - triggers.push_back(new TriggerNode( - "high blood rune", NextAction::array(0, new NextAction("blood strike", ACTION_NORMAL + 1), nullptr))); - triggers.push_back(new TriggerNode( - "freezing fog", NextAction::array(0, new NextAction("howling blast", ACTION_HIGH + 1), nullptr))); + // triggers.push_back(new TriggerNode("empower rune weapon", NextAction::array(0, new NextAction("empower rune // weapon", ACTION_NORMAL + 4), nullptr))); diff --git a/src/strategy/deathknight/GenericDKStrategy.cpp b/src/strategy/deathknight/GenericDKStrategy.cpp index 23693bcf..5fb8556f 100644 --- a/src/strategy/deathknight/GenericDKStrategy.cpp +++ b/src/strategy/deathknight/GenericDKStrategy.cpp @@ -135,7 +135,7 @@ private: { return new ActionNode("death and decay", /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("blood tap"), nullptr), + /*A*/ nullptr, /*C*/ nullptr); } @@ -176,18 +176,17 @@ void GenericDKStrategy::InitTriggers(std::vector& triggers) triggers.push_back( new TriggerNode("mind freeze on enemy healer", NextAction::array(0, new NextAction("mind freeze on enemy healer", ACTION_HIGH + 1), nullptr))); - triggers.push_back(new TriggerNode( - "bone shield", NextAction::array(0, new NextAction("bone shield", ACTION_NORMAL + 1), nullptr))); triggers.push_back(new TriggerNode( "horn of winter", NextAction::array(0, new NextAction("horn of winter", ACTION_NORMAL + 1), nullptr))); - // triggers.push_back(new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("reach melee", - // ACTION_NORMAL + 8), nullptr))); + triggers.push_back(new TriggerNode("critical health", + NextAction::array(0, new NextAction("death pact", ACTION_HIGH + 5), nullptr))); + triggers.push_back( new TriggerNode("low health", NextAction::array(0, new NextAction("icebound fortitude", ACTION_HIGH + 5), new NextAction("rune tap", ACTION_HIGH + 4), nullptr))); - triggers.push_back(new TriggerNode("medium health", - NextAction::array(0, new NextAction("rune tap", ACTION_NORMAL + 4), - new NextAction("death strike", ACTION_NORMAL + 3), nullptr))); + // triggers.push_back(new TriggerNode("medium health", + // NextAction::array(0, new NextAction("rune tap", ACTION_NORMAL + 4), + // new NextAction("death strike", ACTION_NORMAL + 3), nullptr))); triggers.push_back( new TriggerNode("icy touch", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 2), nullptr))); triggers.push_back( diff --git a/src/strategy/deathknight/UnholyDKStrategy.cpp b/src/strategy/deathknight/UnholyDKStrategy.cpp index a5174f36..ac106a7f 100644 --- a/src/strategy/deathknight/UnholyDKStrategy.cpp +++ b/src/strategy/deathknight/UnholyDKStrategy.cpp @@ -26,7 +26,7 @@ public: // creators["summon gargoyle"] = &army of the dead; // creators["anti magic shell"] = &anti_magic_shell; // creators["anti magic zone"] = &anti_magic_zone; - // creators["ghoul frenzy"] = &ghoul_frenzy; + creators["ghoul frenzy"] = &ghoul_frenzy; creators["corpse explosion"] = &corpse_explosion; creators["icy touch"] = &icy_touch; } @@ -35,15 +35,21 @@ private: static ActionNode* death_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode("death strike", - /*P*/ NextAction::array(0, new NextAction("unholy presence"), nullptr), + /*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), + /*A*/ nullptr, + /*C*/ nullptr); + } + static ActionNode* ghoul_frenzy([[maybe_unused]] PlayerbotAI* botAI) + { + return new ActionNode("ghoul frenzy", + /*P*/ nullptr, /*A*/ nullptr, /*C*/ nullptr); } - static ActionNode* corpse_explosion([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode("corpse explosion", - /*P*/ NextAction::array(0, new NextAction("unholy presence"), nullptr), + /*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), /*A*/ nullptr, /*C*/ nullptr); } @@ -51,14 +57,14 @@ private: static ActionNode* scourge_strike([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode("scourge strike", - /*P*/ NextAction::array(0, new NextAction("unholy presence"), nullptr), + /*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), /*A*/ nullptr, /*C*/ nullptr); } static ActionNode* icy_touch([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode("icy touch", - /*P*/ NextAction::array(0, new NextAction("unholy presence"), nullptr), + /*P*/ NextAction::array(0, new NextAction("blood presence"), nullptr), /*A*/ nullptr, /*C*/ nullptr); } @@ -72,29 +78,43 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI NextAction** UnholyDKStrategy::getDefaultActions() { return NextAction::array( - 0, new NextAction("death and decay", ACTION_DEFAULT + 0.5f), - new NextAction("horn of winter", ACTION_DEFAULT + 0.4f), - new NextAction("summon gargoyle", ACTION_DEFAULT + 0.3f), new NextAction("death coil", ACTION_DEFAULT + 0.2f), - new NextAction("scourge strike", ACTION_NORMAL + 0.1f), new NextAction("melee", ACTION_DEFAULT), nullptr); + 0, new NextAction("death and decay", ACTION_DEFAULT + 1.0f), + new NextAction("summon gargoyle", ACTION_DEFAULT + 0.4f), + new NextAction("empower rune weapon", ACTION_DEFAULT + 0.3f), + new NextAction("death coil", ACTION_DEFAULT + 0.2f), + new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), nullptr); } void UnholyDKStrategy::InitTriggers(std::vector& triggers) { GenericDKStrategy::InitTriggers(triggers); + triggers.push_back(new TriggerNode( + "death and decay cooldown", NextAction::array(0, + new NextAction("ghoul frenzy", ACTION_DEFAULT + 0.9f), + new NextAction("scourge strike", ACTION_DEFAULT + 0.8f), + new NextAction("blood boil", ACTION_DEFAULT + 0.7f), + new NextAction("icy touch", ACTION_DEFAULT + 0.6f), + nullptr))); + + triggers.push_back(new TriggerNode( + "high frost rune", NextAction::array(0, new NextAction("icy touch", ACTION_DEFAULT + 0.6f), nullptr))); + + triggers.push_back(new TriggerNode( + "high unholy rune", NextAction::array(0, + new NextAction("ghoul frenzy", ACTION_DEFAULT + 0.9f), + new NextAction("plague strike", ACTION_DEFAULT + 0.5f), nullptr))); + + triggers.push_back(new TriggerNode( + "high blood rune", NextAction::array(0, new NextAction("blood boil", ACTION_DEFAULT + 0.7f), nullptr))); // triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction(, ACTION_NORMAL + 2), nullptr))); triggers.push_back(new TriggerNode( "army of the dead", NextAction::array(0, new NextAction("army of the dead", ACTION_HIGH + 6), nullptr))); - triggers.push_back(new TriggerNode("critical health", - NextAction::array(0, new NextAction("death pact", ACTION_HIGH + 5), nullptr))); triggers.push_back(new TriggerNode("no desolation", NextAction::array(0, new NextAction("blood strike", ACTION_HIGH + 4), nullptr))); - triggers.push_back(new TriggerNode( - "death and decay cooldown", NextAction::array(0, new NextAction("ghoul frenzy", ACTION_NORMAL + 5.0f), - new NextAction("scourge strike", ACTION_NORMAL + 4.0f), - new NextAction("blood boil", ACTION_NORMAL + 3.0f), - new NextAction("icy touch", ACTION_NORMAL + 2.0f), - new NextAction("plague strike", ACTION_NORMAL + 1.0f), nullptr))); + triggers.push_back( + new TriggerNode("bone shield", NextAction::array(0, new NextAction("bone shield", ACTION_HIGH + 1), nullptr))); } void UnholyDKAoeStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/values/Arrow.cpp b/src/strategy/values/Arrow.cpp index f52dc670..0a8afb50 100644 --- a/src/strategy/values/Arrow.cpp +++ b/src/strategy/values/Arrow.cpp @@ -46,14 +46,14 @@ WorldLocation ArrowFormation::GetLocationInternal() float x = master->GetPositionX() - masterUnit->GetX() + botUnit->GetX(); float y = master->GetPositionY() - masterUnit->GetY() + botUnit->GetY(); - float z = master->GetPositionZ(); + float z = master->GetPositionZ() + master->GetHoverHeight(); if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) { x = master->GetPositionX() - masterUnit->GetX() + botUnit->GetX(); y = master->GetPositionY() - masterUnit->GetY() + botUnit->GetY(); z = master->GetPositionZ() + master->GetHoverHeight(); - z = master->GetMapHeight(x, y, z); + master->UpdateAllowedPositionZ(x, y, z); } return WorldLocation(master->GetMapId(), x, y, z); } diff --git a/src/strategy/values/Formations.cpp b/src/strategy/values/Formations.cpp index 9854b420..8c918c56 100644 --- a/src/strategy/values/Formations.cpp +++ b/src/strategy/values/Formations.cpp @@ -88,7 +88,7 @@ public: float angle = GetFollowAngle(); float x = master->GetPositionX() + cos(angle) * range; float y = master->GetPositionY() + sin(angle) * range; - float z = master->GetPositionZ(); + float z = master->GetPositionZ() + master->GetHoverHeight(); if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) { @@ -138,15 +138,14 @@ public: float x = master->GetPositionX() + cos(angle) * range + dx; float y = master->GetPositionY() + sin(angle) * range + dy; - float z = master->GetPositionZ(); - z = bot->GetMapHeight(x, y, z + 5.0f); + float z = master->GetPositionZ() + master->GetHoverHeight(); if (!master->GetMap()->CheckCollisionAndGetValidCoords( master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) { x = master->GetPositionX() + cos(angle) * range + dx; y = master->GetPositionY() + sin(angle) * range + dy; z = master->GetPositionZ() + master->GetHoverHeight(); - z = master->GetMapHeight(x, y, z); + master->UpdateAllowedPositionZ(x, y, z); } // bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), // bot->GetPositionZ(), x, y, z); @@ -155,15 +154,14 @@ public: float x = master->GetPositionX() + cos(angle) * range + dx; float y = master->GetPositionY() + sin(angle) * range + dy; - float z = master->GetPositionZ(); - z = bot->GetMapHeight(x, y, z + 5.0f); + float z = master->GetPositionZ() + master->GetHoverHeight(); if (!master->GetMap()->CheckCollisionAndGetValidCoords(master, master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), x, y, z)) { x = master->GetPositionX() + cos(angle) * range + dx; y = master->GetPositionY() + sin(angle) * range + dy; z = master->GetPositionZ() + master->GetHoverHeight(); - z = master->GetMapHeight(x, y, z); + master->UpdateAllowedPositionZ(x, y, z); } return WorldLocation(master->GetMapId(), x, y, z); } @@ -221,8 +219,8 @@ public: { x = target->GetPositionX() + cos(angle) * range; y = target->GetPositionY() + sin(angle) * range; - z = target->GetPositionZ() + target->GetHoverHeight(); - z = target->GetMapHeight(x, y, z); + z = target->GetPositionZ(); + target->UpdateAllowedPositionZ(x, y, z); } return WorldLocation(bot->GetMapId(), x, y, z); } @@ -389,7 +387,7 @@ public: x = master->GetPositionX() + cos(angle) * range + cos(followAngle) * followRange; y = master->GetPositionY() + sin(angle) * range + sin(followAngle) * followRange; z = master->GetPositionZ() + master->GetHoverHeight(); - z = master->GetMapHeight(x, y, z); + master->UpdateAllowedPositionZ(x, y, z); } return WorldLocation(bot->GetMapId(), minX, minY, z); } @@ -403,7 +401,7 @@ public: x = master->GetPositionX() + cos(angle) * range + cos(followAngle) * followRange; y = master->GetPositionY() + sin(angle) * range + sin(followAngle) * followRange; z = master->GetPositionZ() + master->GetHoverHeight(); - z = master->GetMapHeight(x, y, z); + master->UpdateAllowedPositionZ(x, y, z); } return WorldLocation(bot->GetMapId(), x, y, z); } diff --git a/src/strategy/warrior/ArmsWarriorStrategy.cpp b/src/strategy/warrior/ArmsWarriorStrategy.cpp index bf56e891..540b6cd0 100644 --- a/src/strategy/warrior/ArmsWarriorStrategy.cpp +++ b/src/strategy/warrior/ArmsWarriorStrategy.cpp @@ -34,8 +34,9 @@ ArmsWarriorStrategy::ArmsWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr NextAction** ArmsWarriorStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("bladestorm", ACTION_DEFAULT + 0.1f), - new NextAction("melee", ACTION_DEFAULT), nullptr); + return NextAction::array(0, new NextAction("bladestorm", ACTION_DEFAULT + 0.2f), + new NextAction("mortal strike", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), nullptr); } void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) @@ -63,9 +64,8 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode( "victory rush", NextAction::array(0, new NextAction("victory rush", ACTION_INTERRUPT), nullptr))); triggers.push_back(new TriggerNode( - "medium rage available", NextAction::array(0, new NextAction("heroic strike", ACTION_HIGH + 10), nullptr))); - /*triggers.push_back(new TriggerNode("high rage available", NextAction::array(0, new NextAction("slam", ACTION_HIGH - * + 1), nullptr)));*/ + "high rage available", NextAction::array(0, new NextAction("heroic strike", ACTION_HIGH + 10), nullptr))); + triggers.push_back(new TriggerNode("medium rage available", NextAction::array(0, new NextAction("slam", ACTION_HIGH + 1), nullptr))); triggers.push_back( new TriggerNode("bloodrage", NextAction::array(0, new NextAction("bloodrage", ACTION_HIGH + 2), nullptr))); triggers.push_back( @@ -75,6 +75,6 @@ void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) "rend on attacker", NextAction::array(0, new NextAction("rend on attacker", ACTION_HIGH + 5), nullptr))); triggers.push_back(new TriggerNode( "critical health", NextAction::array(0, new NextAction("intimidating shout", ACTION_EMERGENCY), nullptr))); - triggers.push_back(new TriggerNode("medium rage available", + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("thunder clap", ACTION_HIGH + 1), nullptr))); }