Flee action, factory setting

This commit is contained in:
Yunfan Li
2023-05-29 11:45:18 +08:00
parent dc21fa9d41
commit 2ad567a1a8
22 changed files with 236 additions and 163 deletions

View File

@@ -482,12 +482,12 @@ AiPlayerbot.LootDelay = 1000
AiPlayerbot.FarDistance = 20.0 AiPlayerbot.FarDistance = 20.0
AiPlayerbot.SightDistance = 60.0 AiPlayerbot.SightDistance = 60.0
AiPlayerbot.SpellDistance = 26.0 AiPlayerbot.SpellDistance = 26.0
AiPlayerbot.ShootDistance = 26.0 AiPlayerbot.ShootDistance = 5.0
AiPlayerbot.ReactDistance = 150.0 AiPlayerbot.ReactDistance = 150.0
AiPlayerbot.GrindDistance = 75.0 AiPlayerbot.GrindDistance = 75.0
AiPlayerbot.HealDistance = 20.0 AiPlayerbot.HealDistance = 20.0
AiPlayerbot.LootDistance = 15.0 AiPlayerbot.LootDistance = 15.0
AiPlayerbot.FleeDistance = 15.0 AiPlayerbot.FleeDistance = 5.0
AiPlayerbot.TooCloseDistance = 5.0 AiPlayerbot.TooCloseDistance = 5.0
AiPlayerbot.MeleeDistance = 1.5 AiPlayerbot.MeleeDistance = 1.5
AiPlayerbot.FollowDistance = 1.5 AiPlayerbot.FollowDistance = 1.5

View File

