Merge branch 'master' of github.com:liyunfan1223/mod-playerbots

This commit is contained in:
Yunfan Li
2023-12-25 18:49:05 +08:00
17 changed files with 126 additions and 18 deletions

35
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: liyunfan1223
---
**Describe the bug**
A clear and concise description of what the bug is.
**Commit hash**
The hash of the current commit.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -49,6 +49,18 @@ It's essential to note that there is still a significant amount of work to be do
For enhanced control over the bots and to simplify command usage, you can also make use of our addon: [Unbot Addon](https://github.com/liyunfan1223/unbot-addon). Currently, this addon offers better support only for Simplified Chinese client. For enhanced control over the bots and to simplify command usage, you can also make use of our addon: [Unbot Addon](https://github.com/liyunfan1223/unbot-addon). Currently, this addon offers better support only for Simplified Chinese client.
## Frequently Asked Questions
**Why won't my bot cast spells?**
- Ensure the presence of the required English DBC file (enUS).
**Compilation failed on Windows?**
- Developed primarily on Linux, I may miss cross-platform compilation issues. Feel free to report them.
- Future plans include implementing an auto build workflow to prevent such issues.
## Acknowledgements ## Acknowledgements
The code for this module is ported from [ZhengPeiRu21/mod-playerbots](https://github.com/ZhengPeiRu21/mod-playerbots) and [celguar/mangosbot-bots](https://github.com/celguar/mangosbot-bots). We extend our gratitude to @ZhengPeiRu21 and @celguar for the continued efforts in maintaining the module. The code for this module is ported from [ZhengPeiRu21/mod-playerbots](https://github.com/ZhengPeiRu21/mod-playerbots) and [celguar/mangosbot-bots](https://github.com/celguar/mangosbot-bots). We extend our gratitude to @ZhengPeiRu21 and @celguar for the continued efforts in maintaining the module.

View File

@@ -44,6 +44,13 @@ AiPlayerbot.MaxRandomBots = 50
AiPlayerbot.RandomBotMinLevel = 1 AiPlayerbot.RandomBotMinLevel = 1
AiPlayerbot.RandomBotMaxLevel = 80 AiPlayerbot.RandomBotMaxLevel = 80
# Enable/Disable rotation of bots (randomly select a bot from the bots pool to go online and rotate them periodically)
# default: 0 (disable, the online bots are fixed)
AiPlayerbot.EnableRotation = 0
# Bots pool size for rotation (should be less than RandomBotAccountCount * 10)
AiPlayerbot.RotationPoolSize = 500
# Accounts to create for random bots # Accounts to create for random bots
AiPlayerbot.RandomBotAccountPrefix = "rndbot" AiPlayerbot.RandomBotAccountPrefix = "rndbot"
AiPlayerbot.RandomBotAccountCount = 200 AiPlayerbot.RandomBotAccountCount = 200
@@ -251,7 +258,7 @@ AiPlayerbot.LootDelay = 1000
# Distances # Distances
AiPlayerbot.FarDistance = 20.0 AiPlayerbot.FarDistance = 20.0
AiPlayerbot.SightDistance = 100.0 AiPlayerbot.SightDistance = 75.0
AiPlayerbot.SpellDistance = 28.5 AiPlayerbot.SpellDistance = 28.5
AiPlayerbot.ShootDistance = 5.0 AiPlayerbot.ShootDistance = 5.0
AiPlayerbot.ReactDistance = 150.0 AiPlayerbot.ReactDistance = 150.0
@@ -338,7 +345,7 @@ AiPlayerbot.RandomBotUpdateInterval = 20
AiPlayerbot.RandomBotCountChangeMinInterval = 1800 AiPlayerbot.RandomBotCountChangeMinInterval = 1800
AiPlayerbot.RandomBotCountChangeMaxInterval = 7200 AiPlayerbot.RandomBotCountChangeMaxInterval = 7200
AiPlayerbot.MinRandomBotInWorldTime = 3600 AiPlayerbot.MinRandomBotInWorldTime = 3600
AiPlayerbot.MaxRandomBotInWorldTime = 1209600 AiPlayerbot.MaxRandomBotInWorldTime = 43200
AiPlayerbot.MinRandomBotRandomizeTime = 302400 AiPlayerbot.MinRandomBotRandomizeTime = 302400
AiPlayerbot.MaxRandomRandomizeTime = 1209600 AiPlayerbot.MaxRandomRandomizeTime = 1209600
AiPlayerbot.RandomBotsPerInterval = 500 AiPlayerbot.RandomBotsPerInterval = 500
@@ -350,6 +357,7 @@ AiPlayerbot.MinRandomBotReviveTime = 60
AiPlayerbot.MaxRandomBotReviveTime = 300 AiPlayerbot.MaxRandomBotReviveTime = 300
AiPlayerbot.MinRandomBotTeleportInterval = 3600 AiPlayerbot.MinRandomBotTeleportInterval = 3600
AiPlayerbot.MaxRandomBotTeleportInterval = 18000 AiPlayerbot.MaxRandomBotTeleportInterval = 18000
AiPlayerbot.RandomBotInWorldWithRotaionDisabled = 31104000
# How far random bots are teleported after death # How far random bots are teleported after death
AiPlayerbot.RandomBotTeleportDistance = 100 AiPlayerbot.RandomBotTeleportDistance = 100

View File

@@ -124,6 +124,7 @@ bool PlayerbotAIConfig::Initialize()
maxRandomBotReviveTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE); maxRandomBotReviveTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE);
minRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR); minRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR);
maxRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR); maxRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR);
randomBotInWorldWithRotaionDisabled = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotInWorldWithRotaionDisabled", 1 * YEAR);
randomBotTeleportDistance = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotTeleportDistance", 100); randomBotTeleportDistance = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotTeleportDistance", 100);
randomBotsPerInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotsPerInterval", MINUTE); randomBotsPerInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotsPerInterval", MINUTE);
minRandomBotsPriceChangeInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotsPriceChangeInterval", 2 * HOUR); minRandomBotsPriceChangeInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotsPriceChangeInterval", 2 * HOUR);
@@ -328,6 +329,8 @@ bool PlayerbotAIConfig::Initialize()
randombotsWalkingRPGInDoors = sConfigMgr->GetOption<bool>("AiPlayerbot.RandombotsWalkingRPG.InDoors", false); randombotsWalkingRPGInDoors = sConfigMgr->GetOption<bool>("AiPlayerbot.RandombotsWalkingRPG.InDoors", false);
minEnchantingBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.MinEnchantingBotLevel", 60); minEnchantingBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.MinEnchantingBotLevel", 60);
randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5); randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5);
enableRotation = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableRotation", false);
rotationPoolSize = sConfigMgr->GetOption<int32>("AiPlayerbot.RotationPoolSize", 500);
gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false); gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false);
randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true); randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true);

