diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 7d225da3..8abae51e 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -306,6 +306,16 @@ AiPlayerbot.LowMana = 15 AiPlayerbot.MediumMana = 40 # Random bot default strategies (applied after defaults) + +# Enable healer bot save mana +# Default: 1 (enable) +AiPlayerbot.AutoSaveMana = 1 + +# Healer bot save mana threshold +# Default: 60 (60%) +AiPlayerbot.SaveManaThreshold = 60 + + AiPlayerbot.RandomBotCombatStrategies = "+dps,+dps assist,-threat" # AiPlayerbot.RandomBotNonCombatStrategies = "+grind,+loot,+rpg,+custom::say" AiPlayerbot.RandomBotNonCombatStrategies = "" diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index 0860c59b..12beba33 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -6,6 +6,7 @@ #include "BattlegroundMgr.h" #include "Item.h" #include "PlayerbotAI.h" +#include "PlayerbotAIConfig.h" #include "Playerbots.h" #include "Engine.h" #include "Group.h" @@ -265,7 +266,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa { engine->addStrategies("racials", "chat", "default", "cast time", "duel", "boost", nullptr); } - + if (sPlayerbotAIConfig->autoSaveMana) { + engine->addStrategy("auto save mana"); + } switch (player->getClass()) { case CLASS_PRIEST: @@ -273,8 +276,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa { engine->addStrategies("dps", "shadow debuff", "shadow aoe", "threat", nullptr); } - else + else { engine->addStrategies("heal", "threat", nullptr); + } engine->addStrategies("dps assist", "cure", nullptr); break; @@ -426,7 +430,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa engine->addStrategy("arena"); } - engine->addStrategies("boost", "racials", "chat", "default", "aoe", "potions", "conserve mana", "cast time", "dps assist", nullptr); + engine->addStrategies("boost", "racials", "chat", "default", "aoe", "potions", "cast time", "dps assist", nullptr); engine->removeStrategy("custom::say"); engine->removeStrategy("flee"); engine->removeStrategy("threat"); @@ -532,7 +536,9 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const nonCombatEngine->addStrategies("nc", "food", "chat", "follow", "default", "quest", "loot", "gather", "duel", "buff", "mount", nullptr); } - + if (sPlayerbotAIConfig->autoSaveMana) { + nonCombatEngine->addStrategy("auto save mana"); + } if ((facade->IsRealPlayer() || sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground()) { Player* master = facade->GetMaster(); diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index d0e44032..0d86bc4f 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -88,6 +88,8 @@ bool PlayerbotAIConfig::Initialize() almostFullHealth = sConfigMgr->GetOption("AiPlayerbot.AlmostFullHealth", 85); lowMana = sConfigMgr->GetOption("AiPlayerbot.LowMana", 15); mediumMana = sConfigMgr->GetOption("AiPlayerbot.MediumMana", 40); + autoSaveMana = sConfigMgr->GetOption("AiPlayerbot.AutoSaveMana", true); + saveManaThreshold = sConfigMgr->GetOption("AiPlayerbot.SaveManaThreshold", 60); randomGearLoweringChance = sConfigMgr->GetOption("AiPlayerbot.RandomGearLoweringChance", 0.15f); randomBotMaxLevelChance = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLevelChance", 0.15f); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index d43e457c..9f4ae250 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -23,6 +23,16 @@ enum class BotCheatMask : uint32 maxMask = 32 }; +enum class HealingManaEfficiency : uint8 +{ + VERY_LOW = 1, + LOW = 2, + MEDIUM = 4, + HIGH = 8, + VERY_HIGH = 16, + SUPERIOR = 32 +}; + #define MAX_SPECNO 20 class PlayerbotAIConfig @@ -51,6 +61,8 @@ class PlayerbotAIConfig aoeRadius, rpgDistance, targetPosRecalcDistance, farDistance, healDistance, aggroDistance; uint32 criticalHealth, lowHealth, mediumHealth, almostFullHealth; uint32 lowMana, mediumMana; + bool autoSaveMana; + uint32 saveManaThreshold; uint32 openGoSpell; bool randomBotAutologin; diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index ba04119d..4479a396 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -121,7 +121,7 @@ void PlayerbotFactory::Init() // continue; enchantSpellIdCache.push_back(id); - LOG_INFO("playerbots", "Add {} to enchantment spells", id); + // LOG_INFO("playerbots", "Add {} to enchantment spells", id); } } LOG_INFO("playerbots", "Loading {} enchantment spells", enchantSpellIdCache.size()); diff --git a/src/strategy/AiObject.h b/src/strategy/AiObject.h index ec78779e..ca28b42c 100644 --- a/src/strategy/AiObject.h +++ b/src/strategy/AiObject.h @@ -302,14 +302,14 @@ class clazz : public CastHealingSpellAction \ bool isUseful() override { return useful; } \ } -#define HEAL_PARTY_ACTION(clazz, spell) \ +#define HEAL_PARTY_ACTION(clazz, spell, estAmount, manaEfficiency) \ class clazz : public HealPartyMemberAction \ { \ public: \ - clazz(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, spell) { } \ + clazz(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, spell, estAmount, manaEfficiency) { } \ } -#define AOE_HEAL_ACTION(clazz, spell) \ +#define AOE_HEAL_ACTION(clazz, spell, estAmount, manaEfficiency) \ class clazz : public CastAoeHealSpellAction \ { \ public: \ diff --git a/src/strategy/StrategyContext.h b/src/strategy/StrategyContext.h index 0de14d19..e87982c6 100644 --- a/src/strategy/StrategyContext.h +++ b/src/strategy/StrategyContext.h @@ -58,7 +58,8 @@ class StrategyContext : public NamedObjectContext creators["gather"] = &StrategyContext::gather; creators["emote"] = &StrategyContext::emote; creators["passive"] = &StrategyContext::passive; - creators["conserve mana"] = &StrategyContext::conserve_mana; + // creators["conserve mana"] = &StrategyContext::conserve_mana; + creators["auto save mana"] = &StrategyContext::auto_save_mana; creators["food"] = &StrategyContext::food; creators["chat"] = &StrategyContext::chat; creators["default"] = &StrategyContext::world_packet; @@ -131,7 +132,8 @@ class StrategyContext : public NamedObjectContext static Strategy* gather(PlayerbotAI* botAI) { return new GatherStrategy(botAI); } static Strategy* emote(PlayerbotAI* botAI) { return new EmoteStrategy(botAI); } static Strategy* passive(PlayerbotAI* botAI) { return new PassiveStrategy(botAI); } - static Strategy* conserve_mana(PlayerbotAI* botAI) { return new ConserveManaStrategy(botAI); } + // static Strategy* conserve_mana(PlayerbotAI* botAI) { return new ConserveManaStrategy(botAI); } + static Strategy* auto_save_mana(PlayerbotAI* botAI) { return new HealerAutoSaveManaStrategy(botAI); } static Strategy* food(PlayerbotAI* botAI) { return new UseFoodStrategy(botAI); } static Strategy* chat(PlayerbotAI* botAI) { return new ChatCommandHandlerStrategy(botAI); } static Strategy* world_packet(PlayerbotAI* botAI) { return new WorldPacketHandlerStrategy(botAI); } diff --git a/src/strategy/actions/GenericSpellActions.cpp b/src/strategy/actions/GenericSpellActions.cpp index 7309ee7f..24700d5e 100644 --- a/src/strategy/actions/GenericSpellActions.cpp +++ b/src/strategy/actions/GenericSpellActions.cpp @@ -151,7 +151,8 @@ bool CastEnchantItemAction::isPossible() return spellId && AI_VALUE2(Item*, "item for spell", spellId); } -CastHealingSpellAction::CastHealingSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount) : CastAuraSpellAction(botAI, spell, true), estAmount(estAmount) +CastHealingSpellAction::CastHealingSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount, HealingManaEfficiency manaEfficiency) + : CastAuraSpellAction(botAI, spell, true), estAmount(estAmount), manaEfficiency(manaEfficiency) { range = botAI->GetRange("heal"); } diff --git a/src/strategy/actions/GenericSpellActions.h b/src/strategy/actions/GenericSpellActions.h index 3d8e887e..e0389e51 100644 --- a/src/strategy/actions/GenericSpellActions.h +++ b/src/strategy/actions/GenericSpellActions.h @@ -98,20 +98,23 @@ class CastEnchantItemAction : public CastSpellAction class CastHealingSpellAction : public CastAuraSpellAction { public: - CastHealingSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount = 15.0f); + CastHealingSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount = 15.0f, HealingManaEfficiency manaEfficiency = HealingManaEfficiency::MEDIUM); std::string const GetTargetName() override { return "self target"; } bool isUseful() override; ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } - - protected: + // Yunfan: Mana efficiency tell the bot how to save mana. The higher the better. + HealingManaEfficiency manaEfficiency; uint8 estAmount; + + // protected: }; class CastAoeHealSpellAction : public CastHealingSpellAction { public: - CastAoeHealSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount = 15.0f) : CastHealingSpellAction(botAI, spell, estAmount) { } + CastAoeHealSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount = 15.0f, HealingManaEfficiency manaEfficiency = HealingManaEfficiency::MEDIUM) + : CastHealingSpellAction(botAI, spell, estAmount, manaEfficiency) { } std::string const GetTargetName() override { return "party member to heal"; } bool isUseful() override; @@ -142,8 +145,8 @@ class PartyMemberActionNameSupport class HealPartyMemberAction : public CastHealingSpellAction, public PartyMemberActionNameSupport { public: - HealPartyMemberAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount = 15.0f) : - CastHealingSpellAction(botAI, spell, estAmount), PartyMemberActionNameSupport(spell) { } + HealPartyMemberAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount = 15.0f, HealingManaEfficiency manaEfficiency = HealingManaEfficiency::MEDIUM) : + CastHealingSpellAction(botAI, spell, estAmount, manaEfficiency), PartyMemberActionNameSupport(spell) { } std::string const GetTargetName() override { return "party member to heal"; } std::string const getName() override { return PartyMemberActionNameSupport::getName(); } diff --git a/src/strategy/druid/DruidActions.h b/src/strategy/druid/DruidActions.h index 92a11069..3ae7efb0 100644 --- a/src/strategy/druid/DruidActions.h +++ b/src/strategy/druid/DruidActions.h @@ -46,19 +46,19 @@ class CastHealingTouchAction : public CastHealingSpellAction class CastRejuvenationOnPartyAction : public HealPartyMemberAction { public: - CastRejuvenationOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "rejuvenation") { } + CastRejuvenationOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "rejuvenation", 15.0f, HealingManaEfficiency::VERY_HIGH) { } }; class CastRegrowthOnPartyAction : public HealPartyMemberAction { public: - CastRegrowthOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "regrowth") { } + CastRegrowthOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "regrowth", 35.0f, HealingManaEfficiency::HIGH) { } }; class CastHealingTouchOnPartyAction : public HealPartyMemberAction { public: - CastHealingTouchOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "healing touch") { } + CastHealingTouchOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "healing touch", 50.0f, HealingManaEfficiency::LOW) { } }; class CastReviveAction : public ResurrectPartyMemberAction @@ -242,7 +242,7 @@ class CastInnervateAction : public CastSpellAction class CastTranquilityAction : public CastAoeHealSpellAction { public: - CastTranquilityAction(PlayerbotAI* botAI) : CastAoeHealSpellAction(botAI, "tranquility") { } + CastTranquilityAction(PlayerbotAI* botAI) : CastAoeHealSpellAction(botAI, "tranquility", 15.0f, HealingManaEfficiency::MEDIUM) { } }; class CastNaturesSwiftnessAction : public CastBuffSpellAction @@ -254,19 +254,19 @@ class CastNaturesSwiftnessAction : public CastBuffSpellAction class CastWildGrowthOnPartyAction : public HealPartyMemberAction { public: - CastWildGrowthOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "wild growth") {} + CastWildGrowthOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "wild growth", 15.0f, HealingManaEfficiency::VERY_HIGH) {} }; class CastPartySwiftmendAction : public HealPartyMemberAction { public: - CastPartySwiftmendAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "swiftmend") {} + CastPartySwiftmendAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "swiftmend", 15.0f, HealingManaEfficiency::MEDIUM) {} }; class CastPartyNourishAction : public HealPartyMemberAction { public: - CastPartyNourishAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "nourish") {} + CastPartyNourishAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "nourish", 25.0f, HealingManaEfficiency::LOW) {} }; class CastDruidRemoveCurseOnPartyAction : public CurePartyMemberAction diff --git a/src/strategy/generic/ConserveManaStrategy.cpp b/src/strategy/generic/ConserveManaStrategy.cpp index ab2d008e..c20a7da5 100644 --- a/src/strategy/generic/ConserveManaStrategy.cpp +++ b/src/strategy/generic/ConserveManaStrategy.cpp @@ -5,83 +5,122 @@ #include "ConserveManaStrategy.h" #include "GenericSpellActions.h" #include "LastSpellCastValue.h" +#include "PlayerbotAIConfig.h" #include "Playerbots.h" -float ConserveManaMultiplier::GetValue(Action* action) +// float ConserveManaMultiplier::GetValue(Action* action) +// { +// if (!action) +// return 1.0f; + +// uint8 health = AI_VALUE2(uint8, "health", "self target"); +// uint8 targetHealth = AI_VALUE2(uint8, "health", "current target"); +// uint8 mana = AI_VALUE2(uint8, "mana", "self target"); +// bool hasMana = AI_VALUE2(bool, "has mana", "self target"); +// bool mediumMana = hasMana && mana < sPlayerbotAIConfig->mediumMana; + +// if (health < sPlayerbotAIConfig->lowHealth) +// return 1.0f; + +// Unit* target = AI_VALUE(Unit*, "current target"); +// if (action->GetTarget() != target) +// return 1.0f; + +// CastSpellAction* spellAction = dynamic_cast(action); +// if (!spellAction) +// return 1.0f; + +// std::string const spell = spellAction->getName(); +// uint32 spellId = AI_VALUE2(uint32, "spell id", spell); +// SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); +// if (!spellInfo || spellInfo->PowerType != POWER_MANA) +// return 1.0f; + +// if (mediumMana && dynamic_cast(action)) +// return 0.0f; + +// if (target && ((int)target->getLevel() - (int)bot->getLevel()) >= 0) +// return 1.0f; + +// return 1.0f; +// } + +// float SaveManaMultiplier::GetValue(Action* action) +// { +// if (!action) +// return 1.0f; + +// if (action->GetTarget() != AI_VALUE(Unit*, "current target")) +// return 1.0f; + +// double saveLevel = AI_VALUE(double, "mana save level"); +// if (saveLevel <= 1.0) +// return 1.0f; + +// CastSpellAction* spellAction = dynamic_cast(action); +// if (!spellAction) +// return 1.0f; + +// std::string const spell = spellAction->getName(); +// uint32 spellId = AI_VALUE2(uint32, "spell id", spell); +// SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); +// if (!spellInfo || spellInfo->PowerType != POWER_MANA) +// return 1.0f; + +// int32 cost = spellInfo->ManaCost; +// if (!cost) +// return 1.0f; + +// time_t lastCastTime = AI_VALUE2(time_t, "last spell cast time", spell); +// if (!lastCastTime) +// return 1.0f; + +// time_t elapsed = time(nullptr) - lastCastTime; +// if ((double)elapsed < 10 * saveLevel) +// return 0.0f; + +// return 1.0f; +// } + +// void ConserveManaStrategy::InitMultipliers(std::vector& multipliers) +// { +// multipliers.push_back(new ConserveManaMultiplier(botAI)); +// } + +float HealerAutoSaveManaMultiplier::GetValue(Action* action) { - if (!action) + uint8 mana = bot->GetPowerPct(Powers::POWER_MANA); + if (mana > sPlayerbotAIConfig->saveManaThreshold) return 1.0f; + CastHealingSpellAction* healingAction = dynamic_cast(action); - uint8 health = AI_VALUE2(uint8, "health", "self target"); - uint8 targetHealth = AI_VALUE2(uint8, "health", "current target"); - uint8 mana = AI_VALUE2(uint8, "mana", "self target"); - bool hasMana = AI_VALUE2(bool, "has mana", "self target"); - bool mediumMana = hasMana && mana < sPlayerbotAIConfig->mediumMana; - - if (health < sPlayerbotAIConfig->lowHealth) + if (!healingAction) return 1.0f; - - Unit* target = AI_VALUE(Unit*, "current target"); - if (action->GetTarget() != target) + + Unit* target = healingAction->GetTarget(); + if (!target) return 1.0f; - - CastSpellAction* spellAction = dynamic_cast(action); - if (!spellAction) - return 1.0f; - - std::string const spell = spellAction->getName(); - uint32 spellId = AI_VALUE2(uint32, "spell id", spell); - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo || spellInfo->PowerType != POWER_MANA) - return 1.0f; - - if (mediumMana && dynamic_cast(action)) - return 0.0f; - - if (target && ((int)target->getLevel() - (int)bot->getLevel()) >= 0) - return 1.0f; - + bool isTank = target->ToPlayer() ? botAI->IsTank(target->ToPlayer()) : false; + uint8 health = target->GetHealthPct(); + HealingManaEfficiency manaEfficiency = healingAction->manaEfficiency; + uint8 estAmount = healingAction->estAmount; + uint8 lossAmount = 100 - health; + if (isTank) { + estAmount /= 1.5; // tanks have more health + if (health >= sPlayerbotAIConfig->mediumHealth && (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::MEDIUM)) + return 0.0f; + if (health >= sPlayerbotAIConfig->lowHealth && (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::LOW)) + return 0.0f; + } else { + if (health >= sPlayerbotAIConfig->mediumHealth && (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::MEDIUM)) + return 0.0f; + if (lossAmount < estAmount || manaEfficiency <= HealingManaEfficiency::LOW) + return 0.0f; + } return 1.0f; } -float SaveManaMultiplier::GetValue(Action* action) +void HealerAutoSaveManaStrategy::InitMultipliers(std::vector& multipliers) { - if (!action) - return 1.0f; - - if (action->GetTarget() != AI_VALUE(Unit*, "current target")) - return 1.0f; - - double saveLevel = AI_VALUE(double, "mana save level"); - if (saveLevel <= 1.0) - return 1.0f; - - CastSpellAction* spellAction = dynamic_cast(action); - if (!spellAction) - return 1.0f; - - std::string const spell = spellAction->getName(); - uint32 spellId = AI_VALUE2(uint32, "spell id", spell); - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo || spellInfo->PowerType != POWER_MANA) - return 1.0f; - - int32 cost = spellInfo->ManaCost; - if (!cost) - return 1.0f; - - time_t lastCastTime = AI_VALUE2(time_t, "last spell cast time", spell); - if (!lastCastTime) - return 1.0f; - - time_t elapsed = time(nullptr) - lastCastTime; - if ((double)elapsed < 10 * saveLevel) - return 0.0f; - - return 1.0f; -} - -void ConserveManaStrategy::InitMultipliers(std::vector& multipliers) -{ - multipliers.push_back(new ConserveManaMultiplier(botAI)); -} + multipliers.push_back(new HealerAutoSaveManaMultiplier(botAI)); +} \ No newline at end of file diff --git a/src/strategy/generic/ConserveManaStrategy.h b/src/strategy/generic/ConserveManaStrategy.h index d4def601..9ad9a277 100644 --- a/src/strategy/generic/ConserveManaStrategy.h +++ b/src/strategy/generic/ConserveManaStrategy.h @@ -9,29 +9,57 @@ class PlayerbotAI; -class ConserveManaMultiplier : public Multiplier +// Yunfan: deprecate old save mana method. + +// class ConserveManaMultiplier : public Multiplier +// { +// public: +// ConserveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "conserve mana") { } + +// float GetValue(Action* action) override; +// }; + +// class SaveManaMultiplier : public Multiplier +// { +// public: +// SaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "save mana") { } + +// float GetValue(Action* action) override; +// }; + +// class ConserveManaStrategy : public Strategy +// { +// public: +// ConserveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) { } + +// void InitMultipliers(std::vector& multipliers) override; +// std::string const getName() override { return "conserve mana"; } +// }; + +// class HealerSaveManaStrategy : public Strategy +// { +// public: +// HealerSaveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) { } + +// void InitMultipliers(std::vector& multipliers) override; +// std::string const getName() override { return "healer save mana"; } +// }; + +class HealerAutoSaveManaMultiplier : public Multiplier { public: - ConserveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "conserve mana") { } + HealerAutoSaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "auto save mana") { } float GetValue(Action* action) override; }; -class SaveManaMultiplier : public Multiplier +class HealerAutoSaveManaStrategy : public Strategy { public: - SaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "save mana") { } - - float GetValue(Action* action) override; -}; - -class ConserveManaStrategy : public Strategy -{ - public: - ConserveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) { } + HealerAutoSaveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) { } void InitMultipliers(std::vector& multipliers) override; - std::string const getName() override { return "conserve mana"; } + std::string const getName() override { return "auto save mana"; } }; #endif diff --git a/src/strategy/paladin/PaladinActions.h b/src/strategy/paladin/PaladinActions.h index 9c764aff..0afc9c71 100644 --- a/src/strategy/paladin/PaladinActions.h +++ b/src/strategy/paladin/PaladinActions.h @@ -39,7 +39,6 @@ BUFF_ACTION(CastCrusaderAuraAction, "crusader aura"); BUFF_ACTION(CastSanctityAuraAction, "sanctity aura"); SPELL_ACTION(CastHolyShockAction, "holy shock"); -HEAL_PARTY_ACTION(CastHolyShockOnPartyAction, "holy shock"); // consecration MELEE_ACTION(CastConsecrationAction, "consecration"); @@ -168,10 +167,16 @@ class CastHolyLightAction : public CastHealingSpellAction CastHolyLightAction(PlayerbotAI* botAI) : CastHealingSpellAction(botAI, "holy light") { } }; +class CastHolyShockOnPartyAction : public HealPartyMemberAction +{ + public: + CastHolyShockOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "holy shock", 25.0f, HealingManaEfficiency::MEDIUM) { } +}; + class CastHolyLightOnPartyAction : public HealPartyMemberAction { public: - CastHolyLightOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "holy light") { } + CastHolyLightOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "holy light", 50.0f, HealingManaEfficiency::HIGH) { } }; class CastFlashOfLightAction : public CastHealingSpellAction @@ -183,7 +188,7 @@ class CastFlashOfLightAction : public CastHealingSpellAction class CastFlashOfLightOnPartyAction : public HealPartyMemberAction { public: - CastFlashOfLightOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "flash of light") { } + CastFlashOfLightOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "flash of light", 15.0f, HealingManaEfficiency::LOW) { } }; class CastLayOnHandsAction : public CastHealingSpellAction diff --git a/src/strategy/priest/PriestActions.cpp b/src/strategy/priest/PriestActions.cpp index 9b49d2fe..079d4efd 100644 --- a/src/strategy/priest/PriestActions.cpp +++ b/src/strategy/priest/PriestActions.cpp @@ -39,12 +39,12 @@ Unit* CastPowerWordShieldOnAlmostFullHealthBelow::GetTarget() if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance) { continue; } - if (botAI->HasAnyAuraOf(player, "weakened soul", "power word: shield", NULL)) { + if (botAI->HasAnyAuraOf(player, "weakened soul", "power word: shield", nullptr)) { continue; } return player; } - return NULL; + return nullptr; } bool CastPowerWordShieldOnAlmostFullHealthBelow::isUseful() @@ -64,7 +64,7 @@ bool CastPowerWordShieldOnAlmostFullHealthBelow::isUseful() if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance) { continue; } - if (botAI->HasAnyAuraOf(player, "weakened soul", "power word: shield", NULL)) { + if (botAI->HasAnyAuraOf(player, "weakened soul", "power word: shield", nullptr)) { continue; } return true; diff --git a/src/strategy/priest/PriestActions.h b/src/strategy/priest/PriestActions.h index cb1a84eb..9aab4eb3 100644 --- a/src/strategy/priest/PriestActions.h +++ b/src/strategy/priest/PriestActions.h @@ -6,6 +6,7 @@ #define _PLAYERBOT_PRIESTACTIONS_H #include "GenericSpellActions.h" +#include "PlayerbotAIConfig.h" #include "Playerbots.h" class PlayerbotAI; @@ -15,7 +16,7 @@ BUFF_ACTION(CastPowerWordFortitudeAction, "power word: fortitude"); BUFF_PARTY_ACTION(CastPowerWordFortitudeOnPartyAction, "power word: fortitude"); BUFF_PARTY_ACTION(CastPrayerOfFortitudeOnPartyAction, "prayer of fortitude"); BUFF_ACTION(CastPowerWordShieldAction, "power word: shield"); -HEAL_PARTY_ACTION(CastPowerWordShieldOnPartyAction, "power word: shield"); + BUFF_ACTION(CastInnerFireAction, "inner fire"); CURE_ACTION(CastDispelMagicAction, "dispel magic"); CURE_PARTY_ACTION(CastDispelMagicOnPartyAction, "dispel magic", DISPEL_MAGIC); @@ -39,22 +40,21 @@ PROTECT_ACTION(CastPainSuppressionProtectAction, "pain suppression"); // holy HEAL_ACTION(CastLesserHealAction, "lesser heal"); -HEAL_PARTY_ACTION(CastLesserHealOnPartyAction, "lesser heal"); HEAL_ACTION(CastHealAction, "heal"); -HEAL_PARTY_ACTION(CastHealOnPartyAction, "heal"); HEAL_ACTION(CastGreaterHealAction, "greater heal"); -HEAL_PARTY_ACTION(CastGreaterHealOnPartyAction, "greater heal"); HEAL_ACTION(CastFlashHealAction, "flash heal"); -HEAL_PARTY_ACTION(CastFlashHealOnPartyAction, "flash heal"); HEAL_ACTION(CastRenewAction, "renew"); -HEAL_PARTY_ACTION(CastRenewOnPartyAction, "renew"); -// holy 2.4.3 -HEAL_PARTY_ACTION(CastPrayerOfMendingAction, "prayer of mending"); -HEAL_PARTY_ACTION(CastBindingHealAction, "binding heal"); - -HEAL_PARTY_ACTION(CastPrayerOfHealingAction, "prayer of healing"); -AOE_HEAL_ACTION(CastLightwellAction, "lightwell"); -AOE_HEAL_ACTION(CastCircleOfHealingAction, "circle of healing"); +HEAL_PARTY_ACTION(CastLesserHealOnPartyAction, "lesser heal", 50.0f, HealingManaEfficiency::MEDIUM); +HEAL_PARTY_ACTION(CastHealOnPartyAction, "heal", 50.0f, HealingManaEfficiency::MEDIUM); +HEAL_PARTY_ACTION(CastGreaterHealOnPartyAction, "greater heal", 50.0f, HealingManaEfficiency::MEDIUM); +HEAL_PARTY_ACTION(CastPowerWordShieldOnPartyAction, "power word: shield", 15.0f, HealingManaEfficiency::VERY_HIGH); +HEAL_PARTY_ACTION(CastFlashHealOnPartyAction, "flash heal", 15.0f, HealingManaEfficiency::LOW); +HEAL_PARTY_ACTION(CastRenewOnPartyAction, "renew", 15.0f, HealingManaEfficiency::VERY_HIGH); +HEAL_PARTY_ACTION(CastPrayerOfMendingAction, "prayer of mending", 15.0f, HealingManaEfficiency::MEDIUM); +HEAL_PARTY_ACTION(CastBindingHealAction, "binding heal", 15.0f, HealingManaEfficiency::MEDIUM); +HEAL_PARTY_ACTION(CastPrayerOfHealingAction, "prayer of healing", 15.0f, HealingManaEfficiency::MEDIUM); +AOE_HEAL_ACTION(CastCircleOfHealingAction, "circle of healing", 15.0f, HealingManaEfficiency::HIGH); +AOE_HEAL_ACTION(CastLightwellAction, "lightwell", 15.0f, HealingManaEfficiency::MEDIUM); SPELL_ACTION(CastSmiteAction, "smite"); SPELL_ACTION(CastHolyNovaAction, "holy nova"); @@ -126,7 +126,7 @@ public: class CastPenanceOnPartyAction : public HealPartyMemberAction { public: - CastPenanceOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "penance") {} + CastPenanceOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "penance", 25.0f, HealingManaEfficiency::HIGH) {} }; class CastHymnOfHopeAction : public CastSpellAction @@ -152,7 +152,7 @@ public: class CastPowerWordShieldOnAlmostFullHealthBelow : public HealPartyMemberAction { public: - CastPowerWordShieldOnAlmostFullHealthBelow(PlayerbotAI* ai) : HealPartyMemberAction(ai, "power word: shield") {} + CastPowerWordShieldOnAlmostFullHealthBelow(PlayerbotAI* ai) : HealPartyMemberAction(ai, "power word: shield", 15.0f, HealingManaEfficiency::HIGH) {} bool isUseful() override; Unit* GetTarget() override; }; diff --git a/src/strategy/shaman/GenericShamanStrategy.cpp b/src/strategy/shaman/GenericShamanStrategy.cpp index 9a0583f0..de5229e1 100644 --- a/src/strategy/shaman/GenericShamanStrategy.cpp +++ b/src/strategy/shaman/GenericShamanStrategy.cpp @@ -18,7 +18,6 @@ class GenericShamanStrategyActionNodeFactory : public NamedObjectFactory& triggers) triggers.push_back(new TriggerNode( "party member critical health", - NextAction::array(0, new NextAction("riptide on party", 24.0f), new NextAction("healing wave on party", 23.0f), NULL))); + NextAction::array(0, new NextAction("riptide on party", 24.0f), new NextAction("lesser healing wave on party", 23.0f), nullptr))); triggers.push_back(new TriggerNode( "party member low health", - NextAction::array(0, new NextAction("riptide on party", 18.0f), new NextAction("healing wave on party", 17.0f), NULL))); + NextAction::array(0, new NextAction("riptide on party", 18.0f), new NextAction("lesser healing wave on party", 17.0f), nullptr))); triggers.push_back(new TriggerNode( "party member medium health", - NextAction::array(0, new NextAction("riptide on party", 15.0f), new NextAction("lesser healing wave on party", 14.0f), NULL))); + NextAction::array(0, new NextAction("riptide on party", 15.0f), new NextAction("lesser healing wave on party", 14.0f), nullptr))); triggers.push_back(new TriggerNode( "party member almost full health", - NextAction::array(0, new NextAction("riptide on party", 12.0f), new NextAction("lesser healing wave on party", 11.0f), NULL))); + NextAction::array(0, new NextAction("riptide on party", 12.0f), nullptr))); triggers.push_back(new TriggerNode( "party member cleanse spirit poison", @@ -85,9 +85,9 @@ void HealShamanStrategy::InitTriggers(std::vector& triggers) // "no fire totem", // NextAction::array(0, new NextAction("flametongue totem", 10.0f), NULL))); - triggers.push_back(new TriggerNode( - "no water totem", - NextAction::array(0, new NextAction("healing stream totem", 13.0f), NULL))); + // triggers.push_back(new TriggerNode( + // "no water totem", + // NextAction::array(0, new NextAction("healing stream totem", 13.0f), NULL))); triggers.push_back(new TriggerNode( "earth shield on main tank", diff --git a/src/strategy/shaman/ShamanActions.h b/src/strategy/shaman/ShamanActions.h index 25799565..24226b7a 100644 --- a/src/strategy/shaman/ShamanActions.h +++ b/src/strategy/shaman/ShamanActions.h @@ -21,7 +21,7 @@ class CastLesserHealingWaveAction : public CastHealingSpellAction class CastLesserHealingWaveOnPartyAction : public HealPartyMemberAction { public: - CastLesserHealingWaveOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "lesser healing wave") { } + CastLesserHealingWaveOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "lesser healing wave", 25.0f, HealingManaEfficiency::LOW) { } }; class CastHealingWaveAction : public CastHealingSpellAction @@ -33,13 +33,13 @@ class CastHealingWaveAction : public CastHealingSpellAction class CastHealingWaveOnPartyAction : public HealPartyMemberAction { public: - CastHealingWaveOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "healing wave") { } + CastHealingWaveOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "healing wave", 50.0f, HealingManaEfficiency::MEDIUM) { } }; class CastChainHealAction : public CastAoeHealSpellAction { public: - CastChainHealAction(PlayerbotAI* botAI) : CastAoeHealSpellAction(botAI, "chain heal") { } + CastChainHealAction(PlayerbotAI* botAI) : CastAoeHealSpellAction(botAI, "chain heal", 15.0f, HealingManaEfficiency::HIGH) { } }; class CastRiptideAction : public CastHealingSpellAction @@ -51,7 +51,7 @@ class CastRiptideAction : public CastHealingSpellAction class CastRiptideOnPartyAction : public HealPartyMemberAction { public: - CastRiptideOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "riptide") { } + CastRiptideOnPartyAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "riptide", 15.0f, HealingManaEfficiency::VERY_HIGH) { } }; class CastEarthShieldAction : public CastBuffSpellAction @@ -147,7 +147,7 @@ class CastStrengthOfEarthTotemAction : public CastTotemAction class CastManaSpringTotemAction : public CastTotemAction { public: - CastManaSpringTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "mana spring totem", "mana spring", 20.0f) { } + CastManaSpringTotemAction(PlayerbotAI* botAI) : CastTotemAction(botAI, "mana spring totem", "mana spring", 0.0f) { } bool isUseful() override; }; diff --git a/src/strategy/shaman/ShamanNonCombatStrategy.cpp b/src/strategy/shaman/ShamanNonCombatStrategy.cpp index 44973347..1670d288 100644 --- a/src/strategy/shaman/ShamanNonCombatStrategy.cpp +++ b/src/strategy/shaman/ShamanNonCombatStrategy.cpp @@ -16,19 +16,19 @@ void ShamanNonCombatStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("water walking on party", NextAction::array(0, new NextAction("water walking on party", 11.0f), nullptr))); triggers.push_back(new TriggerNode( "party member critical health", - NextAction::array(0, new NextAction("healing wave on party", 27.0f), NULL))); + NextAction::array(0, new NextAction("riptide on party", 31.0f), new NextAction("healing wave on party", 30.0f), NULL))); triggers.push_back(new TriggerNode( "party member low health", - NextAction::array(0, new NextAction("healing wave on party", 26.0f), NULL))); + NextAction::array(0, new NextAction("riptide on party", 29.0f), new NextAction("healing wave on party", 28.0f), NULL))); triggers.push_back(new TriggerNode( "party member medium health", - NextAction::array(0, new NextAction("healing wave on party", 25.0f), NULL))); + NextAction::array(0, new NextAction("riptide on party", 27.0f), new NextAction("healing wave on party", 26.0f), NULL))); triggers.push_back(new TriggerNode( "party member almost full health", - NextAction::array(0, new NextAction("lesser healing wave on party", 24.0f), NULL))); + NextAction::array(0, new NextAction("riptide on party", 25.0f), new NextAction("lesser healing wave on party", 24.0f), NULL))); triggers.push_back(new TriggerNode( "medium aoe heal", diff --git a/src/strategy/values/DpsTargetValue.cpp b/src/strategy/values/DpsTargetValue.cpp index e26c1545..f16a3f84 100644 --- a/src/strategy/values/DpsTargetValue.cpp +++ b/src/strategy/values/DpsTargetValue.cpp @@ -91,7 +91,7 @@ class CasterFindTargetSmartStrategy : public FindTargetStrategy return true; } int32_t level = GetIntervalLevel(new_unit); - if (level % 10 == 2 || level % 10 == 0) { + if (level % 10 == 2 || level % 10 == 1) { return new_time < old_time; } // dont switch targets when all of them with low health @@ -110,10 +110,10 @@ class CasterFindTargetSmartStrategy : public FindTargetStrategy float attackRange = botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig->spellDistance : sPlayerbotAIConfig->meleeDistance; attackRange += 5.0f; int level = dis < attackRange ? 10 : 0; - if (time >= 5 && time <= 20) { + if (time >= 3 && time <= 20) { return level + 2; } - if (time < 5) { + if (time > 20) { return level + 1; } return level;