@@ -260,7 +260,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
if (!player->InBattleground()) if (!player->InBattleground())
{ {
engine->addStrategies("racials", "chat", "default", "potions", "cast time", "duel", nullptr); engine->addStrategies("racials", "chat", "default", "cast time", "duel", nullptr);
} }
switch (player->getClass()) switch (player->getClass())
@@ -270,16 +270,10 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
{ {
engine->addStrategies("dps", "shadow debuff", "shadow aoe", "threat", nullptr); engine->addStrategies("dps", "shadow debuff", "shadow aoe", "threat", nullptr);
} }
else if (tab == 0)
{
engine->addStrategies("holy", "shadow debuff", "shadow aoe", "threat", nullptr);
//if (player->getLevel() >= 4)
//engine->addStrategy("dps debuff");
}
else else
engine->addStrategies("heal", "threat", nullptr); engine->addStrategies("heal", "threat", nullptr);
engine->addStrategies("dps assist", "flee", "cure", "ranged", nullptr); engine->addStrategies("dps assist", "cure", "ranged", nullptr);
break; break;
case CLASS_MAGE: case CLASS_MAGE:
if (tab == 0) if (tab == 0)
@@ -289,7 +283,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
else else
engine->addStrategies("frost", "frost aoe", "threat", "dps aoe", nullptr); engine->addStrategies("frost", "frost aoe", "threat", "dps aoe", nullptr);
engine->addStrategies("dps", "dps assist", "flee", "cure", "ranged", nullptr); engine->addStrategies("dps", "dps assist", "cure", "ranged", nullptr);
break; break;
case CLASS_WARRIOR: case CLASS_WARRIOR:
if (tab == 2) if (tab == 2)
@@ -301,9 +295,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
break; break;
case CLASS_SHAMAN: case CLASS_SHAMAN:
if (tab == 0) if (tab == 0)
engine->addStrategies("caster", "caster aoe", "bmana", "threat", "flee", "ranged", nullptr); engine->addStrategies("caster", "caster aoe", "bmana", "threat", "ranged", nullptr);
else if (tab == 2) else if (tab == 2)
engine->addStrategies("heal", "bmana", "flee", "ranged", nullptr); engine->addStrategies("heal", "bmana", "ranged", nullptr);
else else
engine->addStrategies("dps", "melee aoe", "bdps", "threat", "close", nullptr); engine->addStrategies("dps", "melee aoe", "bdps", "threat", "close", nullptr);
@@ -313,7 +307,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
if (tab == 1) if (tab == 1)
engine->addStrategies("tank", "tank assist", "bthreat", "cure", "baoe", "bstats", "close", nullptr); engine->addStrategies("tank", "tank assist", "bthreat", "cure", "baoe", "bstats", "close", nullptr);
else if (tab == 0) else if (tab == 0)
engine->addStrategies("heal", "bmana", "dps assist", "cure", "flee", nullptr); engine->addStrategies("heal", "bmana", "dps assist", "cure", nullptr);
else else
engine->addStrategies("dps", "bdps", "dps assist", "cure", "close", nullptr); engine->addStrategies("dps", "bdps", "dps assist", "cure", "close", nullptr);
@@ -330,21 +324,21 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
case CLASS_DRUID: case CLASS_DRUID:
if (tab == 0) if (tab == 0)
{ {
engine->addStrategies("caster", "cure", "caster aoe", "threat", "flee", "dps assist", "ranged", nullptr); engine->addStrategies("caster", "cure", "caster aoe", "threat", "dps assist", "ranged", nullptr);
if (player->getLevel() > 19) if (player->getLevel() > 19)
engine->addStrategy("caster debuff"); engine->addStrategy("caster debuff");
} }
else if (tab == 2) else if (tab == 2)
engine->addStrategies("heal", "cure", "flee", "dps assist", "ranged", nullptr); engine->addStrategies("heal", "cure", "dps assist", "ranged", nullptr);
else else
{ {
engine->removeStrategy("ranged"); engine->removeStrategy("ranged");
engine->removeStrategy("flee"); engine->removeStrategy("flee");
engine->addStrategies("bear", "tank assist", "flee", "close", nullptr); engine->addStrategies("bear", "tank assist", "close", nullptr);
} }
break; break;
case CLASS_HUNTER: case CLASS_HUNTER:
engine->addStrategies("dps", "bdps", "threat", "dps assist", "ranged", "pet", nullptr); engine->addStrategies("dps", "aoe", "bdps", "threat", "dps assist", "ranged", nullptr);
if (player->getLevel() > 19) if (player->getLevel() > 19)
engine->addStrategy("dps debuff"); engine->addStrategy("dps debuff");
break; break;
@@ -355,7 +349,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
if (player->getLevel() > 19) if (player->getLevel() > 19)
engine->addStrategy("dps debuff"); engine->addStrategy("dps debuff");
engine->addStrategies("dps assist", "dps", "flee", "ranged", "pet", "threat", nullptr); engine->addStrategies("dps assist", "dps", "aoe", "ranged", "pet", "threat", nullptr);
break; break;
case CLASS_DEATH_KNIGHT: case CLASS_DEATH_KNIGHT:
if (tab == 0) if (tab == 0)
@@ -365,7 +359,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
else else
engine->addStrategies("unholy", "unholy aoe", "dps assist", "threat", nullptr); engine->addStrategies("unholy", "unholy aoe", "dps assist", "threat", nullptr);
engine->addStrategies("dps assist", "flee", "close", nullptr); engine->addStrategies("dps assist", "close", nullptr);
break; break;
} }
@@ -376,7 +370,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
{ {
engine->ChangeStrategy(sPlayerbotAIConfig->randomBotCombatStrategies); engine->ChangeStrategy(sPlayerbotAIConfig->randomBotCombatStrategies);
engine->addStrategy("flee"); // engine->addStrategy("flee");
engine->addStrategy("boost"); engine->addStrategy("boost");
if (player->getClass() == CLASS_WARLOCK) if (player->getClass() == CLASS_WARLOCK)
@@ -493,7 +487,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
nonCombatEngine->addStrategies("barmor", nullptr); nonCombatEngine->addStrategies("barmor", nullptr);
break; break;
case CLASS_HUNTER: case CLASS_HUNTER:
nonCombatEngine->addStrategies("bdps", "dps assist", nullptr); nonCombatEngine->addStrategies("bdps", "dps assist", "pet", nullptr);
break; break;
case CLASS_SHAMAN: case CLASS_SHAMAN:
if (tab == 0 || tab == 2) if (tab == 0 || tab == 2)

View File

@@ -1648,11 +1648,21 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell,
if (pet->HasSpell(spellid)) if (pet->HasSpell(spellid))
return true; return true;
if (checkHasSpell && !bot->HasSpell(spellid)) if (checkHasSpell && !bot->HasSpell(spellid)) {
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
LOG_DEBUG("playerbots", "Can cast spell failed. Bot not has spell. - target name: {}, spellid: {}, bot name: {}",
target->GetName(), spellid, bot->GetName());
}
return false; return false;
}
if (bot->HasSpellCooldown(spellid)) if (bot->HasSpellCooldown(spellid)) {
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
LOG_DEBUG("playerbots", "Can cast spell failed. Spell not has cooldown. - target name: {}, spellid: {}, bot name: {}",
target->GetName(), spellid, bot->GetName());
}
return false; return false;
}
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
if (!spellInfo) if (!spellInfo)

View File