View File

@@ -70,6 +70,7 @@ class PlayerbotAIConfig
uint32 minRandomBotChangeStrategyTime, maxRandomBotChangeStrategyTime; uint32 minRandomBotChangeStrategyTime, maxRandomBotChangeStrategyTime;
uint32 minRandomBotReviveTime, maxRandomBotReviveTime; uint32 minRandomBotReviveTime, maxRandomBotReviveTime;
uint32 minRandomBotTeleportInterval, maxRandomBotTeleportInterval; uint32 minRandomBotTeleportInterval, maxRandomBotTeleportInterval;
uint32 randomBotInWorldWithRotaionDisabled;
uint32 minRandomBotPvpTime, maxRandomBotPvpTime; uint32 minRandomBotPvpTime, maxRandomBotPvpTime;
uint32 randomBotsPerInterval; uint32 randomBotsPerInterval;
uint32 minRandomBotsPriceChangeInterval, maxRandomBotsPriceChangeInterval; uint32 minRandomBotsPriceChangeInterval, maxRandomBotsPriceChangeInterval;
@@ -108,6 +109,8 @@ class PlayerbotAIConfig
bool randombotsWalkingRPGInDoors; bool randombotsWalkingRPGInDoors;
uint32 minEnchantingBotLevel; uint32 minEnchantingBotLevel;
uint32 randombotStartingLevel; uint32 randombotStartingLevel;
bool enableRotation;
uint32 rotationPoolSize;
bool gearscorecheck; bool gearscorecheck;
bool randomBotPreQuests; bool randomBotPreQuests;

