Compare commits

..

1 Commits

Author SHA1 Message Date
Yunfan Li
8d09a08dfd Preparation for project transfer 2025-10-14 00:05:16 +08:00
17 changed files with 108 additions and 171 deletions

1
.gitignore vendored
View File

@@ -49,4 +49,3 @@ local.properties
.project .project
.cproject .cproject
.vscode .vscode
.idea

View File

@@ -93,9 +93,6 @@ The [Playerbots Wiki](https://github.com/mod-playerbots/mod-playerbots/wiki) con
- **What platforms are supported?** We support Ubuntu, Windows, and macOS. Other Linux distros may work, but will not receive support. - **What platforms are supported?** We support Ubuntu, Windows, and macOS. Other Linux distros may work, but will not receive support.
- **Why isn't my source compiling?** Please ensure that you are compiling with the required [custom branch of AzerothCore](https://github.com/mod-playerbots/azerothcore-wotlk/tree/Playerbot). Additionally, please [check the build status of our CI](https://github.com/mod-playerbots/mod-playerbots/actions). If the latest build is failing, rever to the last successful commit until we address the issue. - **Why isn't my source compiling?** Please ensure that you are compiling with the required [custom branch of AzerothCore](https://github.com/mod-playerbots/azerothcore-wotlk/tree/Playerbot). Additionally, please [check the build status of our CI](https://github.com/mod-playerbots/mod-playerbots/actions). If the latest build is failing, rever to the last successful commit until we address the issue.
## Code standards
- https://www.azerothcore.org/wiki/cpp-code-standards
## Addons ## Addons
Typically, bots are controlled via chat commands. For larger bot groups, this can be unwieldy. As an alternative, community members have developed client Add-Ons to allow controlling bots through the in-game UI. We recommend you check out their projects: Typically, bots are controlled via chat commands. For larger bot groups, this can be unwieldy. As an alternative, community members have developed client Add-Ons to allow controlling bots through the in-game UI. We recommend you check out their projects:

View File

@@ -284,6 +284,9 @@ AiPlayerbot.TwoRoundsGearInit = 0
# #
# #
# Bots will say information about items when collecting them
AiPlayerbot.SayWhenCollectingItems = 1
# Bots keep looting when loot system is set to free for all # Bots keep looting when loot system is set to free for all
# Default: 0 (disabled) # Default: 0 (disabled)
AiPlayerbot.FreeMethodLoot = 0 AiPlayerbot.FreeMethodLoot = 0
@@ -357,15 +360,15 @@ AiPlayerbot.LootDelay = 1000
# #
# #
# Distances are in yards
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.GrindDistance = 75.0
AiPlayerbot.HealDistance = 38.5 AiPlayerbot.HealDistance = 38.5
AiPlayerbot.LootDistance = 15.0 AiPlayerbot.LootDistance = 15.0
AiPlayerbot.FleeDistance = 5.0 AiPlayerbot.FleeDistance = 5.0
AiPlayerbot.AggroDistance = 22
AiPlayerbot.TooCloseDistance = 5.0 AiPlayerbot.TooCloseDistance = 5.0
AiPlayerbot.MeleeDistance = 0.75 AiPlayerbot.MeleeDistance = 0.75
AiPlayerbot.FollowDistance = 1.5 AiPlayerbot.FollowDistance = 1.5
@@ -373,8 +376,7 @@ AiPlayerbot.WhisperDistance = 6000.0
AiPlayerbot.ContactDistance = 0.45 AiPlayerbot.ContactDistance = 0.45
AiPlayerbot.AoeRadius = 10 AiPlayerbot.AoeRadius = 10
AiPlayerbot.RpgDistance = 200 AiPlayerbot.RpgDistance = 200
AiPlayerbot.GrindDistance = 75.0 AiPlayerbot.AggroDistance = 22
AiPlayerbot.ReactDistance = 150.0
# #
# #
@@ -482,8 +484,7 @@ AiPlayerbot.RPWarningCooldown = 30
# #
# #
# Enable/Disable maintenance command # Enable/Disable maintenance command (learn all available spells and skills, supplement consumables, repair, enchant equipment if bot's level is above AiPlayerbot.MinEnchantingBotLevel)
# Learn all available spells and skills, refresh consumables, repair, enchant equipment and socket gems if bot's level is above AiPlayerbot.MinEnchantingBotLevel
# Default: 1 (enabled) # Default: 1 (enabled)
AiPlayerbot.MaintenanceCommand = 1 AiPlayerbot.MaintenanceCommand = 1
@@ -547,7 +548,7 @@ AiPlayerbot.AutoGearScoreLimit = 0
# "mana" (bots have infinite mana) # "mana" (bots have infinite mana)
# "power" (bots have infinite energy, rage, and runic power) # "power" (bots have infinite energy, rage, and runic power)
# "taxi" (bots may use all flight paths, though they will not actually learn them) # "taxi" (bots may use all flight paths, though they will not actually learn them)
# "raid" (bots use cheats implemented into raid strategies (currently only for Ulduar)) # "raid" (bots use cheats implemented into raid strategies)
# To use multiple cheats, separate them by commas below (e.g., to enable all, use "gold,health,mana,power,raid,taxi") # To use multiple cheats, separate them by commas below (e.g., to enable all, use "gold,health,mana,power,raid,taxi")
# Default: food, taxi, and raid are enabled # Default: food, taxi, and raid are enabled
AiPlayerbot.BotCheats = "food,taxi,raid" AiPlayerbot.BotCheats = "food,taxi,raid"
@@ -605,11 +606,9 @@ AiPlayerbot.RandomBotMaxLevel = 80
AiPlayerbot.SyncLevelWithPlayers = 0 AiPlayerbot.SyncLevelWithPlayers = 0
# Mark many quests ≤ bot level as complete (slows down bot creation) # Mark many quests ≤ bot level as complete (slows down bot creation)
# Default: 0 (disabled)
AiPlayerbot.PreQuests = 0 AiPlayerbot.PreQuests = 0
# Enable LFG for randombots # Enable LFG for randombots
# Default: 1 (enabled)
AiPlayerbot.RandomBotJoinLfg = 1 AiPlayerbot.RandomBotJoinLfg = 1
# Enable/Disable periodic online - offline of randombots to mimic the real-world scenario where not all players are online simultaneously # Enable/Disable periodic online - offline of randombots to mimic the real-world scenario where not all players are online simultaneously
@@ -630,8 +629,7 @@ AiPlayerbot.RandomBotHordeRatio = 50
AiPlayerbot.DisableDeathKnightLogin = 0 AiPlayerbot.DisableDeathKnightLogin = 0
# Enable simulated expansion limitation for talents and glyphs # Enable simulated expansion limitation for talents and glyphs
# If enabled, limits talent trees to 5 rows plus the middle talent of the 6th row for bots until level 61 # If enabled, limits talent trees to 5 rows plus the middle talent of the 6th row for bots until level 61 and 7 rows plus the middle talent of the 8th row for bots until level 71
# and 7 rows plus the middle talent of the 8th row for bots from level 61 until level 71
# Default: 0 (disabled) # Default: 0 (disabled)
AiPlayerbot.LimitTalentsExpansion = 0 AiPlayerbot.LimitTalentsExpansion = 0
@@ -715,8 +713,8 @@ AiPlayerbot.IncrementalGearInit = 1
# Default: 60 # Default: 60
AiPlayerbot.MinEnchantingBotLevel = 60 AiPlayerbot.MinEnchantingBotLevel = 60
# Enable expansion limitation for bot enchants and gems # Enable expansion limitation for bot enchants
# If enabled, bots will not use TBC enchants until level 61 or WotLK enchants and gems until level 71 # If enabled, bots will not use TBC enchants until level 61 or WotLK enchants until level 71
# Default: 1 (enabled) # Default: 1 (enabled)
AiPlayerbot.LimitEnchantExpansion = 1 AiPlayerbot.LimitEnchantExpansion = 1
@@ -812,7 +810,7 @@ AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel = 80
# #
# Quest that will be completed and rewarded for all randombots # Quest that will be completed and rewarded for all randombots
AiPlayerbot.RandomBotQuestIds = "3802,5505,6502,7761,7848,10277,10285,11492,13188,13189,24499,24511,24710,24712" AiPlayerbot.RandomBotQuestIds = "7848,3802,5505,6502,7761,10277,10285,11492,13188,13189,24499,24511,24710,24712"
# Randombots will group with nearby randombots to do shared quests # Randombots will group with nearby randombots to do shared quests
AiPlayerbot.RandomBotGroupNearby = 0 AiPlayerbot.RandomBotGroupNearby = 0
@@ -873,9 +871,9 @@ AiPlayerbot.RandomBotNonCombatStrategies = ""
AiPlayerbot.CombatStrategies = "" AiPlayerbot.CombatStrategies = ""
AiPlayerbot.NonCombatStrategies = "" AiPlayerbot.NonCombatStrategies = ""
# Remove "healer dps" strategy on the maps specified below. # Remove "healer dps" strategy on specified maps.
# Default: 1 (enabled) # Default: 0 (disabled)
AiPlayerbot.HealerDPSMapRestriction = 1 AiPlayerbot.HealerDPSMapRestriction = 0
# List of Map IDs where "healer dps" strategy will be removed if AiPlayerbot.HealerDPSMapRestriction is enabled # List of Map IDs where "healer dps" strategy will be removed if AiPlayerbot.HealerDPSMapRestriction is enabled
# Default: (Dungeon and Raid maps) "33,34,36,43,47,48,70,90,109,129,209,229,230,329,349,389,429,1001,1004,1007,269,540,542,543,545,546,547,552,553,554,555,556,557,558,560,585,574,575,576,578,595,599,600,601,602,604,608,619,632,650,658,668,409,469,509,531,532,534,544,548,550,564,565,580,249,533,603,615,616,624,631,649,724" # Default: (Dungeon and Raid maps) "33,34,36,43,47,48,70,90,109,129,209,229,230,329,349,389,429,1001,1004,1007,269,540,542,543,545,546,547,552,553,554,555,556,557,558,560,585,574,575,576,578,595,599,600,601,602,604,608,619,632,650,658,668,409,469,509,531,532,534,544,548,550,564,565,580,249,533,603,615,616,624,631,649,724"
@@ -1059,8 +1057,7 @@ AiPlayerbot.ZoneBracket.4197 = 79,80
# #
# #
# Map IDs where bots can be teleported to # Maps where bots can be teleported to
# Defaults: 0 = Eastern Kingdoms, 1 = Kalimdor, 530 = Outland, 571 = Northrend
AiPlayerbot.RandomBotMaps = 0,1,530,571 AiPlayerbot.RandomBotMaps = 0,1,530,571
# Probabilty bots teleport to banker (city) # Probabilty bots teleport to banker (city)

View File

@@ -57,54 +57,55 @@ void LoadListString(std::string const value, T& list)
bool PlayerbotAIConfig::Initialize() bool PlayerbotAIConfig::Initialize()
{ {
LOG_INFO("server.loading", "Initializing mod-playerbots, based on AI Playerbots by ike3 and the original Playerbots by blueboy"); LOG_INFO("server.loading", "Initializing AI Playerbots by ike3, based on the original Playerbots by blueboy");
enabled = sConfigMgr->GetOption<bool>("AiPlayerbot.Enabled", true); enabled = sConfigMgr->GetOption<bool>("AiPlayerbot.Enabled", true);
if (!enabled) if (!enabled)
{ {
LOG_INFO("server.loading", "Playerbots Module is disabled in playerbots.conf"); LOG_INFO("server.loading", "AI Playerbots is Disabled in aiplayerbot.conf");
return false; return false;
} }
globalCoolDown = sConfigMgr->GetOption<int32>("AiPlayerbot.GlobalCooldown", 500); globalCoolDown = sConfigMgr->GetOption<int32>("AiPlayerbot.GlobalCooldown", 1500);
maxWaitForMove = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxWaitForMove", 5000); maxWaitForMove = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxWaitForMove", 5000);
disableMoveSplinePath = sConfigMgr->GetOption<int32>("AiPlayerbot.DisableMoveSplinePath", 0); disableMoveSplinePath = sConfigMgr->GetOption<int32>("AiPlayerbot.DisableMoveSplinePath", 0);
maxMovementSearchTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxMovementSearchTime", 3); maxMovementSearchTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxMovementSearchTime", 3);
expireActionTime = sConfigMgr->GetOption<int32>("AiPlayerbot.ExpireActionTime", 5000); expireActionTime = sConfigMgr->GetOption<int32>("AiPlayerbot.ExpireActionTime", 5000);
dispelAuraDuration = sConfigMgr->GetOption<int32>("AiPlayerbot.DispelAuraDuration", 700); dispelAuraDuration = sConfigMgr->GetOption<int32>("AiPlayerbot.DispelAuraDuration", 7000);
reactDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.ReactDelay", 100); reactDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.ReactDelay", 100);
dynamicReactDelay = sConfigMgr->GetOption<bool>("AiPlayerbot.DynamicReactDelay", true); dynamicReactDelay = sConfigMgr->GetOption<bool>("AiPlayerbot.DynamicReactDelay", true);
passiveDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.PassiveDelay", 10000); passiveDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.PassiveDelay", 10000);
repeatDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.RepeatDelay", 2000); repeatDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.RepeatDelay", 2000);
errorDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.ErrorDelay", 100); errorDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.ErrorDelay", 5000);
rpgDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.RpgDelay", 10000); rpgDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.RpgDelay", 10000);
sitDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.SitDelay", 20000); sitDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.SitDelay", 30000);
returnDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.ReturnDelay", 2000); returnDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.ReturnDelay", 7000);
lootDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.LootDelay", 1000); lootDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.LootDelay", 1000);
// Buff system
minBotsForGreaterBuff = sConfigMgr->GetOption<int32>("AiPlayerbot.MinBotsForGreaterBuff", 3); minBotsForGreaterBuff = sConfigMgr->GetOption<int32>("AiPlayerbot.MinBotsForGreaterBuff", 3);
rpWarningCooldown = sConfigMgr->GetOption<int32>("AiPlayerbot.RPWarningCooldown", 30); rpWarningCooldown = sConfigMgr->GetOption<int32>("AiPlayerbot.RPWarningCooldown", 30);
disabledWithoutRealPlayerLoginDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.DisabledWithoutRealPlayerLoginDelay", 30); disabledWithoutRealPlayerLoginDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.DisabledWithoutRealPlayerLoginDelay", 30);
disabledWithoutRealPlayerLogoutDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay", 300); disabledWithoutRealPlayerLogoutDelay = sConfigMgr->GetOption<int32>("AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay", 300);
farDistance = sConfigMgr->GetOption<float>("AiPlayerbot.FarDistance", 20.0f); farDistance = sConfigMgr->GetOption<float>("AiPlayerbot.FarDistance", 20.0f);
sightDistance = sConfigMgr->GetOption<float>("AiPlayerbot.SightDistance", 100.0f); sightDistance = sConfigMgr->GetOption<float>("AiPlayerbot.SightDistance", 75.0f);
spellDistance = sConfigMgr->GetOption<float>("AiPlayerbot.SpellDistance", 28.5f); spellDistance = sConfigMgr->GetOption<float>("AiPlayerbot.SpellDistance", 25.0f);
shootDistance = sConfigMgr->GetOption<float>("AiPlayerbot.ShootDistance", 5.0f); shootDistance = sConfigMgr->GetOption<float>("AiPlayerbot.ShootDistance", 25.0f);
healDistance = sConfigMgr->GetOption<float>("AiPlayerbot.HealDistance", 38.5f); healDistance = sConfigMgr->GetOption<float>("AiPlayerbot.HealDistance", 25.0f);
lootDistance = sConfigMgr->GetOption<float>("AiPlayerbot.LootDistance", 15.0f); lootDistance = sConfigMgr->GetOption<float>("AiPlayerbot.LootDistance", 15.0f);
fleeDistance = sConfigMgr->GetOption<float>("AiPlayerbot.FleeDistance", 5.0f); fleeDistance = sConfigMgr->GetOption<float>("AiPlayerbot.FleeDistance", 7.5f);
aggroDistance = sConfigMgr->GetOption<float>("AiPlayerbot.AggroDistance", 22.0f); aggroDistance = sConfigMgr->GetOption<float>("AiPlayerbot.AggroDistance", 22.0f);
tooCloseDistance = sConfigMgr->GetOption<float>("AiPlayerbot.TooCloseDistance", 5.0f); tooCloseDistance = sConfigMgr->GetOption<float>("AiPlayerbot.TooCloseDistance", 5.0f);
meleeDistance = sConfigMgr->GetOption<float>("AiPlayerbot.MeleeDistance", 0.75f); meleeDistance = sConfigMgr->GetOption<float>("AiPlayerbot.MeleeDistance", 0.75f);
followDistance = sConfigMgr->GetOption<float>("AiPlayerbot.FollowDistance", 1.5f); followDistance = sConfigMgr->GetOption<float>("AiPlayerbot.FollowDistance", 1.5f);
whisperDistance = sConfigMgr->GetOption<float>("AiPlayerbot.WhisperDistance", 6000.0f); whisperDistance = sConfigMgr->GetOption<float>("AiPlayerbot.WhisperDistance", 6000.0f);
contactDistance = sConfigMgr->GetOption<float>("AiPlayerbot.ContactDistance", 0.45f); contactDistance = sConfigMgr->GetOption<float>("AiPlayerbot.ContactDistance", 0.5f);
aoeRadius = sConfigMgr->GetOption<float>("AiPlayerbot.AoeRadius", 10.0f); aoeRadius = sConfigMgr->GetOption<float>("AiPlayerbot.AoeRadius", 5.0f);
rpgDistance = sConfigMgr->GetOption<float>("AiPlayerbot.RpgDistance", 200.0f); rpgDistance = sConfigMgr->GetOption<float>("AiPlayerbot.RpgDistance", 200.0f);
grindDistance = sConfigMgr->GetOption<float>("AiPlayerbot.GrindDistance", 75.0f); grindDistance = sConfigMgr->GetOption<float>("AiPlayerbot.GrindDistance", 75.0f);
reactDistance = sConfigMgr->GetOption<float>("AiPlayerbot.ReactDistance", 150.0f); reactDistance = sConfigMgr->GetOption<float>("AiPlayerbot.ReactDistance", 150.0f);
criticalHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.CriticalHealth", 25); criticalHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.CriticalHealth", 20);
lowHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.LowHealth", 45); lowHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.LowHealth", 45);
mediumHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.MediumHealth", 65); mediumHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.MediumHealth", 65);
almostFullHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.AlmostFullHealth", 85); almostFullHealth = sConfigMgr->GetOption<int32>("AiPlayerbot.AlmostFullHealth", 85);
@@ -115,7 +116,7 @@ bool PlayerbotAIConfig::Initialize()
saveManaThreshold = sConfigMgr->GetOption<int32>("AiPlayerbot.SaveManaThreshold", 60); saveManaThreshold = sConfigMgr->GetOption<int32>("AiPlayerbot.SaveManaThreshold", 60);
autoAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoAvoidAoe", true); autoAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoAvoidAoe", true);
maxAoeAvoidRadius = sConfigMgr->GetOption<float>("AiPlayerbot.MaxAoeAvoidRadius", 15.0f); maxAoeAvoidRadius = sConfigMgr->GetOption<float>("AiPlayerbot.MaxAoeAvoidRadius", 15.0f);
LoadSet<std::set<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.AoeAvoidSpellWhitelist", "50759,57491,13810,29946"), LoadSet<std::set<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.AoeAvoidSpellWhitelist", "50759,57491,13810"),
aoeAvoidSpellWhitelist); aoeAvoidSpellWhitelist);
tellWhenAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.TellWhenAvoidAoe", false); tellWhenAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.TellWhenAvoidAoe", false);
@@ -128,7 +129,7 @@ bool PlayerbotAIConfig::Initialize()
randomBotMaxLevelChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotMaxLevelChance", 0.1f); randomBotMaxLevelChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotMaxLevelChance", 0.1f);
randomBotRpgChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotRpgChance", 0.20f); randomBotRpgChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotRpgChance", 0.20f);
iterationsPerTick = sConfigMgr->GetOption<int32>("AiPlayerbot.IterationsPerTick", 10); iterationsPerTick = sConfigMgr->GetOption<int32>("AiPlayerbot.IterationsPerTick", 100);
allowAccountBots = sConfigMgr->GetOption<bool>("AiPlayerbot.AllowAccountBots", true); allowAccountBots = sConfigMgr->GetOption<bool>("AiPlayerbot.AllowAccountBots", true);
allowGuildBots = sConfigMgr->GetOption<bool>("AiPlayerbot.AllowGuildBots", true); allowGuildBots = sConfigMgr->GetOption<bool>("AiPlayerbot.AllowGuildBots", true);
@@ -142,11 +143,11 @@ bool PlayerbotAIConfig::Initialize()
LoadList<std::vector<uint32>>(randomBotMapsAsString, randomBotMaps); LoadList<std::vector<uint32>>(randomBotMapsAsString, randomBotMaps);
probTeleToBankers = sConfigMgr->GetOption<float>("AiPlayerbot.ProbTeleToBankers", 0.25f); probTeleToBankers = sConfigMgr->GetOption<float>("AiPlayerbot.ProbTeleToBankers", 0.25f);
enableWeightTeleToCityBankers = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableWeightTeleToCityBankers", false); enableWeightTeleToCityBankers = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableWeightTeleToCityBankers", false);
weightTeleToStormwind = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToStormwindWeight", 2); weightTeleToStormwind = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToStormwindWeight", 1);
weightTeleToIronforge = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToIronforgeWeight", 1); weightTeleToIronforge = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToIronforgeWeight", 1);
weightTeleToDarnassus = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToDarnassusWeight", 1); weightTeleToDarnassus = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToDarnassusWeight", 1);
weightTeleToExodar = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToExodarWeight", 1); weightTeleToExodar = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToExodarWeight", 1);
weightTeleToOrgrimmar = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToOrgrimmarWeight", 2); weightTeleToOrgrimmar = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToOrgrimmarWeight", 1);
weightTeleToUndercity = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToUndercityWeight", 1); weightTeleToUndercity = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToUndercityWeight", 1);
weightTeleToThunderBluff = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToThunderBluffWeight", 1); weightTeleToThunderBluff = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToThunderBluffWeight", 1);
weightTeleToSilvermoonCity = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToSilvermoonCityWeight", 1); weightTeleToSilvermoonCity = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToSilvermoonCityWeight", 1);
@@ -154,7 +155,7 @@ bool PlayerbotAIConfig::Initialize()
weightTeleToDalaran = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToDalaranWeight", 1); weightTeleToDalaran = sConfigMgr->GetOption<int>("AiPlayerbot.TeleToDalaranWeight", 1);
LoadList<std::vector<uint32>>( LoadList<std::vector<uint32>>(
sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestItems", sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestItems",
"5175,5176,5177,5178,6948,11000,12382,13704,16309"), "6948,5175,5176,5177,5178,16309,12382,13704,11000"),
randomBotQuestItems); randomBotQuestItems);
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotSpellIds", "54197"), LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotSpellIds", "54197"),
randomBotSpellIds); randomBotSpellIds);
@@ -169,7 +170,7 @@ bool PlayerbotAIConfig::Initialize()
pvpProhibitedAreaIds); pvpProhibitedAreaIds);
fastReactInBG = sConfigMgr->GetOption<bool>("AiPlayerbot.FastReactInBG", true); fastReactInBG = sConfigMgr->GetOption<bool>("AiPlayerbot.FastReactInBG", true);
LoadList<std::vector<uint32>>( LoadList<std::vector<uint32>>(
sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestIds", "3802,5505,6502,7761,7848,10277,10285,11492,13188,13189,24499,24511,24710,24712"), sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestIds", "7848,3802,5505,6502,7761,10277,10285,11492,13188,13189,24499,24511,24710,24712"),
randomBotQuestIds); randomBotQuestIds);
LoadSet<std::set<uint32>>( LoadSet<std::set<uint32>>(
@@ -180,8 +181,8 @@ bool PlayerbotAIConfig::Initialize()
disallowedGameObjects); disallowedGameObjects);
botAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.BotAutologin", false); botAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.BotAutologin", false);
randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true); randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true);
minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 500); minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 50);
maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 500); maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 50);
randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", 20); randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", 20);
randomBotCountChangeMinInterval = randomBotCountChangeMinInterval =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE); sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE);
@@ -390,8 +391,8 @@ bool PlayerbotAIConfig::Initialize()
randomBotCombatStrategies = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotCombatStrategies", ""); randomBotCombatStrategies = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotCombatStrategies", "");
randomBotNonCombatStrategies = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotNonCombatStrategies", ""); randomBotNonCombatStrategies = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotNonCombatStrategies", "");
combatStrategies = sConfigMgr->GetOption<std::string>("AiPlayerbot.CombatStrategies", ""); combatStrategies = sConfigMgr->GetOption<std::string>("AiPlayerbot.CombatStrategies", "+custom::say");
nonCombatStrategies = sConfigMgr->GetOption<std::string>("AiPlayerbot.NonCombatStrategies", ""); nonCombatStrategies = sConfigMgr->GetOption<std::string>("AiPlayerbot.NonCombatStrategies", "+custom::say,+return");
applyInstanceStrategies = sConfigMgr->GetOption<bool>("AiPlayerbot.ApplyInstanceStrategies", true); applyInstanceStrategies = sConfigMgr->GetOption<bool>("AiPlayerbot.ApplyInstanceStrategies", true);
commandPrefix = sConfigMgr->GetOption<std::string>("AiPlayerbot.CommandPrefix", ""); commandPrefix = sConfigMgr->GetOption<std::string>("AiPlayerbot.CommandPrefix", "");
@@ -511,7 +512,7 @@ bool PlayerbotAIConfig::Initialize()
randomBotGuildSizeMax = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotGuildSizeMax", 15); randomBotGuildSizeMax = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotGuildSizeMax", 15);
deleteRandomBotGuilds = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotGuilds", false); deleteRandomBotGuilds = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotGuilds", false);
guildTaskEnabled = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableGuildTasks", false); guildTaskEnabled = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableGuildTasks", true);
minGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600); minGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600);
maxGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600); maxGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600);
minGuildTaskAdvertisementTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskAdvertisementTime", 300); minGuildTaskAdvertisementTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskAdvertisementTime", 300);
@@ -597,12 +598,12 @@ bool PlayerbotAIConfig::Initialize()
minEnchantingBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.MinEnchantingBotLevel", 60); minEnchantingBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.MinEnchantingBotLevel", 60);
limitEnchantExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitEnchantExpansion", 1); limitEnchantExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitEnchantExpansion", 1);
limitGearExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitGearExpansion", 1); limitGearExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitGearExpansion", 1);
randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 1); randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5);
enablePeriodicOnlineOffline = sConfigMgr->GetOption<bool>("AiPlayerbot.EnablePeriodicOnlineOffline", false); enablePeriodicOnlineOffline = sConfigMgr->GetOption<bool>("AiPlayerbot.EnablePeriodicOnlineOffline", false);
enableRandomBotTrading = sConfigMgr->GetOption<int32>("AiPlayerbot.EnableRandomBotTrading", 1); enableRandomBotTrading = sConfigMgr->GetOption<int32>("AiPlayerbot.EnableRandomBotTrading", 1);
periodicOnlineOfflineRatio = sConfigMgr->GetOption<float>("AiPlayerbot.PeriodicOnlineOfflineRatio", 2.0); periodicOnlineOfflineRatio = sConfigMgr->GetOption<float>("AiPlayerbot.PeriodicOnlineOfflineRatio", 2.0);
gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false); gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false);
randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", false); randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true);
// SPP automation // SPP automation
freeMethodLoot = sConfigMgr->GetOption<bool>("AiPlayerbot.FreeMethodLoot", false); freeMethodLoot = sConfigMgr->GetOption<bool>("AiPlayerbot.FreeMethodLoot", false);
@@ -635,7 +636,7 @@ bool PlayerbotAIConfig::Initialize()
RpgStatusProbWeight[RPG_REST] = sConfigMgr->GetOption<int32>("AiPlayerbot.RpgStatusProbWeight.Rest", 5); RpgStatusProbWeight[RPG_REST] = sConfigMgr->GetOption<int32>("AiPlayerbot.RpgStatusProbWeight.Rest", 5);
syncLevelWithPlayers = sConfigMgr->GetOption<bool>("AiPlayerbot.SyncLevelWithPlayers", false); syncLevelWithPlayers = sConfigMgr->GetOption<bool>("AiPlayerbot.SyncLevelWithPlayers", false);
randomBotGroupNearby = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGroupNearby", false); randomBotGroupNearby = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGroupNearby", true);
// arena // arena
randomBotArenaTeam2v2Count = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeam2v2Count", 10); randomBotArenaTeam2v2Count = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotArenaTeam2v2Count", 10);
@@ -678,7 +679,7 @@ bool PlayerbotAIConfig::Initialize()
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.ExcludedHunterPetFamilies", ""), excludedHunterPetFamilies); LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.ExcludedHunterPetFamilies", ""), excludedHunterPetFamilies);
LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", "---------------------------------------");
LOG_INFO("server.loading", " mod-playerbots initialized "); LOG_INFO("server.loading", " AI Playerbots initialized ");
LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", "---------------------------------------");
return true; return true;