@@ -335,15 +335,7 @@ void PlayerbotFactory::Randomize(bool incremental)
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Save"); pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Save");
LOG_INFO("playerbots", "Saving to DB..."); LOG_INFO("playerbots", "Saving to DB...");
if (incremental) bot->SetMoney(urand(level * 100000, level * 5 * 100000));
{
uint32 money = bot->GetMoney();
bot->SetMoney(money + 1000 * sqrt(urand(1, level * 5)));
}
else
{
bot->SetMoney(10000 * sqrt(urand(1, level * 5)));
}
bot->SaveToDB(false, false); bot->SaveToDB(false, false);
LOG_INFO("playerbots", "Done."); LOG_INFO("playerbots", "Done.");
if (pmo) if (pmo)
@@ -353,10 +345,25 @@ void PlayerbotFactory::Randomize(bool incremental)
void PlayerbotFactory::Refresh() void PlayerbotFactory::Refresh()
{ {
Prepare(); Prepare();
InitEquipment(true);
InitAmmo(); InitAmmo();
InitFood(); InitFood();
InitPotions();
InitReagents(); InitReagents();
InitPotions();
InitTalents(true);
InitClassSpells();
InitAvailableSpells();
bot->DurabilityRepairAll(false, 1.0f, false);
uint32 money = urand(level * 1000, level * 5 * 1000);
if (bot->GetMoney() < money)
bot->SetMoney(money);
bot->SaveToDB(false, false);
// Prepare();
// InitAmmo();
// InitFood();
// InitPotions();
//bot->SaveToDB(); //bot->SaveToDB();
} }
@@ -1731,12 +1738,13 @@ void PlayerbotFactory::SetRandomSkill(uint16 id)
uint32 maxValue = level * 5; uint32 maxValue = level * 5;
// do not let skill go beyond limit even if maxlevel > blizzlike // do not let skill go beyond limit even if maxlevel > blizzlike
if (level > 60) // if (level > 60)
{ // {
maxValue = (level + 10) * 5; // maxValue = (level + 10) * 5;
} // }
uint32 value = urand(maxValue - level, maxValue); // uint32 value = urand(maxValue - level, maxValue);
uint32 value = maxValue;
uint32 curValue = bot->GetSkillValue(id); uint32 curValue = bot->GetSkillValue(id);
uint16 step = bot->GetSkillValue(id) ? bot->GetSkillStep(id) : 1; uint16 step = bot->GetSkillValue(id) ? bot->GetSkillStep(id) : 1;

View File

@@ -3,6 +3,7 @@
*/ */
#include "CharacterPackets.h" #include "CharacterPackets.h"
#include "Common.h"
#include "ObjectAccessor.h" #include "ObjectAccessor.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "PlayerbotMgr.h" #include "PlayerbotMgr.h"
@@ -519,6 +520,10 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
if (!bot) if (!bot)
return "bot not found"; return "bot not found";
if (!isRandomAccount || !isRandomBot) {
return "ERROR: You can not use this command on non-ramdom bot.";
}
if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster()) if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster())
{ {
@@ -846,7 +851,7 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
} }
else if (master && member != master->GetGUID()) else if (master && member != master->GetGUID())
{ {
out << ProcessBotCommand(cmdStr, member, master->GetGUID(), master->GetSession()->GetSecurity() >= SEC_GAMEMASTER, master->GetSession()->GetAccountId(), master->GetGuildId()); out << ProcessBotCommand(cmdStr, member, master->GetGUID(), true, master->GetSession()->GetAccountId(), master->GetGuildId());
} }
else if (!master) else if (!master)
{ {

View File

@@ -2195,7 +2195,7 @@ void RandomItemMgr::BuildAmmoCache()
uint32 RandomItemMgr::GetAmmo(uint32 level, uint32 subClass) uint32 RandomItemMgr::GetAmmo(uint32 level, uint32 subClass)
{ {
return ammoCache[(level - 1) / 10][subClass]; return ammoCache[level / 10][subClass];
} }
void RandomItemMgr::BuildPotionCache() void RandomItemMgr::BuildPotionCache()

View File

@@ -27,6 +27,16 @@ bool FollowAction::Execute(Event event)
moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ()); moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ());
} }
if (Pet* pet = bot->GetPet())
{
if (CreatureAI* creatureAI = ((Creature*)pet)->AI())
{
pet->SetReactState(REACT_PASSIVE);
pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
pet->GetCharmInfo()->SetIsFollowing(true);
pet->AttackStop();
}
}
//if (moved) //if (moved)
//botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); //botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay);

View File