View File

@@ -541,6 +541,7 @@ void PlayerbotFactory::InitPetTalents()
// LOG_INFO("playerbots", "{} init pet talents failed with petTalentType < 0({})", bot->GetName().c_str(), pet_family->petTalentType); // LOG_INFO("playerbots", "{} init pet talents failed with petTalentType < 0({})", bot->GetName().c_str(), pet_family->petTalentType);
return; return;
} }
pet->resetTalents();
std::map<uint32, std::vector<TalentEntry const*> > spells; std::map<uint32, std::vector<TalentEntry const*> > spells;
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
{ {
@@ -798,7 +799,9 @@ void PlayerbotFactory::InitTalentsTree(bool increment/*false*/, bool use_templat
{ {
uint32 specNo; uint32 specNo;
uint8 cls = bot->getClass(); uint8 cls = bot->getClass();
if (increment && bot->GetFreeTalentPoints() <= 2) { std::map<uint8, uint32> tabs = AiFactory::GetPlayerSpecTabs(bot);
uint32 total_tabs = tabs[0] + tabs[1] + tabs[2];
if (increment && bot->GetFreeTalentPoints() <= 2 && total_tabs != 0) {
specNo = AiFactory::GetPlayerSpecTab(bot); specNo = AiFactory::GetPlayerSpecTab(bot);
} else { } else {
uint32 point = urand(0, 100); uint32 point = urand(0, 100);

View File

@@ -287,10 +287,10 @@ void RandomPlayerbotFactory::CreateRandomBots()
} }
PlayerbotsDatabase.Execute(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_RANDOM_BOTS)); PlayerbotsDatabase.Execute(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_RANDOM_BOTS));
CharacterDatabase.Execute("UPDATE playerbots_names SET in_use=0 WHERE in_use=1"); CharacterDatabase.DirectExecute("UPDATE playerbots_names SET in_use = 0 WHERE in_use = 1");
/* TODO(yunfan): we need to sleep here to wait for async account deleted, or the newly account won't be created correctly /* TODO(yunfan): we need to sleep here to wait for async account deleted, or the newly account won't be created correctly
the better way is turning the async db operation to sync db operation */ the better way is turning the async db operation to sync db operation */
std::this_thread::sleep_for(100ms * sPlayerbotAIConfig->randomBotAccountCount); std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount);
LOG_INFO("playerbots", "Random bot characters deleted."); LOG_INFO("playerbots", "Random bot characters deleted.");
LOG_INFO("playerbots", "Please reset the AiPlayerbot.DeleteRandomBotAccounts to 0 and restart the server..."); LOG_INFO("playerbots", "Please reset the AiPlayerbot.DeleteRandomBotAccounts to 0 and restart the server...");
World::StopNow(SHUTDOWN_EXIT_CODE); World::StopNow(SHUTDOWN_EXIT_CODE);
@@ -335,7 +335,7 @@ void RandomPlayerbotFactory::CreateRandomBots()
if (account_creation) { if (account_creation) {
/* wait for async accounts create to make character create correctly, same as account delete */ /* wait for async accounts create to make character create correctly, same as account delete */
std::this_thread::sleep_for(100ms * sPlayerbotAIConfig->randomBotAccountCount); std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount);
} }
LOG_INFO("playerbots", "Creating random bot characters..."); LOG_INFO("playerbots", "Creating random bot characters...");
@@ -403,7 +403,7 @@ void RandomPlayerbotFactory::CreateRandomBots()
if (bot_creation) { if (bot_creation) {
LOG_INFO("playerbots", "Waiting for {} characters loading into database...", totalCharCount); LOG_INFO("playerbots", "Waiting for {} characters loading into database...", totalCharCount);
/* wait for characters load into database, or characters will fail to loggin */ /* wait for characters load into database, or characters will fail to loggin */
std::this_thread::sleep_for(15ms * totalCharCount); std::this_thread::sleep_for(10s);
} }
for (WorldSession* session : sessionBots) for (WorldSession* session : sessionBots)

View File

@@ -337,6 +337,11 @@ uint32 RandomPlayerbotMgr::AddRandomBots()
for (std::vector<uint32>::iterator i = sPlayerbotAIConfig->randomBotAccounts.begin(); i != sPlayerbotAIConfig->randomBotAccounts.end(); i++) for (std::vector<uint32>::iterator i = sPlayerbotAIConfig->randomBotAccounts.begin(); i != sPlayerbotAIConfig->randomBotAccounts.end(); i++)
{ {
uint32 accountId = *i; uint32 accountId = *i;
if (sPlayerbotAIConfig->enableRotation) {
uint32 limit = std::min((uint32)sPlayerbotAIConfig->randomBotAccounts.size(), sPlayerbotAIConfig->rotationPoolSize / 10 + 1);
uint32 index = urand(0, limit);
accountId = sPlayerbotAIConfig->randomBotAccounts[index];
}
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID);
stmt->SetData(0, accountId); stmt->SetData(0, accountId);
PreparedQueryResult result = CharacterDatabase.Query(stmt); PreparedQueryResult result = CharacterDatabase.Query(stmt);
@@ -359,8 +364,12 @@ uint32 RandomPlayerbotMgr::AddRandomBots()
if (std::find(currentBots.begin(), currentBots.end(), guid) != currentBots.end()) if (std::find(currentBots.begin(), currentBots.end(), guid) != currentBots.end())
continue; continue;
SetEventValue(guid, "add", 1, urand(sPlayerbotAIConfig->minRandomBotInWorldTime, sPlayerbotAIConfig->maxRandomBotInWorldTime)); uint32 add_time = sPlayerbotAIConfig->enableRotation ?
urand(sPlayerbotAIConfig->minRandomBotInWorldTime, sPlayerbotAIConfig->maxRandomBotInWorldTime) :
sPlayerbotAIConfig->randomBotInWorldWithRotaionDisabled;
SetEventValue(guid, "add", 1, add_time);
SetEventValue(guid, "logout", 0, 0); SetEventValue(guid, "logout", 0, 0);
currentBots.push_back(guid); currentBots.push_back(guid);
@@ -969,8 +978,8 @@ void RandomPlayerbotMgr::Revive(Player* player)
SetEventValue(bot, "revive", 0, 0); SetEventValue(bot, "revive", 0, 0);
RandomTeleportGrindForLevel(player);
Refresh(player); Refresh(player);
RandomTeleportGrindForLevel(player);
} }
void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth) void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth)