View File

@@ -220,8 +220,7 @@ public:
bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) override bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) override
{ {
if ((sRandomPlayerbotMgr->IsRandomBot(player) || sRandomPlayerbotMgr->IsAddclassBot(player)) && if (sRandomPlayerbotMgr->IsRandomBot(player) && (achievement->flags == 256 || achievement->flags == 768))
(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)))
{ {
return false; return false;
} }

View File

@@ -4287,7 +4287,7 @@ void PlayerbotFactory::ApplyEnchantTemplate(uint8 spec)
// const SpellItemEnchantmentEntry* a = sSpellItemEnchantmentStore.LookupEntry(1); // const SpellItemEnchantmentEntry* a = sSpellItemEnchantmentStore.LookupEntry(1);
} }
void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destroyOld) void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destoryOld)
{ {
//int32 bestGemEnchantId[4] = {-1, -1, -1, -1}; // 1, 2, 4, 8 color //not used, line marked for removal. //int32 bestGemEnchantId[4] = {-1, -1, -1, -1}; // 1, 2, 4, 8 color //not used, line marked for removal.
//float bestGemScore[4] = {0, 0, 0, 0}; //not used, line marked for removal. //float bestGemScore[4] = {0, 0, 0, 0}; //not used, line marked for removal.

View File

@@ -79,7 +79,7 @@ public:
void InitFood(); void InitFood();
void InitMounts(); void InitMounts();
void InitBags(bool destroyOld = true); void InitBags(bool destroyOld = true);
void ApplyEnchantAndGemsNew(bool destroyOld = true); void ApplyEnchantAndGemsNew(bool destoryOld = true);
void InitInstanceQuests(); void InitInstanceQuests();
void UnbindInstance(); void UnbindInstance();
void InitKeyring(); void InitKeyring();

View File

@@ -92,18 +92,9 @@ float StatsWeightCalculator::CalculateItem(uint32 itemId, int32 randomPropertyId
CalculateSocketBonus(player_, proto); CalculateSocketBonus(player_, proto);
if (enable_quality_blend_) if (enable_quality_blend_)
{ // Blend with item quality and level
// Heirloom items scale with player level weight_ *= PlayerbotFactory::CalcMixedGearScore(proto->ItemLevel, proto->Quality);
// Use player level as effective item level for heirlooms - Quality EPIC
// Else - Blend with item quality and level for normal items
if (proto->Quality == ITEM_QUALITY_HEIRLOOM)
weight_ *= PlayerbotFactory::CalcMixedGearScore(lvl, ITEM_QUALITY_EPIC);
else
weight_ *= PlayerbotFactory::CalcMixedGearScore(proto->ItemLevel, proto->Quality);
return weight_;
}
// If quality/level blending is disabled, also return the calculated weight.
return weight_; return weight_;
} }

View File

@@ -82,7 +82,7 @@
#include "TameAction.h" #include "TameAction.h"
#include "TellGlyphsAction.h" #include "TellGlyphsAction.h"
#include "EquipGlyphsAction.h" #include "EquipGlyphsAction.h"
#include "PetsAction.h" #include "PetAction.h"
class ChatActionContext : public NamedObjectContext<Action> class ChatActionContext : public NamedObjectContext<Action>
{ {
@@ -307,8 +307,8 @@ private:
static Action* tame(PlayerbotAI* botAI) { return new TameAction(botAI); } static Action* tame(PlayerbotAI* botAI) { return new TameAction(botAI); }
static Action* glyphs(PlayerbotAI* botAI) { return new TellGlyphsAction(botAI); } // Added for custom Glyphs static Action* glyphs(PlayerbotAI* botAI) { return new TellGlyphsAction(botAI); } // Added for custom Glyphs
static Action* glyph_equip(PlayerbotAI* ai) { return new EquipGlyphsAction(ai); } // Added for custom Glyphs static Action* glyph_equip(PlayerbotAI* ai) { return new EquipGlyphsAction(ai); } // Added for custom Glyphs
static Action* pet(PlayerbotAI* botAI) { return new PetsAction(botAI); } static Action* pet(PlayerbotAI* botAI) { return new PetAction(botAI); }
static Action* pet_attack(PlayerbotAI* botAI) { return new PetsAction(botAI, "attack"); } static Action* pet_attack(PlayerbotAI* botAI) { return new PetAction(botAI, "attack"); }
static Action* roll_action(PlayerbotAI* botAI) { return new RollAction(botAI); } static Action* roll_action(PlayerbotAI* botAI) { return new RollAction(botAI); }
}; };

View File

@@ -199,8 +199,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
{ {
VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot); VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(bot);
Unit* vehicleBase = vehicle->GetBase(); Unit* vehicleBase = vehicle->GetBase();
// If the mover (vehicle) can fly, we DO NOT want an mmaps path (2D ground) => disable pathfinding generatePath = vehicleBase->CanFly();
generatePath = !vehicleBase || !vehicleBase->CanFly();
if (!vehicleBase || !seat || !seat->CanControl()) // is passenger and cant move anyway if (!vehicleBase || !seat || !seat->CanControl()) // is passenger and cant move anyway
return false; return false;
@@ -208,20 +207,14 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
if (distance > 0.01f) if (distance > 0.01f)
{ {
MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot
// Disable ground pathing if the bot/master/vehicle are flying
auto isFlying = [](Unit* u){ return u && (u->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) || u->IsInFlight()); };
bool allowPathVeh = generatePath;
Unit* masterVeh = botAI ? botAI->GetMaster() : nullptr;
if (isFlying(vehicleBase) || isFlying(bot) || isFlying(masterVeh))
allowPathVeh = false;
mm.Clear(); mm.Clear();
if (!backwards) if (!backwards)
{ {
mm.MovePoint(0, x, y, z, FORCED_MOVEMENT_NONE, 0.0f, 0.0f, allowPathVeh); mm.MovePoint(0, x, y, z, generatePath);
} }
else else
{ {
mm.MovePointBackwards(0, x, y, z, allowPathVeh); mm.MovePointBackwards(0, x, y, z, generatePath);
} }
float speed = backwards ? vehicleBase->GetSpeed(MOVE_RUN_BACK) : vehicleBase->GetSpeed(MOVE_RUN); float speed = backwards ? vehicleBase->GetSpeed(MOVE_RUN_BACK) : vehicleBase->GetSpeed(MOVE_RUN);
float delay = 1000.0f * (distance / speed); float delay = 1000.0f * (distance / speed);
@@ -248,22 +241,15 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// bot->CastStop(); // bot->CastStop();
// botAI->InterruptSpell(); // botAI->InterruptSpell();
// } // }
MotionMaster& mm = *bot->GetMotionMaster(); MotionMaster& mm = *bot->GetMotionMaster();
// No ground pathfinding if the bot/master are flying => allow true 3D (Z) movement
auto isFlying = [](Unit* u){ return u && (u->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) || u->IsInFlight()); };
bool allowPath = generatePath;
Unit* master = botAI ? botAI->GetMaster() : nullptr;
if (isFlying(bot) || isFlying(master))
allowPath = false;
mm.Clear(); mm.Clear();
if (!backwards) if (!backwards)
{ {
mm.MovePoint(0, x, y, z, FORCED_MOVEMENT_NONE, 0.0f, 0.0f, allowPath); mm.MovePoint(0, x, y, z, generatePath);
} }
else else
{ {
mm.MovePointBackwards(0, x, y, z, allowPath); mm.MovePointBackwards(0, x, y, z, generatePath);
} }
float delay = 1000.0f * MoveDelay(distance, backwards); float delay = 1000.0f * MoveDelay(distance, backwards);
if (lessDelay) if (lessDelay)
@@ -296,23 +282,16 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// bot->CastStop(); // bot->CastStop();
// botAI->InterruptSpell(); // botAI->InterruptSpell();
// } // }
MotionMaster& mm = *bot->GetMotionMaster(); MotionMaster& mm = *bot->GetMotionMaster();
G3D::Vector3 endP = path.back(); G3D::Vector3 endP = path.back();
// No ground pathfinding if the bot/master are flying => allow true 3D (Z) movement
auto isFlying = [](Unit* u){ return u && (u->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) || u->IsInFlight()); };
bool allowPath = generatePath;
Unit* master = botAI ? botAI->GetMaster() : nullptr;
if (isFlying(bot) || isFlying(master))
allowPath = false;
mm.Clear(); mm.Clear();
if (!backwards) if (!backwards)
{ {
mm.MovePoint(0, x, y, z, FORCED_MOVEMENT_NONE, 0.0f, 0.0f, allowPath); mm.MovePoint(0, x, y, z, generatePath);
} }
else else
{ {
mm.MovePointBackwards(0, x, y, z, allowPath); mm.MovePointBackwards(0, x, y, z, generatePath);
} }
float delay = 1000.0f * MoveDelay(distance, backwards); float delay = 1000.0f * MoveDelay(distance, backwards);
if (lessDelay) if (lessDelay)
@@ -1034,49 +1013,18 @@ void MovementAction::UpdateMovementState()
bot->GetMapWaterOrGroundLevel(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()) + 1.0f; bot->GetMapWaterOrGroundLevel(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()) + 1.0f;
// Keep bot->SendMovementFlagUpdate() withing the if statements to not intefere with bot behavior on ground/(shallow) waters // Keep bot->SendMovementFlagUpdate() withing the if statements to not intefere with bot behavior on ground/(shallow) waters
if (!bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) &&
bool hasFlightAura = bot->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || bot->HasAuraType(SPELL_AURA_FLY); bot->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !onGround)
if (hasFlightAura)
{ {
bool changed = false; bot->AddUnitMovementFlag(MOVEMENTFLAG_FLYING);
if (!bot->HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY)) bot->SendMovementFlagUpdate();
{
bot->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
changed = true;
}
if (!bot->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
{
bot->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
changed = true;
}
if (!bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING))
{
bot->AddUnitMovementFlag(MOVEMENTFLAG_FLYING);
changed = true;
}
if (changed)
bot->SendMovementFlagUpdate();
} }
else if (!hasFlightAura)
else if (bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) &&
(!bot->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || onGround))
{ {
bool changed = false; bot->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING)) bot->SendMovementFlagUpdate();
{
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
changed = true;
}
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
{
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
changed = true;
}
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
{
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
changed = true;
}
if (changed)
bot->SendMovementFlagUpdate();
} }
// See if the bot is currently slowed, rooted, or otherwise unable to move // See if the bot is currently slowed, rooted, or otherwise unable to move
@@ -1174,6 +1122,13 @@ bool MovementAction::Follow(Unit* target, float distance, float angle)
if (!target) if (!target)
return false; return false;
if (!bot->InBattleground() && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target),
sPlayerbotAIConfig->followDistance))
{
// botAI->TellError("No need to follow");
return false;
}
/* /*
if (!bot->InBattleground() if (!bot->InBattleground()
&& sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target->GetPositionX(), && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target->GetPositionX(),
@@ -1291,17 +1246,21 @@ bool MovementAction::Follow(Unit* target, float distance, float angle)
return MoveTo(target, sPlayerbotAIConfig->followDistance); return MoveTo(target, sPlayerbotAIConfig->followDistance);
} }
if (sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target),
sPlayerbotAIConfig->followDistance))
{
// botAI->TellError("No need to follow");
return false;
}
if (target->IsFriendlyTo(bot) && bot->IsMounted() && AI_VALUE(GuidVector, "all targets").empty()) if (target->IsFriendlyTo(bot) && bot->IsMounted() && AI_VALUE(GuidVector, "all targets").empty())
distance += angle; distance += angle;
// Do not cancel follow if the 2D distance is short but the Z still differs (e.g., master above). if (!bot->InBattleground() && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target),
float dz1 = fabs(bot->GetPositionZ() - target->GetPositionZ()); sPlayerbotAIConfig->followDistance))
if (!bot->InBattleground()
&& sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target), sPlayerbotAIConfig->followDistance)
&& dz1 < sPlayerbotAIConfig->contactDistance)
{ {
// botAI->TellError("No need to follow"); // botAI->TellError("No need to follow");
return false; // truly in range (2D and Z) => no need to move return false;
} }
bot->HandleEmoteCommand(0); bot->HandleEmoteCommand(0);

View File

@@ -3,7 +3,7 @@
* and/or modify it under version 3 of the License, or (at your option), any later version. * and/or modify it under version 3 of the License, or (at your option), any later version.
*/ */
#include "PetsAction.h" #include "PetAction.h"
#include "CharmInfo.h" #include "CharmInfo.h"
#include "Creature.h" #include "Creature.h"
@@ -13,7 +13,7 @@
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
#include "SharedDefines.h" #include "SharedDefines.h"
bool PetsAction::Execute(Event event) bool PetAction::Execute(Event event)
{ {
// Extract the command parameter from the event (e.g., "aggressive", "defensive", "attack", etc.) // Extract the command parameter from the event (e.g., "aggressive", "defensive", "attack", etc.)
std::string param = event.getParam(); std::string param = event.getParam();

View File

@@ -3,8 +3,8 @@
* and/or modify it under version 3 of the License, or (at your option), any later version. * and/or modify it under version 3 of the License, or (at your option), any later version.
*/ */
#ifndef _PLAYERBOT_PETSACTION_H #ifndef _PLAYERBOT_PETACTION_H
#define _PLAYERBOT_PETSACTION_H #define _PLAYERBOT_PETACTION_H
#include <string> #include <string>
@@ -14,10 +14,10 @@
class PlayerbotAI; class PlayerbotAI;
class PetsAction : public Action class PetAction : public Action
{ {
public: public:
PetsAction(PlayerbotAI* botAI, const std::string& defaultCmd = "") : Action(botAI, "pet"), defaultCmd(defaultCmd) {} PetAction(PlayerbotAI* botAI, const std::string& defaultCmd = "") : Action(botAI, "pet"), defaultCmd(defaultCmd) {}
bool Execute(Event event) override; bool Execute(Event event) override;

View File

@@ -205,18 +205,17 @@ void TalkToQuestGiverAction::RewardMultipleItem(Quest const* quest, Object* ques
} }
else else
{ {
// Try to pick the usable item. If multiple, list usable rewards. // Try to pick the usable item. If multiple list usable rewards.
bestIds = BestRewards(quest); bestIds = BestRewards(quest);
if (!bestIds.empty())
if (bestIds.size() > 1) {
AskToSelectReward(quest, out, true); AskToSelectReward(quest, out, true);
}
else if (!bestIds.empty()) else
{ {
// Pick the first item // Pick the first item
uint32 firstId = *bestIds.begin(); ItemTemplate const* item = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[*bestIds.begin()]);
ItemTemplate const* item = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[firstId]); bot->RewardQuest(quest, *bestIds.begin(), questGiver, true);
bot->RewardQuest(quest, firstId, questGiver, true);
out << "Rewarded " << ChatHelper::FormatItem(item); out << "Rewarded " << ChatHelper::FormatItem(item);
} }

View File

@@ -41,7 +41,7 @@
#include "UseMeetingStoneAction.h" #include "UseMeetingStoneAction.h"
#include "NamedObjectContext.h" #include "NamedObjectContext.h"
#include "ReleaseSpiritAction.h" #include "ReleaseSpiritAction.h"
#include "PetsAction.h" #include "PetAction.h"
class PlayerbotAI; class PlayerbotAI;
@@ -141,7 +141,7 @@ private:
static Action* tell_not_enough_reputation(PlayerbotAI* botAI) { return new TellMasterAction(botAI, "Not enough reputation"); } static Action* tell_not_enough_reputation(PlayerbotAI* botAI) { return new TellMasterAction(botAI, "Not enough reputation"); }
static Action* tell_cannot_equip(PlayerbotAI* botAI) { return new InventoryChangeFailureAction(botAI); } static Action* tell_cannot_equip(PlayerbotAI* botAI) { return new InventoryChangeFailureAction(botAI); }
static Action* self_resurrect(PlayerbotAI* botAI) { return new SelfResurrectAction(botAI); } static Action* self_resurrect(PlayerbotAI* botAI) { return new SelfResurrectAction(botAI); }
static Action* pet(PlayerbotAI* botAI) { return new PetsAction(botAI); } static Action* pet(PlayerbotAI* botAI) { return new PetAction(botAI); }
// quest // quest
static Action* quest_update_add_kill(PlayerbotAI* ai) { return new QuestUpdateAddKillAction(ai); } static Action* quest_update_add_kill(PlayerbotAI* ai) { return new QuestUpdateAddKillAction(ai); }

View File

@@ -472,6 +472,7 @@ float IccBqlMultiplier::GetValue(Action* action)
else else
return 0.0f; // Cancel all other actions when we need to handle Swarming Shadows return 0.0f; // Cancel all other actions when we need to handle Swarming Shadows
} }
return 1.0f;
if ((boss->GetExactDist2d(ICC_BQL_TANK_POSITION.GetPositionX(), ICC_BQL_TANK_POSITION.GetPositionY()) > 10.0f) && if ((boss->GetExactDist2d(ICC_BQL_TANK_POSITION.GetPositionX(), ICC_BQL_TANK_POSITION.GetPositionY()) > 10.0f) &&
botAI->IsRanged(bot) && !((boss->GetPositionZ() - bot->GetPositionZ()) > 5.0f)) botAI->IsRanged(bot) && !((boss->GetPositionZ() - bot->GetPositionZ()) > 5.0f))
@@ -480,7 +481,6 @@ float IccBqlMultiplier::GetValue(Action* action)
return 0.0f; return 0.0f;
} }
return 1.0f;
} }
//VDW //VDW