@@ -4,6 +4,7 @@
#include "MovementActions.h" #include "MovementActions.h"
#include "MovementGenerator.h" #include "MovementGenerator.h"
#include "PlayerbotAIConfig.h"
#include "TargetedMovementGenerator.h" #include "TargetedMovementGenerator.h"
#include "Event.h" #include "Event.h"
#include "LastMovementValue.h" #include "LastMovementValue.h"
@@ -1211,22 +1212,33 @@ void MovementAction::ClearIdleState()
context->GetValue<PositionMap&>("position")->Get()["random"].Reset(); context->GetValue<PositionMap&>("position")->Get()["random"].Reset();
} }
bool MovementAction::MoveAway(Unit* target)
{
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);
}
bool FleeAction::Execute(Event event) bool FleeAction::Execute(Event event)
{ {
return Flee(AI_VALUE(Unit*, "current target")); // return Flee(AI_VALUE(Unit*, "current target"));
return MoveAway(AI_VALUE(Unit*, "current target"));
} }
bool FleeWithPetAction::Execute(Event event) bool FleeWithPetAction::Execute(Event event)
{ {
// if (Pet* pet = bot->GetPet()) if (Pet* pet = bot->GetPet())
// { {
// if (CreatureAI* creatureAI = ((Creature*)pet)->AI()) if (CreatureAI* creatureAI = ((Creature*)pet)->AI())
// { {
// pet->SetReactState(REACT_PASSIVE); pet->SetReactState(REACT_PASSIVE);
// pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
// pet->AttackStop(); pet->GetCharmInfo()->SetIsFollowing(true);
// } pet->AttackStop();
// } }
}
return Flee(AI_VALUE(Unit*, "current target")); return Flee(AI_VALUE(Unit*, "current target"));
} }

View File

@@ -36,7 +36,7 @@ class MovementAction : public Action
bool Flee(Unit *target); bool Flee(Unit *target);
void ClearIdleState(); void ClearIdleState();
void UpdateMovementState(); void UpdateMovementState();
bool MoveAway(Unit* target);
void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false); void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false);
}; };

View File

@@ -10,5 +10,5 @@ void UseFoodStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
Strategy::InitTriggers(triggers); Strategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("food", 3.0f), nullptr))); triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("food", 3.0f), nullptr)));
triggers.push_back(new TriggerNode("high mana", NextAction::array(0, new NextAction("drink", 3.0f), nullptr))); triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("drink", 3.0f), nullptr)));
} }

View File

@@ -11,50 +11,14 @@ class DpsHunterStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
DpsHunterStrategyActionNodeFactory() DpsHunterStrategyActionNodeFactory()
{ {
creators["aimed shot"] = &aimed_shot; creators["aimed shot"] = &aimed_shot;
creators["chimera shot"] = &chimera_shot;
creators["explosive shot"] = &explosive_shot;
creators["concussive shot"] = &concussive_shot;
creators["viper sting"] = &viper_sting;
} }
private: private:
static ActionNode* viper_sting([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode ("viper sting",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("mana potion", 10.0f), nullptr),
/*C*/ nullptr);
}
static ActionNode* aimed_shot([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* aimed_shot([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("aimed shot", return new ActionNode ("aimed shot",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("chimera shot", 10.0f), nullptr), /*A*/ NextAction::array(0, new NextAction("multi-shot", 10.0f), nullptr),
/*C*/ nullptr);
}
static ActionNode* chimera_shot([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode ("chimera shot",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("arcane shot", 10.0f), nullptr),
/*C*/ nullptr);
}
static ActionNode* explosive_shot([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode ("explosive shot",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("aimed shot"), nullptr),
/*C*/ nullptr);
}
static ActionNode* concussive_shot([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode ("concussive shot",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
}; };
@@ -66,7 +30,16 @@ DpsHunterStrategy::DpsHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy
NextAction** DpsHunterStrategy::getDefaultActions() NextAction** DpsHunterStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("explosive shot", 11.0f), new NextAction("auto shot", 10.0f), new NextAction("auto attack", 9.0f), nullptr); 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),
NULL);
// return NextAction::array(0, new NextAction("explosive shot", 11.0f), new NextAction("auto shot", 10.0f), new NextAction("auto attack", 9.0f), nullptr);
} }
void DpsHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DpsHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -77,6 +50,8 @@ void DpsHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23), nullptr))); triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23), nullptr)));
triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 19.0f), nullptr))); triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 19.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("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)));
/*triggers.push_back(new TriggerNode("has aggro", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr)));*/ /*triggers.push_back(new TriggerNode("has aggro", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr)));*/
} }

View File