View File

@@ -337,7 +337,7 @@ bool AutoSetTalentsAction::Execute(Event event)
PlayerbotFactory factory(bot, bot->GetLevel()); PlayerbotFactory factory(bot, bot->GetLevel());
factory.InitTalentsTree(true, true, true); factory.InitTalentsTree(true, true, true);
factory.InitPetTalents();
botAI->TellMaster(out); botAI->TellMaster(out);
return true; return true;

View File

@@ -179,7 +179,7 @@ bool QuestAction::AcceptQuest(Quest const* quest, ObjectGuid questGiver)
p.rpos(0); p.rpos(0);
bot->GetSession()->HandleQuestgiverAcceptQuestOpcode(p); bot->GetSession()->HandleQuestgiverAcceptQuestOpcode(p);
if (bot->GetQuestStatus(questId) == QUEST_STATUS_NONE && !sPlayerbotAIConfig->syncQuestWithPlayer) if (bot->GetQuestStatus(questId ) == QUEST_STATUS_NONE && sPlayerbotAIConfig->syncQuestWithPlayer)
{ {
Object* pObject = ObjectAccessor::GetObjectByTypeMask(*bot, questGiver, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); Object* pObject = ObjectAccessor::GetObjectByTypeMask(*bot, questGiver, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM);
bot->AddQuest(quest, pObject); bot->AddQuest(quest, pObject);
@@ -191,6 +191,7 @@ bool QuestAction::AcceptQuest(Quest const* quest, ObjectGuid questGiver)
botAI->TellMaster(out); botAI->TellMaster(out);
return true; return true;
} }
out << "Cannot accept";
} }
out << " " << chat->FormatQuest(quest); out << " " << chat->FormatQuest(quest);