View File

@@ -41,11 +41,6 @@ class ShamanCombatStrategyFactoryInternal : public NamedObjectContext<Strategy>
public: public:
ShamanCombatStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true) ShamanCombatStrategyFactoryInternal() : NamedObjectContext<Strategy>(false, true)
{ {
creators["heal"] = &ShamanCombatStrategyFactoryInternal::resto;
creators["melee"] = &ShamanCombatStrategyFactoryInternal::enh;
creators["dps"] = &ShamanCombatStrategyFactoryInternal::enh;
creators["caster"] = &ShamanCombatStrategyFactoryInternal::ele;
//creators["offheal"] = &ShamanCombatStrategyFactoryInternal::offheal;
creators["resto"] = &ShamanCombatStrategyFactoryInternal::resto; creators["resto"] = &ShamanCombatStrategyFactoryInternal::resto;
creators["enh"] = &ShamanCombatStrategyFactoryInternal::enh; creators["enh"] = &ShamanCombatStrategyFactoryInternal::enh;
creators["ele"] = &ShamanCombatStrategyFactoryInternal::ele; creators["ele"] = &ShamanCombatStrategyFactoryInternal::ele;

View File

@@ -102,7 +102,7 @@ std::vector<CreatureData const*> BgMastersValue::Calculate()
} }
} }
return bmGuids; return std::move(bmGuids);
} }
CreatureData const* BgMasterValue::Calculate() CreatureData const* BgMasterValue::Calculate()
@@ -120,7 +120,7 @@ CreatureData const* BgMasterValue::NearestBm(bool allowDead)
std::vector<CreatureData const*> bmPairs = AI_VALUE2(std::vector<CreatureData const*>, "bg masters", qualifier); std::vector<CreatureData const*> bmPairs = AI_VALUE2(std::vector<CreatureData const*>, "bg masters", qualifier);
float rDist = 0.0f; float rDist;
CreatureData const* rbmPair = nullptr; CreatureData const* rbmPair = nullptr;
for (auto& bmPair : bmPairs) for (auto& bmPair : bmPairs)