@@ -45,8 +45,8 @@ void GenericHunterNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tri
triggers.push_back(new TriggerNode("trueshot aura", NextAction::array(0, new NextAction("trueshot aura", 2.0f), nullptr))); triggers.push_back(new TriggerNode("trueshot aura", NextAction::array(0, new NextAction("trueshot aura", 2.0f), nullptr)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr))); triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("low ammo", NextAction::array(0, new NextAction("say::low ammo", ACTION_NORMAL), nullptr))); triggers.push_back(new TriggerNode("low ammo", NextAction::array(0, new NextAction("say::low ammo", ACTION_NORMAL), nullptr)));
triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", ACTION_NORMAL + 1), new NextAction("say::no ammo", ACTION_NORMAL), nullptr))); // triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", ACTION_NORMAL + 1), new NextAction("say::no ammo", ACTION_NORMAL), nullptr)));
triggers.push_back(new TriggerNode("has ammo", NextAction::array(0, new NextAction("switch to ranged", ACTION_NORMAL), nullptr))); // triggers.push_back(new TriggerNode("has ammo", NextAction::array(0, new NextAction("switch to ranged", ACTION_NORMAL), nullptr)));
} }
void HunterPetStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void HunterPetStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -69,13 +69,13 @@ void GenericHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
CombatStrategy::InitTriggers(triggers); CombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("enemy too close for auto shot", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH), nullptr))); // triggers.push_back(new TriggerNode("enemy too close for auto shot", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH), nullptr)));
triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("wing clip", ACTION_HIGH), nullptr))); triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("wing clip", ACTION_HIGH), nullptr)));
triggers.push_back(new TriggerNode("medium threat", NextAction::array(0, new NextAction("feign death", 35.0f), nullptr))); triggers.push_back(new TriggerNode("medium threat", NextAction::array(0, new NextAction("feign death", 35.0f), nullptr)));
triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", ACTION_HIGH + 2), nullptr))); triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", ACTION_HIGH + 2), nullptr)));
triggers.push_back(new TriggerNode("switch to melee", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH + 1), nullptr))); // triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH + 1), new NextAction("say::no ammo", ACTION_HIGH), nullptr)));
triggers.push_back(new TriggerNode("switch to ranged", NextAction::array(0, new NextAction("switch to ranged", ACTION_HIGH), nullptr))); triggers.push_back(new TriggerNode("aspect of the viper", NextAction::array(0, new NextAction("aspect of the viper", ACTION_HIGH), NULL)));
triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH + 1), new NextAction("say::no ammo", ACTION_HIGH), nullptr))); triggers.push_back(new TriggerNode("enemy too close for shoot", NextAction::array(0, new NextAction("flee", ACTION_HIGH + 3), NULL)));
} }
NextAction** HunterBoostStrategy::getDefaultActions() NextAction** HunterBoostStrategy::getDefaultActions()

View File

@@ -62,12 +62,27 @@ END_SPELL_ACTION()
BEGIN_RANGED_SPELL_ACTION(CastScorpidStingAction, "scorpid sting") BEGIN_RANGED_SPELL_ACTION(CastScorpidStingAction, "scorpid sting")
END_SPELL_ACTION() END_SPELL_ACTION()
BEGIN_RANGED_SPELL_ACTION(CastSteadyShotAction, "steady shot")
END_SPELL_ACTION()
BEGIN_RANGED_SPELL_ACTION(CastKillShotAction, "kill shot")
END_SPELL_ACTION()
BEGIN_RANGED_SPELL_ACTION(CastTranquilizingShortAction, "tranquilizing shot")
END_SPELL_ACTION()
class CastAspectOfTheHawkAction : public CastBuffSpellAction class CastAspectOfTheHawkAction : public CastBuffSpellAction
{ {
public: public:
CastAspectOfTheHawkAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "aspect of the hawk") { } CastAspectOfTheHawkAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "aspect of the hawk") { }
}; };
class CastAspectOfTheDragonhawkAction : public CastBuffSpellAction
{
public:
CastAspectOfTheDragonhawkAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "aspect of the dragonhawk") {}
};
class CastAspectOfTheWildAction : public CastBuffSpellAction class CastAspectOfTheWildAction : public CastBuffSpellAction
{ {
public: public:

View File

@@ -148,6 +148,10 @@ class HunterAiObjectContextInternal : public NamedObjectContext<Action>
creators["bestial wrath"] = &HunterAiObjectContextInternal::bestial_wrath; creators["bestial wrath"] = &HunterAiObjectContextInternal::bestial_wrath;
creators["scare beast"] = &HunterAiObjectContextInternal::scare_beast; creators["scare beast"] = &HunterAiObjectContextInternal::scare_beast;
creators["scare beast on cc"] = &HunterAiObjectContextInternal::scare_beast_on_cc; creators["scare beast on cc"] = &HunterAiObjectContextInternal::scare_beast_on_cc;
creators["aspect of the dragonhawk"] = &HunterAiObjectContextInternal::aspect_of_the_dragonhawk;
creators["tranquilizing shot"] = &HunterAiObjectContextInternal::tranquilizing_shot;
creators["steady shot"] = &HunterAiObjectContextInternal::steady_shot;
creators["kill shot"] = &HunterAiObjectContextInternal::kill_shot;
} }
private: private:
@@ -186,6 +190,10 @@ class HunterAiObjectContextInternal : public NamedObjectContext<Action>
static Action* aspect_of_the_cheetah(PlayerbotAI* botAI) { return new CastAspectOfTheCheetahAction(botAI); } static Action* aspect_of_the_cheetah(PlayerbotAI* botAI) { return new CastAspectOfTheCheetahAction(botAI); }
static Action* wing_clip(PlayerbotAI* botAI) { return new CastWingClipAction(botAI); } static Action* wing_clip(PlayerbotAI* botAI) { return new CastWingClipAction(botAI); }
static Action* raptor_strike(PlayerbotAI* botAI) { return new CastRaptorStrikeAction(botAI); } static Action* raptor_strike(PlayerbotAI* botAI) { return new CastRaptorStrikeAction(botAI); }
static Action* aspect_of_the_dragonhawk(PlayerbotAI* ai) { return new CastAspectOfTheDragonhawkAction(ai); }
static Action* tranquilizing_shot(PlayerbotAI* ai) { return new CastTranquilizingShortAction(ai); }
static Action* steady_shot(PlayerbotAI* ai) { return new CastSteadyShotAction(ai); }
static Action* kill_shot(PlayerbotAI* ai) { return new CastKillShotAction(ai); }
}; };
HunterAiObjectContext::HunterAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) HunterAiObjectContext::HunterAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI)