View File

@@ -13,6 +13,9 @@ bool QuestConfirmAcceptAction::Execute(Event event)
if (!quest || !bot->CanAddQuest(quest, true)) { if (!quest || !bot->CanAddQuest(quest, true)) {
return false; return false;
} }
std::ostringstream out;
out << "Quest: " << chat->FormatQuest(quest) << " confirm accept";
botAI->TellMaster(out);
bot->GetSession()->HandleQuestConfirmAccept(sendPacket); bot->GetSession()->HandleQuestConfirmAccept(sendPacket);
return true; return true;
} }

View File

@@ -16,10 +16,10 @@ class Player;
class PlayerbotAI; class PlayerbotAI;
class WorldObject; class WorldObject;
class QuestConfirmAcceptAction : public QuestAction class QuestConfirmAcceptAction : public Action
{ {
public: public:
QuestConfirmAcceptAction(PlayerbotAI* botAI) : QuestAction(botAI, "quest confirm accept") {} QuestConfirmAcceptAction(PlayerbotAI* botAI) : Action(botAI, "quest confirm accept") {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };

View File

@@ -8,6 +8,7 @@
#include "ItemUsageValue.h" #include "ItemUsageValue.h"
#include "Object.h" #include "Object.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "QuestDef.h"
#include "WorldPacket.h" #include "WorldPacket.h"
void TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver) void TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver)
@@ -238,6 +239,7 @@ bool TurnInQueryQuestAction::Execute(Event event)
} }
} }
std::ostringstream out; std::ostringstream out;
out << "Quest ";
switch (status) switch (status)
{ {
case QUEST_STATUS_COMPLETE: case QUEST_STATUS_COMPLETE:
@@ -252,6 +254,9 @@ bool TurnInQueryQuestAction::Execute(Event event)
case QUEST_STATUS_FAILED: case QUEST_STATUS_FAILED:
out << "|cffff0000Failed|r"; out << "|cffff0000Failed|r";
break; break;
case QUEST_STATUS_REWARDED:
out << "|cffff0000Rewarded|r";
break;
} }
out << ": " << chat->FormatQuest(quest); out << ": " << chat->FormatQuest(quest);

View File