View File

@@ -7,6 +7,7 @@
void HunterBuffDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void HunterBuffDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("aspect of the hawk", NextAction::array(0, new NextAction("aspect of the dragonhawk", 90.0f), nullptr)));
triggers.push_back(new TriggerNode("aspect of the hawk", NextAction::array(0, new NextAction("aspect of the hawk", 90.0f), nullptr))); triggers.push_back(new TriggerNode("aspect of the hawk", NextAction::array(0, new NextAction("aspect of the hawk", 90.0f), nullptr)));
} }

View File

@@ -7,6 +7,14 @@
#include "Playerbots.h" #include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
bool HunterAspectOfTheHawkTrigger::IsActive()
{
Unit* target = GetTarget();
return SpellTrigger::IsActive() &&
!botAI->HasAura("aspect of the hawk", target) && !botAI->HasAura("aspect of the dragonhawk", target) &&
(!AI_VALUE2(bool, "has mana", "self target") || AI_VALUE2(uint8, "mana", "self target") > 70);
}
bool HunterNoStingsActiveTrigger::IsActive() bool HunterNoStingsActiveTrigger::IsActive()
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
@@ -16,6 +24,8 @@ bool HunterNoStingsActiveTrigger::IsActive()
bool HuntersPetDeadTrigger::IsActive() bool HuntersPetDeadTrigger::IsActive()
{ {
// Unit* pet = AI_VALUE(Unit*, "pet target");
// return pet && AI_VALUE2(bool, "dead", "pet target") && !AI_VALUE2(bool, "mounted", "self target");
return AI_VALUE(bool, "pet dead") && !AI_VALUE2(bool, "mounted", "self target"); return AI_VALUE(bool, "pet dead") && !AI_VALUE2(bool, "mounted", "self target");
} }
@@ -32,7 +42,8 @@ bool HunterPetNotHappy::IsActive()
bool HunterAspectOfTheViperTrigger::IsActive() bool HunterAspectOfTheViperTrigger::IsActive()
{ {
return SpellTrigger::IsActive() && !botAI->HasAura(spell, GetTarget()); return SpellTrigger::IsActive() && !botAI->HasAura(spell, GetTarget()) &&
AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->lowMana;;
} }
bool HunterAspectOfThePackTrigger::IsActive() bool HunterAspectOfThePackTrigger::IsActive()

View File

@@ -24,6 +24,7 @@ class HunterAspectOfTheHawkTrigger : public BuffTrigger
{ {
public: public:
HunterAspectOfTheHawkTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "aspect of the hawk") { } HunterAspectOfTheHawkTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "aspect of the hawk") { }
bool IsActive() override;
}; };
class HunterAspectOfTheWildTrigger : public BuffTrigger class HunterAspectOfTheWildTrigger : public BuffTrigger

View File

@@ -13,19 +13,19 @@
#include "PullStrategy.h" #include "PullStrategy.h"
#include "Playerbots.h" #include "Playerbots.h"
class StrategyFactoryInternal : public NamedObjectContext<Strategy> class MageStrategyFactoryInternal : public NamedObjectContext<Strategy>
{ {
public: public:
StrategyFactoryInternal() MageStrategyFactoryInternal()
{ {
creators["nc"] = &StrategyFactoryInternal::nc; creators["nc"] = &MageStrategyFactoryInternal::nc;
creators["pull"] = &StrategyFactoryInternal::pull; creators["pull"] = &MageStrategyFactoryInternal::pull;
creators["fire aoe"] = &StrategyFactoryInternal::fire_aoe; creators["fire aoe"] = &MageStrategyFactoryInternal::fire_aoe;
creators["frost aoe"] = &StrategyFactoryInternal::frost_aoe; creators["frost aoe"] = &MageStrategyFactoryInternal::frost_aoe;
creators["cure"] = &StrategyFactoryInternal::cure; creators["cure"] = &MageStrategyFactoryInternal::cure;
creators["buff"] = &StrategyFactoryInternal::buff; creators["buff"] = &MageStrategyFactoryInternal::buff;
creators["boost"] = &StrategyFactoryInternal::boost; creators["boost"] = &MageStrategyFactoryInternal::boost;
creators["cc"] = &StrategyFactoryInternal::cc; creators["cc"] = &MageStrategyFactoryInternal::cc;
} }
private: private:
@@ -39,14 +39,14 @@ class StrategyFactoryInternal : public NamedObjectContext<Strategy>
static Strategy* cc(PlayerbotAI* botAI) { return new MageCcStrategy(botAI); } static Strategy* cc(PlayerbotAI* botAI) { return new MageCcStrategy(botAI); }
}; };
class MageStrategyFactoryInternal : public NamedObjectContext<Strategy> class MageCombatStrategyFactoryInternal : public NamedObjectContext<Strategy>
{ {
public: public:
MageStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true) MageCombatStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true)
{ {
creators["frost"] = &MageStrategyFactoryInternal::frost; creators["frost"] = &MageCombatStrategyFactoryInternal::frost;
creators["fire"] = &MageStrategyFactoryInternal::fire; creators["fire"] = &MageCombatStrategyFactoryInternal::fire;
creators["arcane"] = &MageStrategyFactoryInternal::arcane; creators["arcane"] = &MageCombatStrategyFactoryInternal::arcane;
} }
private: private:
@@ -213,7 +213,7 @@ class MageAiObjectContextInternal : public NamedObjectContext<Action>
MageAiObjectContext::MageAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) MageAiObjectContext::MageAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI)
{ {
strategyContexts.Add(new MageStrategyFactoryInternal()); strategyContexts.Add(new MageStrategyFactoryInternal());
strategyContexts.Add(new MageStrategyFactoryInternal()); strategyContexts.Add(new MageCombatStrategyFactoryInternal());
strategyContexts.Add(new MageBuffStrategyFactoryInternal()); strategyContexts.Add(new MageBuffStrategyFactoryInternal());
actionContexts.Add(new MageAiObjectContextInternal()); actionContexts.Add(new MageAiObjectContextInternal());
triggerContexts.Add(new MageTriggerFactoryInternal()); triggerContexts.Add(new MageTriggerFactoryInternal());

View File

@@ -145,7 +145,23 @@ bool MyAttackerCountTrigger::IsActive()
bool AoeTrigger::IsActive() bool AoeTrigger::IsActive()
{ {
return AI_VALUE2(bool, "combat", "self target") && AI_VALUE(uint8, "aoe count") >= amount && AI_VALUE(uint8, "attacker count") >= amount; Unit* current_target = AI_VALUE(Unit*, "current target");
if (!current_target) {
return false;
}
GuidVector attackers = context->GetValue<GuidVector>("attackers")->Get();
int attackers_count = 0;
for (ObjectGuid const guid : attackers)
{
Unit* unit = botAI->GetUnit(guid);
if (!unit || !unit->IsAlive())
continue;
if (unit->GetExactDist2d(current_target) <= range) {
attackers_count++;
}
}
return attackers_count >= amount;
} }
bool NoFoodTrigger::IsActive() bool NoFoodTrigger::IsActive()

View File

@@ -225,19 +225,19 @@ class NoDrinkTrigger : public Trigger
class LightAoeTrigger : public AoeTrigger class LightAoeTrigger : public AoeTrigger
{ {
public: public:
LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 15.0f) { } LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 8.0f) { }
}; };
class MediumAoeTrigger : public AoeTrigger class MediumAoeTrigger : public AoeTrigger
{ {
public: public:
MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 17.0f) { } MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 8.0f) { }
}; };
class HighAoeTrigger : public AoeTrigger class HighAoeTrigger : public AoeTrigger
{ {
public: public:
HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 20.0f) { } HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 8.0f) { }
}; };
class BuffTrigger : public SpellTrigger class BuffTrigger : public SpellTrigger
@@ -413,7 +413,7 @@ END_TRIGGER()
class NoPetTrigger : public Trigger class NoPetTrigger : public Trigger
{ {
public: public:
NoPetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no pet", 30) { } NoPetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no pet", 5) { }
bool IsActive() override; bool IsActive() override;
}; };