@@ -24,6 +24,7 @@
#include "QuestAction.h" #include "QuestAction.h"
#include "PassLeadershipToMasterAction.h" #include "PassLeadershipToMasterAction.h"
#include "PetitionSignAction.h" #include "PetitionSignAction.h"
#include "QuestConfirmAcceptAction.h"
#include "ReadyCheckAction.h" #include "ReadyCheckAction.h"
#include "RememberTaxiAction.h" #include "RememberTaxiAction.h"
#include "ReviveFromCorpseAction.h" #include "ReviveFromCorpseAction.h"
@@ -36,6 +37,7 @@
#include "TradeStatusAction.h" #include "TradeStatusAction.h"
#include "UseMeetingStoneAction.h" #include "UseMeetingStoneAction.h"
#include "NamedObjectContext.h" #include "NamedObjectContext.h"
#include "QuestConfirmAcceptAction.h"
class PlayerbotAI; class PlayerbotAI;
@@ -92,6 +94,7 @@ class WorldPacketActionContext : public NamedObjectContext<Action>
creators["see spell"] = &WorldPacketActionContext::see_spell; creators["see spell"] = &WorldPacketActionContext::see_spell;
creators["arena team accept"] = &WorldPacketActionContext::arena_team_accept; creators["arena team accept"] = &WorldPacketActionContext::arena_team_accept;
creators["turn in query quest"] = &WorldPacketActionContext::turn_in_query_quest; creators["turn in query quest"] = &WorldPacketActionContext::turn_in_query_quest;
creators["quest confirm accept"] = &WorldPacketActionContext::quest_confirm_accept;
} }
private: private:
@@ -143,6 +146,7 @@ class WorldPacketActionContext : public NamedObjectContext<Action>
static Action* see_spell(PlayerbotAI* botAI) { return new SeeSpellAction(botAI); } static Action* see_spell(PlayerbotAI* botAI) { return new SeeSpellAction(botAI); }
static Action* arena_team_accept(PlayerbotAI* botAI) { return new ArenaTeamAcceptAction(botAI); } static Action* arena_team_accept(PlayerbotAI* botAI) { return new ArenaTeamAcceptAction(botAI); }
static Action* turn_in_query_quest(PlayerbotAI* botAI) { return new TurnInQueryQuestAction(botAI); } static Action* turn_in_query_quest(PlayerbotAI* botAI) { return new TurnInQueryQuestAction(botAI); }
static Action* quest_confirm_accept(PlayerbotAI* botAI) { return new QuestConfirmAcceptAction(botAI); }
}; };
#endif #endif

View File

@@ -79,7 +79,6 @@ 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 is close", triggers.push_back(new TriggerNode("enemy is close",
NextAction::array(0, NextAction::array(0,
new NextAction("wing clip", ACTION_HIGH + 1), new NextAction("wing clip", ACTION_HIGH + 1),

View File

@@ -4,6 +4,7 @@
#include "RangeTriggers.h" #include "RangeTriggers.h"
#include "MoveSplineInit.h" #include "MoveSplineInit.h"
#include "PlayerbotAIConfig.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
@@ -16,8 +17,8 @@ bool EnemyTooCloseForSpellTrigger::IsActive()
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
return target && (target->GetVictim() != bot || target->isFrozen() || !target->CanFreeMove()) && return target && (target->GetVictim() != bot || target->isFrozen() || !target->CanFreeMove()) &&
target->GetObjectSize() <= 10.0f && target->GetObjectSize() <= 10.0f &&
AI_VALUE2(float, "distance", "current target") <= sPlayerbotAIConfig->tooCloseDistance; target->IsWithinCombatRange(bot, MIN_MELEE_REACH);
// Unit* target = AI_VALUE(Unit*, "current target"); // Unit* target = AI_VALUE(Unit*, "current target");
// if (!target) { // if (!target) {
// return false; // return false;
@@ -79,7 +80,9 @@ bool EnemyTooCloseForAutoShotTrigger::IsActive()
bool EnemyTooCloseForShootTrigger::IsActive() bool EnemyTooCloseForShootTrigger::IsActive()
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
return target && (target->GetVictim() != bot || target->isFrozen() || !target->CanFreeMove()) && AI_VALUE2(float, "distance", "current target") <= sPlayerbotAIConfig->shootDistance; // target->IsWithinCombatRange()
return target && (target->GetVictim() != bot || target->isFrozen() || !target->CanFreeMove()) && target->IsWithinCombatRange(bot, MIN_MELEE_REACH);
// Unit* target = AI_VALUE(Unit*, "current target"); // Unit* target = AI_VALUE(Unit*, "current target");
// if (!target) // if (!target)