View File

@@ -15,33 +15,37 @@ static float GetSpeedInMotion(Unit* target)
bool EnemyTooCloseForSpellTrigger::IsActive() bool EnemyTooCloseForSpellTrigger::IsActive()
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
if (target) return target && target->GetVictim() != bot &&
{ target->GetObjectSize() <= 10.0f &&
if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f) AI_VALUE2(float, "distance", "current target") <= sPlayerbotAIConfig->tooCloseDistance;
return false; // Unit* target = AI_VALUE(Unit*, "current target");
// if (!target) {
// return false;
// }
bool isBoss = false; // if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f)
bool isRaid = false; // return false;
float combatReach = bot->GetCombatReach() + target->GetCombatReach();
float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach;
if (target->GetTypeId() == TYPEID_UNIT)
{
Creature* creature = botAI->GetCreature(target->GetGUID());
if (creature)
{
isBoss = creature->isWorldBoss();
}
}
if (bot->GetMap() && bot->GetMap()->IsRaid()) // bool isBoss = false;
isRaid = true; // bool isRaid = false;
// float combatReach = bot->GetCombatReach() + target->GetCombatReach();
// float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach;
// if (target->GetTypeId() == TYPEID_UNIT)
// {
// Creature* creature = botAI->GetCreature(target->GetGUID());
// if (creature)
// {
// isBoss = creature->isWorldBoss();
// }
// }
// if (isBoss || isRaid) // if (bot->GetMap() && bot->GetMap()->IsRaid())
// return sServerFacade->IsDistanceLessThan(targetDistance, (botAI->GetRange("spell") + combatReach) / 2); // isRaid = true;
return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("spell") + combatReach / 2)); // // if (isBoss || isRaid)
} // // return sServerFacade->IsDistanceLessThan(targetDistance, (sPlayerbotAIConfig->tooCloseDistance + combatReach) / 2);
return false;
// return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (sPlayerbotAIConfig->tooCloseDistance + combatReach / 2));
} }
bool EnemyTooCloseForAutoShotTrigger::IsActive() bool EnemyTooCloseForAutoShotTrigger::IsActive()
@@ -75,32 +79,35 @@ bool EnemyTooCloseForAutoShotTrigger::IsActive()
bool EnemyTooCloseForShootTrigger::IsActive() bool EnemyTooCloseForShootTrigger::IsActive()
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
if (!target) return target && target->GetVictim() != bot && AI_VALUE2(float, "distance", "current target") <= sPlayerbotAIConfig->shootDistance;
return false;
if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f) // Unit* target = AI_VALUE(Unit*, "current target");
return false; // if (!target)
// return false;
bool isBoss = false; // if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f)
bool isRaid = false; // return false;
float combatReach = bot->GetCombatReach() + target->GetCombatReach();
float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach;
if (target->GetTypeId() == TYPEID_UNIT)
{
Creature* creature = botAI->GetCreature(target->GetGUID());
if (creature)
{
isBoss = creature->isWorldBoss();
}
}
if (bot->GetMap() && bot->GetMap()->IsRaid()) // bool isBoss = false;
isRaid = true; // bool isRaid = false;
// float combatReach = bot->GetCombatReach() + target->GetCombatReach();
// float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach;
// if (target->GetTypeId() == TYPEID_UNIT)
// {
// Creature* creature = botAI->GetCreature(target->GetGUID());
// if (creature)
// {
// isBoss = creature->isWorldBoss();
// }
// }
// if (isBoss || isRaid) // if (bot->GetMap() && bot->GetMap()->IsRaid())
// return sServerFacade->IsDistanceLessThan(targetDistance, botAI->GetRange("shoot") + combatReach); // isRaid = true;
return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("shoot") + combatReach / 2)); // // if (isBoss || isRaid)
// // return sServerFacade->IsDistanceLessThan(targetDistance, botAI->GetRange("shoot") + combatReach);
// return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("shoot") + combatReach / 2));
} }
bool EnemyTooCloseForMeleeTrigger::IsActive() bool EnemyTooCloseForMeleeTrigger::IsActive()