Compare commits

..

3 Commits

Author SHA1 Message Date
bash
0952beec73 tesy 2026-02-01 22:32:43 +01:00
bash
b01a830cc8 Merge branch 'master' of https://github.com/mod-playerbots/mod-playerbots 2026-02-01 22:31:38 +01:00
bash
78f5f01207 fix 2026-02-01 22:25:17 +01:00
290 changed files with 3197 additions and 10553 deletions

View File

@@ -1,15 +1,13 @@
name: Enforce test-staging → master name: Enforce test-staging → main
on: on:
pull_request: pull_request:
branches: branches:
- master - main
- test-staging
jobs: jobs:
require-test-staging: require-test-staging:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
if: github.event.pull_request.base.ref == 'master'
steps: steps:
- name: Ensure PR source is test-staging - name: Ensure PR source is test-staging
run: | run: |

View File

@@ -2,9 +2,9 @@ name: Codestyle
on: on:
push: push:
branches: [ "master", "test-staging" ] branches: [ "master" ]
pull_request: pull_request:
branches: [ "master", "test-staging" ] branches: [ "master" ]
concurrency: concurrency:
group: "codestyle-${{ github.event.pull_request.number }}" group: "codestyle-${{ github.event.pull_request.number }}"

View File

@@ -2,9 +2,9 @@ name: ubuntu-build
on: on:
push: push:
branches: [ "master", "test-staging" ] branches: [ "master" ]
pull_request: pull_request:
branches: [ "master", "test-staging" ] branches: [ "master" ]
concurrency: concurrency:
group: "core-build-${{ github.event.pull_request.number }}" group: "core-build-${{ github.event.pull_request.number }}"

View File

@@ -1,9 +1,9 @@
name: macos-build name: macos-build
on: on:
push: push:
branches: [ "master", "test-staging" ] branches: [ "master" ]
pull_request: pull_request:
branches: [ "master", "test-staging" ] branches: [ "master" ]
concurrency: concurrency:
group: "macos-build-${{ github.event.pull_request.number }}" group: "macos-build-${{ github.event.pull_request.number }}"

View File

@@ -1,9 +1,9 @@
name: windows-build name: windows-build
on: on:
push: push:
branches: [ "master", "test-staging" ] branches: [ "master" ]
pull_request: pull_request:
branches: [ "master", "test-staging" ] branches: [ "master" ]
concurrency: concurrency:
group: "windows-build-${{ github.event.pull_request.number }}" group: "windows-build-${{ github.event.pull_request.number }}"

View File

@@ -66,35 +66,38 @@ Please answer the following:
## Complexity & Impact ## Complexity & Impact
Does this change add new decision branches? - Does this change add new decision branches?
- - [ ] No - [ ] No
- - [ ] Yes (**explain below**) - [ ] Yes (**explain below**)
Does this change increase per-bot or per-tick processing? - Does this change increase per-bot or per-tick processing?
- - [ ] No - [ ] No
- - [ ] Yes (**describe and justify impact**) - [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [ ] No
- [ ] Yes (**explain why**)
Could this logic scale poorly under load?
- - [ ] No
- - [ ] Yes (**explain why**)
--- ---
## Defaults & Configuration ## Defaults & Configuration
Does this change modify default bot behavior? - Does this change modify default bot behavior?
- - [ ] No - [ ] No
- - [ ] Yes (**explain why**) - [ ] Yes (**explain why**)
If this introduces more advanced or AI-heavy logic: If this introduces more advanced or AI-heavy logic:
- - [ ] Lightweight mode remains the default
- - [ ] More complex behavior is optional and thereby configurable - [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
--- ---
## AI Assistance ## AI Assistance
Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change? - Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change?
- - [ ] No - [ ] No
- - [ ] Yes (**explain below**) - [ ] Yes (**explain below**)
If yes, please specify: If yes, please specify:
@@ -111,10 +114,10 @@ about what they do and do not understand.
## Final Checklist ## Final Checklist
- - [ ] Stability is not compromised - [ ] Stability is not compromised
- - [ ] Performance impact is understood, tested, and acceptable - [ ] Performance impact is understood, tested, and acceptable
- - [ ] Added logic complexity is justified and explained - [ ] Added logic complexity is justified and explained
- - [ ] Documentation updated if needed - [ ] Documentation updated if needed
--- ---

View File

@@ -1,71 +0,0 @@
[English](README.md) | [Español](README_ES.md) | [中文](README_CN.md)
# 玩家机器人模块
欢迎使用AzerothCore的玩家机器人模块这是一个基于IKE3玩家机器人的正在进行中的项目。这些玩家机器人利用实际的玩家数据使您能够与您自己的替身进行交互组建队伍升级角色等等。
如果您遇到任何错误或出现崩溃请您将它们报告为GitHub问题。您宝贵的反馈将帮助我们协作改进和增强这个项目。
## 安装
请注意此模块需要对AzerothCore进行特定的自定义更改。为了确保兼容性您必须使用我fork的自定义分支来编译它可以在这里找到[mod-playerbots/azerothcore-wotlk/tree/Playerbot](https://github.com/mod-playerbots/azerothcore-wotlk/tree/Playerbot)。
要安装此模块请参考AzerothCore Wiki的详细说明[AzerothCore安装指南](https://www.azerothcore.org/wiki/installation)。
我们提供了一个简单的方法来克隆该模块:
```bash
git clone https://github.com/mod-playerbots/azerothcore-wotlk.git --branch=Playerbot
cd azerothcore-wotlk/modules
git clone https://github.com/mod-playerbots/mod-playerbots.git --branch=master
```
## 快速开始与文档
要快速开始并了解一系列命令您可以参考ike3原版playerbots的手册。该模块提供了大部分基本命令。您可以在此找到文档[IKE3 Playerbots 文档](https://ike3.github.io/mangosbot-docs/)。请注意,在我们的模块中,您需要将文档中所有的 `.bot` 替换为 `.playerbot bot`
请注意,由于项目仍在开发中,新添加的命令的文档目前尚不完善。
## 进展
该模块主要强调以下关键功能,并在这些领域实施了改进:
- **世界中的机器人(随机机器人):** 我们增强了随机机器人的行为,使它们更接近真实玩家的表现,从而创建了更真实的玩家服务器环境。
- **团队副本中的机器人:** 我们赋予机器人征服具有挑战性的团队副本内容的能力通过为各种Boss实施特定策略使团队副本更加吸引人。此外我们增强了机器人在DPS、治疗和坦克等各种角色中的能力确保它们有效地为团队的成功做出贡献。
- **战场中的机器人:** 机器人现在能够与真实玩家一起积极参与战场为这些PvP场景增添了深度和刺激。
- **与机器人的交互:** 我们改进了真实玩家和机器人之间的交互,使玩家能够在与机器人伙伴合作时完成任务并升级多个角色。
- **玩家进阶路径:** 我们设计了一个改进的玩家进阶路径,辅以机器人,为玩家提供了一种替代且引人入胜的游戏体验。
- **稳定性:** 我们的努力主要集中在增强使用Playerbots模块时AzerothCore的整体稳定性。这些改进旨在防止服务器崩溃并确保所有用户都能获得更流畅的体验。
- **配置:** 我们引入了一系列可配置的选项,以满足不同需求的玩家,从而提供更个性化的体验。
值得注意的是,随着我们继续改进项目,还有大量工作需要完成。我们欢迎每个人以不同的方式做出贡献。
## 插件
为了更好地控制机器人并简化命令的使用,您还可以使用我们的插件:[Unbot Addon](https://github.com/liyunfan1223/unbot-addon)。目前,该插件仅对简体中文客户端提供更好的支持。
## 常见问题
**机器人无法释放技能**
- 请确保必要的英文DBC文件enUS存在。
**编译错误**
- 我们支持Ubuntu、Windows和macOS。
- 我们建立了持续集成工作流。您可以在[GitHub Actions](https://github.com/mod-playerbots/mod-playerbots/actions)中查看构建状态。
- 如果最新的构建状态失败,请恢复到上一个提交。我们将尽快解决此问题。
## 致谢
该模块的代码来自[ZhengPeiRu21/mod-playerbots](https://github.com/ZhengPeiRu21/mod-playerbots)和[celguar/mangosbot-bots](https://github.com/celguar/mangosbot-bots)。我们衷心感谢@ZhengPeiRu21和@celguar对维护该模块的持续努力
我们还要向所有为playerbot开发做出贡献的个人表示诚挚的感谢。您的奉献和努力对塑造这个项目至关重要我们对您的贡献表示感谢。

View File

@@ -558,7 +558,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 SSC and Ulduar)) # "raid" (bots use cheats implemented into raid strategies (currently only for Ulduar))
# 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"
@@ -990,7 +990,7 @@ AiPlayerbot.ZoneBracket.3433 = 10,22
AiPlayerbot.ZoneBracket.3525 = 10,21 AiPlayerbot.ZoneBracket.3525 = 10,21
# Classic WoW - High-level zones: # Classic WoW - High-level zones:
# Duskwood (Zone ID: 10 Default Min,Max: 19,33) # Deadwind Pass (Zone ID: 10 Default Min,Max: 19,33)
# Wetlands (Zone ID: 11 Default Min,Max: 21,30) # Wetlands (Zone ID: 11 Default Min,Max: 21,30)
# Redridge Mountains (Zone ID: 44 Default Min,Max: 16,28) # Redridge Mountains (Zone ID: 44 Default Min,Max: 16,28)
# Hillsbrad Foothills (Zone ID: 267 Default Min,Max: 20,34) # Hillsbrad Foothills (Zone ID: 267 Default Min,Max: 20,34)

View File

@@ -1,101 +0,0 @@
-- #########################################################
-- Playerbots - Add PVP / Arena texts for TellPvpAction
-- Localized for all WotLK locales (koKR, frFR, deDE, zhCN,
-- zhTW, esES, esMX, ruRU)
-- #########################################################
-- ---------------------------------------------------------
-- pvp_currency
-- [PVP] Arena points: %arena_points | Honor Points: %honor_points
-- ---------------------------------------------------------
INSERT INTO `ai_playerbot_texts`
(`name`, `text`, `say_type`, `reply_type`,
`text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`,
`text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`)
SELECT
'pvp_currency',
'[PVP] Arena points: %arena_points | Honor Points: %honor_points',
0, 0,
-- koKR
'[PVP] 투기장 점수: %arena_points | 명예 점수: %honor_points',
-- frFR
'[PVP] Points d''arène : %arena_points | Points d''honneur : %honor_points',
-- deDE
'[PVP] Arenapunkte: %arena_points | Ehrenpunkte: %honor_points',
-- zhCN
'[PVP] 竞技场点数:%arena_points | 荣誉点数:%honor_points',
-- zhTW
'[PVP] 競技場點數:%arena_points | 榮譽點數:%honor_points',
-- esES
'[PVP] Puntos de arena: %arena_points | Puntos de honor: %honor_points',
-- esMX
'[PVP] Puntos de arena: %arena_points | Puntos de honor: %honor_points',
-- ruRU
'[PVP] Очки арены: %arena_points | Очки чести: %honor_points'
WHERE NOT EXISTS (
SELECT 1 FROM `ai_playerbot_texts` WHERE `name` = 'pvp_currency'
);
-- ---------------------------------------------------------
-- pvp_arena_team
-- [PVP] %bracket: <%team_name> (rating %team_rating)
-- ---------------------------------------------------------
INSERT INTO `ai_playerbot_texts`
(`name`, `text`, `say_type`, `reply_type`,
`text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`,
`text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`)
SELECT
'pvp_arena_team',
'[PVP] %bracket: <%team_name> (rating %team_rating)',
0, 0,
-- koKR
'[PVP] %bracket: <%team_name> (평점 %team_rating)',
-- frFR
'[PVP] %bracket : <%team_name> (cote %team_rating)',
-- deDE
'[PVP] %bracket: <%team_name> (Wertung %team_rating)',
-- zhCN
'[PVP] %bracket: <%team_name> (评分 %team_rating)',
-- zhTW
'[PVP] %bracket: <%team_name> (評分 %team_rating)',
-- esES
'[PVP] %bracket: <%team_name> (índice %team_rating)',
-- esMX
'[PVP] %bracket: <%team_name> (índice %team_rating)',
-- ruRU
'[PVP] %bracket: <%team_name> (рейтинг %team_rating)'
WHERE NOT EXISTS (
SELECT 1 FROM `ai_playerbot_texts` WHERE `name` = 'pvp_arena_team'
);
-- ---------------------------------------------------------
-- pvp_no_arena_team
-- [PVP] I have no Arena Team.
-- ---------------------------------------------------------
INSERT INTO `ai_playerbot_texts`
(`name`, `text`, `say_type`, `reply_type`,
`text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`,
`text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`)
SELECT
'pvp_no_arena_team',
'[PVP] I have no Arena Team.',
0, 0,
-- koKR
'[PVP] 투기장 팀이 없습니다.',
-- frFR
'[PVP] Je n''ai aucune équipe d''arène.',
-- deDE
'[PVP] Ich habe kein Arenateam.',
-- zhCN
'[PVP] 我没有竞技场战队。',
-- zhTW
'[PVP] 我沒有競技場隊伍。',
-- esES
'[PVP] No tengo equipo de arena.',
-- esMX
'[PVP] No tengo equipo de arena.',
-- ruRU
'[PVP] У меня нет команды арены.'
WHERE NOT EXISTS (
SELECT 1 FROM `ai_playerbot_texts` WHERE `name` = 'pvp_no_arena_team'
);

View File

@@ -6,9 +6,9 @@
#include "AcceptBattlegroundInvitationAction.h" #include "AcceptBattlegroundInvitationAction.h"
#include "Event.h" #include "Event.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
bool AcceptBgInvitationAction::Execute(Event /*event*/) bool AcceptBgInvitationAction::Execute(Event event)
{ {
uint8 type = 0; // arenatype if arena uint8 type = 0; // arenatype if arena
uint8 unk2 = 0; // unk, can be 0x0 (may be if was invited?) and 0x1 uint8 unk2 = 0; // unk, can be 0x0 (may be if was invited?) and 0x1
@@ -18,9 +18,9 @@ bool AcceptBgInvitationAction::Execute(Event /*event*/)
WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20); WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20);
packet << type << unk2 << (uint32)bgTypeId_ << unk << action; packet << type << unk2 << (uint32)bgTypeId_ << unk << action;
// packet << bgTypeId_ << action;
bot->GetSession()->HandleBattleFieldPortOpcode(packet); bot->GetSession()->HandleBattleFieldPortOpcode(packet);
botAI->ResetStrategies(); botAI->ResetStrategies();
return true; return true;
} }

View File

@@ -22,7 +22,7 @@ bool AddLootAction::Execute(Event event)
return AI_VALUE(LootObjectStack*, "available loot")->Add(guid); return AI_VALUE(LootObjectStack*, "available loot")->Add(guid);
} }
bool AddAllLootAction::Execute(Event /*event*/) bool AddAllLootAction::Execute(Event event)
{ {
bool added = false; bool added = false;

View File

@@ -58,7 +58,7 @@ bool ReachAreaTriggerAction::Execute(Event event)
return true; return true;
} }
bool AreaTriggerAction::Execute(Event /*event*/) bool AreaTriggerAction::Execute(Event event)
{ {
LastMovement& movement = context->GetValue<LastMovement&>("last area trigger")->Get(); LastMovement& movement = context->GetValue<LastMovement&>("last area trigger")->Get();

View File

@@ -1,20 +1,19 @@
#include "AutoMaintenanceOnLevelupAction.h" #include "AutoMaintenanceOnLevelupAction.h"
#include "SpellMgr.h" #include "GuildMgr.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "Playerbots.h"
#include "RandomPlayerbotMgr.h" #include "RandomPlayerbotMgr.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "BroadcastHelper.h" #include "BroadcastHelper.h"
bool AutoMaintenanceOnLevelupAction::Execute(Event /*event*/) bool AutoMaintenanceOnLevelupAction::Execute(Event event)
{ {
AutoPickTalents(); AutoPickTalents();
AutoLearnSpell(); AutoLearnSpell();
AutoUpgradeEquip(); AutoUpgradeEquip();
AutoTeleportForLevel(); AutoTeleportForLevel();
return true; return true;
} }

View File

@@ -13,8 +13,9 @@
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "PositionValue.h" #include "PositionValue.h"
#include "UpdateTime.h"
bool BGJoinAction::Execute(Event /*event*/) bool BGJoinAction::Execute(Event event)
{ {
uint32 queueType = AI_VALUE(uint32, "bg type"); uint32 queueType = AI_VALUE(uint32, "bg type");
if (!queueType) // force join to fill bg if (!queueType) // force join to fill bg
@@ -652,7 +653,7 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg
return false; return false;
} }
bool BGLeaveAction::Execute(Event /*event*/) bool BGLeaveAction::Execute(Event event)
{ {
if (!(bot->InBattlegroundQueue() || bot->InBattleground())) if (!(bot->InBattlegroundQueue() || bot->InBattleground()))
return false; return false;
@@ -1063,7 +1064,7 @@ bool BGStatusAction::Execute(Event event)
return true; return true;
} }
bool BGStatusCheckAction::Execute(Event /*event*/) bool BGStatusCheckAction::Execute(Event event)
{ {
if (bot->IsBeingTeleported()) if (bot->IsBeingTeleported())
return false; return false;
@@ -1079,7 +1080,7 @@ bool BGStatusCheckAction::Execute(Event /*event*/)
bool BGStatusCheckAction::isUseful() { return bot->InBattlegroundQueue(); } bool BGStatusCheckAction::isUseful() { return bot->InBattlegroundQueue(); }
bool BGStrategyCheckAction::Execute(Event /*event*/) bool BGStrategyCheckAction::Execute(Event event)
{ {
bool inside_bg = bot->InBattleground() && bot->GetBattleground(); bool inside_bg = bot->InBattleground() && bot->GetBattleground();
; ;

View File

@@ -1557,7 +1557,7 @@ bool BGTactics::eyJumpDown()
// //
// actual bg tactics below // actual bg tactics below
// //
bool BGTactics::Execute(Event /*event*/) bool BGTactics::Execute(Event event)
{ {
Battleground* bg = bot->GetBattleground(); Battleground* bg = bot->GetBattleground();
if (!bg) if (!bg)
@@ -4249,7 +4249,7 @@ bool BGTactics::IsLockedInsideKeep()
return false; return false;
} }
bool ArenaTactics::Execute(Event /*event*/) bool ArenaTactics::Execute(Event event)
{ {
if (!bot->InBattleground()) if (!bot->InBattleground())
{ {

View File

@@ -18,7 +18,7 @@ bool BossFireResistanceAction::isUseful()
return bossFireResistanceTrigger.IsActive(); return bossFireResistanceTrigger.IsActive();
} }
bool BossFireResistanceAction::Execute(Event /*event*/) bool BossFireResistanceAction::Execute(Event event)
{ {
PaladinFireResistanceStrategy paladinFireResistanceStrategy(botAI); PaladinFireResistanceStrategy paladinFireResistanceStrategy(botAI);
botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinFireResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinFireResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT);
@@ -32,7 +32,7 @@ bool BossFrostResistanceAction::isUseful()
return bossFrostResistanceTrigger.IsActive(); return bossFrostResistanceTrigger.IsActive();
} }
bool BossFrostResistanceAction::Execute(Event /*event*/) bool BossFrostResistanceAction::Execute(Event event)
{ {
PaladinFrostResistanceStrategy paladinFrostResistanceStrategy(botAI); PaladinFrostResistanceStrategy paladinFrostResistanceStrategy(botAI);
botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinFrostResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinFrostResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT);
@@ -46,7 +46,7 @@ bool BossNatureResistanceAction::isUseful()
return bossNatureResistanceTrigger.IsActive(); return bossNatureResistanceTrigger.IsActive();
} }
bool BossNatureResistanceAction::Execute(Event /*event*/) bool BossNatureResistanceAction::Execute(Event event)
{ {
HunterNatureResistanceStrategy hunterNatureResistanceStrategy(botAI); HunterNatureResistanceStrategy hunterNatureResistanceStrategy(botAI);
botAI->ChangeStrategy(ADD_STRATEGY_CHAR + hunterNatureResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + hunterNatureResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT);
@@ -60,7 +60,7 @@ bool BossShadowResistanceAction::isUseful()
return bossShadowResistanceTrigger.IsActive(); return bossShadowResistanceTrigger.IsActive();
} }
bool BossShadowResistanceAction::Execute(Event /*event*/) bool BossShadowResistanceAction::Execute(Event event)
{ {
PaladinShadowResistanceStrategy paladinShadowResistanceStrategy(botAI); PaladinShadowResistanceStrategy paladinShadowResistanceStrategy(botAI);
botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinShadowResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinShadowResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT);

View File

@@ -175,7 +175,7 @@ bool BuyAction::Execute(Event event)
if (needMoneyFor == NeedMoneyFor::gear) if (needMoneyFor == NeedMoneyFor::gear)
{ {
botAI->DoSpecificAction("equip upgrades packet action"); botAI->DoSpecificAction("equip upgrades");
} }
} }
} }
@@ -206,7 +206,7 @@ bool BuyAction::Execute(Event event)
if (usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_EQUIP || if (usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_EQUIP ||
usage == ITEM_USAGE_BAD_EQUIP || usage == ITEM_USAGE_BROKEN_EQUIP) usage == ITEM_USAGE_BAD_EQUIP || usage == ITEM_USAGE_BROKEN_EQUIP)
{ {
botAI->DoSpecificAction("equip upgrades packet action"); botAI->DoSpecificAction("equip upgrades");
break; break;
} }
} }

View File

@@ -7,14 +7,12 @@
#include "Player.h" #include "Player.h"
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
bool CancelChannelAction::Execute(Event /*event*/) bool CancelChannelAction::Execute(Event event)
{ {
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
{ {
bot->InterruptSpell(CURRENT_CHANNELED_SPELL); bot->InterruptSpell(CURRENT_CHANNELED_SPELL);
return true; return true;
} }
return false; return false;
} }

View File

@@ -334,7 +334,7 @@ bool CastRandomSpellAction::castSpell(uint32 spellId, WorldObject* wo)
return botAI->CastSpell(spellId, wo->GetPositionX(), wo->GetPositionY(), wo->GetPositionZ()); return botAI->CastSpell(spellId, wo->GetPositionX(), wo->GetPositionY(), wo->GetPositionZ());
} }
bool DisEnchantRandomItemAction::Execute(Event /*event*/) bool DisEnchantRandomItemAction::Execute(Event event)
{ {
std::vector<Item*> items = std::vector<Item*> items =
AI_VALUE2(std::vector<Item*>, "inventory items", "usage " + std::to_string(ITEM_USAGE_DISENCHANT)); AI_VALUE2(std::vector<Item*>, "inventory items", "usage " + std::to_string(ITEM_USAGE_DISENCHANT));

View File

@@ -10,9 +10,9 @@
#include "Event.h" #include "Event.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "Playerbots.h"
#include "AiObjectContext.h" #include "AiObjectContext.h"
#include "Log.h" #include "Log.h"
#include "RandomPlayerbotMgr.h"
bool ChangeTalentsAction::Execute(Event event) bool ChangeTalentsAction::Execute(Event event)
{ {
@@ -184,7 +184,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
// // } // // }
// // } // // }
// return ret; // return std::move(ret);
// } // }
// std::vector<TalentPath*> ChangeTalentsAction::getPremadePaths(TalentSpec* oldSpec) // std::vector<TalentPath*> ChangeTalentsAction::getPremadePaths(TalentSpec* oldSpec)
@@ -201,7 +201,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
// // } // // }
// // } // // }
// return ret; // return std::move(ret);
// } // }
// TalentPath* ChangeTalentsAction::getPremadePath(uint32 id) // TalentPath* ChangeTalentsAction::getPremadePath(uint32 id)
@@ -368,11 +368,11 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
// return nullptr; // return nullptr;
// } // }
bool AutoSetTalentsAction::Execute(Event /*event*/) bool AutoSetTalentsAction::Execute(Event event)
{ {
std::ostringstream out; std::ostringstream out;
if (!PlayerbotAIConfig::instance().autoPickTalents || !RandomPlayerbotMgr::instance().IsRandomBot(bot)) if (!sPlayerbotAIConfig.autoPickTalents || !sRandomPlayerbotMgr.IsRandomBot(bot))
return false; return false;
if (bot->GetFreeTalentPoints() <= 0) if (bot->GetFreeTalentPoints() <= 0)

View File

@@ -42,7 +42,7 @@ void PositionsResetAction::SetStayPosition(float x, float y, float z)
posMap["stay"] = pos; posMap["stay"] = pos;
} }
bool FollowChatShortcutAction::Execute(Event /*event*/) bool FollowChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
@@ -116,7 +116,7 @@ bool FollowChatShortcutAction::Execute(Event /*event*/)
return true; return true;
} }
bool StayChatShortcutAction::Execute(Event /*event*/) bool StayChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
@@ -133,7 +133,7 @@ bool StayChatShortcutAction::Execute(Event /*event*/)
return true; return true;
} }
bool MoveFromGroupChatShortcutAction::Execute(Event /*event*/) bool MoveFromGroupChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
@@ -148,7 +148,7 @@ bool MoveFromGroupChatShortcutAction::Execute(Event /*event*/)
return true; return true;
} }
bool FleeChatShortcutAction::Execute(Event /*event*/) bool FleeChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
@@ -171,7 +171,7 @@ bool FleeChatShortcutAction::Execute(Event /*event*/)
return true; return true;
} }
bool GoawayChatShortcutAction::Execute(Event /*event*/) bool GoawayChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
@@ -188,7 +188,7 @@ bool GoawayChatShortcutAction::Execute(Event /*event*/)
return true; return true;
} }
bool GrindChatShortcutAction::Execute(Event /*event*/) bool GrindChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
@@ -204,7 +204,7 @@ bool GrindChatShortcutAction::Execute(Event /*event*/)
return true; return true;
} }
bool TankAttackChatShortcutAction::Execute(Event /*event*/) bool TankAttackChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
@@ -224,7 +224,7 @@ bool TankAttackChatShortcutAction::Execute(Event /*event*/)
return true; return true;
} }
bool MaxDpsChatShortcutAction::Execute(Event /*event*/) bool MaxDpsChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
@@ -241,7 +241,7 @@ bool MaxDpsChatShortcutAction::Execute(Event /*event*/)
return true; return true;
} }
bool BwlChatShortcutAction::Execute(Event /*event*/) bool BwlChatShortcutAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)

View File

@@ -7,10 +7,9 @@
#include "Event.h" #include "Event.h"
#include "GuildTaskMgr.h" #include "GuildTaskMgr.h"
#include "PlayerbotAIConfig.h" #include "Playerbots.h"
#include "PlayerbotAI.h"
bool CheckMailAction::Execute(Event /*event*/) bool CheckMailAction::Execute(Event event)
{ {
WorldPacket p; WorldPacket p;
bot->GetSession()->HandleQueryNextMailTime(p); bot->GetSession()->HandleQueryNextMailTime(p);
@@ -29,7 +28,7 @@ bool CheckMailAction::Execute(Event /*event*/)
continue; continue;
uint32 account = owner->GetSession()->GetAccountId(); uint32 account = owner->GetSession()->GetAccountId();
if (PlayerbotAIConfig::instance().IsInRandomAccountList(account)) if (sPlayerbotAIConfig.IsInRandomAccountList(account))
continue; continue;
ProcessMail(mail, owner, trans); ProcessMail(mail, owner, trans);

View File

@@ -55,6 +55,63 @@ MountData CollectMountData(const Player* bot)
return data; return data;
} }
bool CheckMountStateAction::isUseful()
{
// Not useful when:
if (botAI->IsInVehicle() || bot->isDead() || bot->HasUnitState(UNIT_STATE_IN_FLIGHT) ||
!bot->IsOutdoors() || bot->InArena())
return false;
master = GetMaster();
// Get shapeshift states, only applicable when there's a master
if (master)
{
botInShapeshiftForm = bot->GetShapeshiftForm();
masterInShapeshiftForm = master->GetShapeshiftForm();
}
// Not useful when in combat and not currently mounted / travel formed
if ((bot->IsInCombat() || botAI->GetState() == BOT_STATE_COMBAT) &&
!bot->IsMounted() && botInShapeshiftForm != FORM_TRAVEL && botInShapeshiftForm != FORM_FLIGHT && botInShapeshiftForm != FORM_FLIGHT_EPIC)
return false;
// In addition to checking IsOutdoors, also check whether bot is clipping below floor slightly because that will
// cause bot to falsly indicate they are outdoors. This fixes bug where bot tries to mount indoors (which seems
// to mostly be an issue in tunnels of WSG and AV)
float posZ = bot->GetPositionZ();
float groundLevel = bot->GetMapWaterOrGroundLevel(bot->GetPositionX(), bot->GetPositionY(), posZ);
if (!bot->IsMounted() && !bot->HasWaterWalkAura() && posZ < groundLevel)
return false;
// Not useful when bot does not have mount strat and is not currently mounted
if (!GET_PLAYERBOT_AI(bot)->HasStrategy("mount", BOT_STATE_NON_COMBAT) && !bot->IsMounted())
return false;
// Not useful when level lower than minimum required
if (bot->GetLevel() < sPlayerbotAIConfig.useGroundMountAtMinLevel)
return false;
// Allow mounting while transformed only if the form allows it
if (bot->HasAuraType(SPELL_AURA_TRANSFORM) && bot->IsInDisallowedMountForm())
return false;
// BG Logic
if (bot->InBattleground())
{
// Do not use when carrying BG Flags
if (bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))
return false;
// Only mount if BG starts in less than 30 sec
if (Battleground* bg = bot->GetBattleground())
if (bg->GetStatus() == STATUS_WAIT_JOIN && bg->GetStartDelayTime() > BG_START_DELAY_30S)
return false;
}
return true;
}
bool CheckMountStateAction::Execute(Event /*event*/) bool CheckMountStateAction::Execute(Event /*event*/)
{ {
// Determine if there are no attackers // Determine if there are no attackers
@@ -125,63 +182,6 @@ bool CheckMountStateAction::Execute(Event /*event*/)
return false; return false;
} }
bool CheckMountStateAction::isUseful()
{
// Not useful when:
if (botAI->IsInVehicle() || bot->isDead() || bot->HasUnitState(UNIT_STATE_IN_FLIGHT) ||
!bot->IsOutdoors() || bot->InArena())
return false;
master = GetMaster();
// Get shapeshift states, only applicable when there's a master
if (master)
{
botInShapeshiftForm = bot->GetShapeshiftForm();
masterInShapeshiftForm = master->GetShapeshiftForm();
}
// Not useful when in combat and not currently mounted / travel formed
if ((bot->IsInCombat() || botAI->GetState() == BOT_STATE_COMBAT) &&
!bot->IsMounted() && botInShapeshiftForm != FORM_TRAVEL && botInShapeshiftForm != FORM_FLIGHT && botInShapeshiftForm != FORM_FLIGHT_EPIC)
return false;
// In addition to checking IsOutdoors, also check whether bot is clipping below floor slightly because that will
// cause bot to falsly indicate they are outdoors. This fixes bug where bot tries to mount indoors (which seems
// to mostly be an issue in tunnels of WSG and AV)
float posZ = bot->GetPositionZ();
float groundLevel = bot->GetMapWaterOrGroundLevel(bot->GetPositionX(), bot->GetPositionY(), posZ);
if (!bot->IsMounted() && !bot->HasWaterWalkAura() && posZ < groundLevel)
return false;
// Not useful when bot does not have mount strat and is not currently mounted
if (!GET_PLAYERBOT_AI(bot)->HasStrategy("mount", BOT_STATE_NON_COMBAT) && !bot->IsMounted())
return false;
// Not useful when level lower than minimum required
if (bot->GetLevel() < sPlayerbotAIConfig.useGroundMountAtMinLevel)
return false;
// Allow mounting while transformed only if the form allows it
if (bot->HasAuraType(SPELL_AURA_TRANSFORM) && bot->IsInDisallowedMountForm())
return false;
// BG Logic
if (bot->InBattleground())
{
// Do not use when carrying BG Flags
if (bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) || bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL))
return false;
// Only mount if BG starts in less than 30 sec
if (Battleground* bg = bot->GetBattleground())
if (bg->GetStatus() == STATUS_WAIT_JOIN && bg->GetStartDelayTime() > BG_START_DELAY_30S)
return false;
}
return true;
}
bool CheckMountStateAction::Mount() bool CheckMountStateAction::Mount()
{ {
// Remove current Shapeshift if need be // Remove current Shapeshift if need be

View File

@@ -6,15 +6,12 @@
#include "CheckValuesAction.h" #include "CheckValuesAction.h"
#include "Event.h" #include "Event.h"
#include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
#include "PlayerbotAI.h"
#include "TravelNode.h"
#include "AiObjectContext.h"
CheckValuesAction::CheckValuesAction(PlayerbotAI* botAI) : Action(botAI, "check values") {} CheckValuesAction::CheckValuesAction(PlayerbotAI* botAI) : Action(botAI, "check values") {}
bool CheckValuesAction::Execute(Event /*event*/) bool CheckValuesAction::Execute(Event event)
{ {
if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT)) if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT))
{ {

View File

@@ -6,6 +6,7 @@
#include <random> #include <random>
#include "ChooseRpgTargetAction.h" #include "ChooseRpgTargetAction.h"
#include "BattlegroundMgr.h"
#include "BudgetValues.h" #include "BudgetValues.h"
#include "ChatHelper.h" #include "ChatHelper.h"
#include "Event.h" #include "Event.h"
@@ -13,6 +14,7 @@
#include "GuildCreateActions.h" #include "GuildCreateActions.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "RpgSubActions.h" #include "RpgSubActions.h"
#include "Util.h"
#include "ServerFacade.h" #include "ServerFacade.h"
#include "PossibleRpgTargetsValue.h" #include "PossibleRpgTargetsValue.h"
@@ -110,7 +112,7 @@ float ChooseRpgTargetAction::getMaxRelevance(GuidPosition guidP)
return floor((maxRelevance - 1.0) * 1000.0f); return floor((maxRelevance - 1.0) * 1000.0f);
} }
bool ChooseRpgTargetAction::Execute(Event /*event*/) bool ChooseRpgTargetAction::Execute(Event event)
{ {
//TravelTarget* travelTarget = AI_VALUE(TravelTarget*, "travel target"); //not used, line marked for removal. //TravelTarget* travelTarget = AI_VALUE(TravelTarget*, "travel target"); //not used, line marked for removal.
Player* master = botAI->GetMaster(); Player* master = botAI->GetMaster();
@@ -318,7 +320,7 @@ bool ChooseRpgTargetAction::isFollowValid(Player* bot, WorldPosition pos)
inDungeon = true; inDungeon = true;
if (realMaster && realMaster->IsInWorld() && realMaster->GetMap()->IsDungeon() && if (realMaster && realMaster->IsInWorld() && realMaster->GetMap()->IsDungeon() &&
(realMaster->GetMapId() != pos.GetMapId())) (realMaster->GetMapId() != pos.getMapId()))
return false; return false;
} }
@@ -332,7 +334,7 @@ bool ChooseRpgTargetAction::isFollowValid(Player* bot, WorldPosition pos)
return false; return false;
Formation* formation = AI_VALUE(Formation*, "formation"); Formation* formation = AI_VALUE(Formation*, "formation");
float distance = groupLeader->GetDistance2d(pos.GetPositionX(), pos.GetPositionY()); float distance = groupLeader->GetDistance2d(pos.getX(), pos.getY());
if (!botAI->HasActivePlayerMaster() && distance < 50.0f) if (!botAI->HasActivePlayerMaster() && distance < 50.0f)
{ {

View File

@@ -30,7 +30,38 @@ bool AttackEnemyFlagCarrierAction::isUseful()
PlayerHasFlag::IsCapturingFlag(bot); PlayerHasFlag::IsCapturingFlag(bot);
} }
bool DropTargetAction::Execute(Event /*event*/) bool AttackAnythingAction::isUseful()
{
if (!bot || !botAI) // Prevents invalid accesses
return false;
if (!botAI->AllowActivity(GRIND_ACTIVITY)) // Bot cannot be active
return false;
if (botAI->HasStrategy("stay", BOT_STATE_NON_COMBAT))
return false;
if (bot->IsInCombat())
return false;
Unit* target = GetTarget();
if (!target || !target->IsInWorld()) // Checks if the target is valid and in the world
return false;
std::string const name = std::string(target->GetName());
if (!name.empty() &&
(name.find("Dummy") != std::string::npos ||
name.find("Charge Target") != std::string::npos ||
name.find("Melee Target") != std::string::npos ||
name.find("Ranged Target") != std::string::npos))
{
return false;
}
return true;
}
bool DropTargetAction::Execute(Event event)
{ {
Unit* target = context->GetValue<Unit*>("current target")->Get(); Unit* target = context->GetValue<Unit*>("current target")->Get();
if (target && target->isDead()) if (target && target->isDead())
@@ -96,38 +127,7 @@ bool AttackAnythingAction::Execute(Event event)
return result; return result;
} }
bool AttackAnythingAction::isUseful() bool AttackAnythingAction::isPossible() { return AttackAction::isPossible() && GetTarget(); }
{
if (!bot || !botAI) // Prevents invalid accesses
return false;
if (!botAI->AllowActivity(GRIND_ACTIVITY)) // Bot cannot be active
return false;
if (botAI->HasStrategy("stay", BOT_STATE_NON_COMBAT))
return false;
if (bot->IsInCombat())
return false;
Unit* target = GetTarget();
if (!target || !target->IsInWorld()) // Checks if the target is valid and in the world
return false;
std::string const name = std::string(target->GetName());
if (!name.empty() &&
(name.find("Dummy") != std::string::npos ||
name.find("Charge Target") != std::string::npos ||
name.find("Melee Target") != std::string::npos ||
name.find("Ranged Target") != std::string::npos))
{
return false;
}
return true;
}
bool AttackAnythingAction::isPossible() { return GetTarget() && AttackAction::isPossible(); }
bool DpsAssistAction::isUseful() bool DpsAssistAction::isUseful()
{ {
@@ -137,7 +137,7 @@ bool DpsAssistAction::isUseful()
return true; return true;
} }
bool AttackRtiTargetAction::Execute(Event /*event*/) bool AttackRtiTargetAction::Execute(Event event)
{ {
Unit* rtiTarget = AI_VALUE(Unit*, "rti target"); Unit* rtiTarget = AI_VALUE(Unit*, "rti target");

View File

@@ -9,7 +9,7 @@
#include "LootObjectStack.h" #include "LootObjectStack.h"
#include "Playerbots.h" #include "Playerbots.h"
bool ChooseTravelTargetAction::Execute(Event /*event*/) bool ChooseTravelTargetAction::Execute(Event event)
{ {
// Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); //not used, line marked for removal. // Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); //not used, line marked for removal.

View File

@@ -7,11 +7,7 @@
#include "ChooseTravelTargetAction.h" #include "ChooseTravelTargetAction.h"
#include "MapMgr.h" #include "MapMgr.h"
#include "TravelMgr.h" #include "Playerbots.h"
#include "Player.h"
#include "PlayerbotAI.h"
#include "SpellMgr.h"
#include "Spell.h"
bool DebugAction::Execute(Event event) bool DebugAction::Execute(Event event)
{ {
@@ -32,8 +28,8 @@ bool DebugAction::Execute(Event event)
uint32 areaId = 0; uint32 areaId = 0;
uint32 zoneId = 0; uint32 zoneId = 0;
sMapMgr->GetZoneAndAreaId(PHASEMASK_NORMAL, zoneId, areaId, pos.GetMapId(), pos.GetPositionX(), pos.GetPositionY(), sMapMgr->GetZoneAndAreaId(PHASEMASK_NORMAL, zoneId, areaId, pos.getMapId(), pos.getX(), pos.getY(),
pos.GetPositionZ()); pos.getZ());
std::ostringstream out; std::ostringstream out;
out << zoneId << "," << areaId << "," << (pos.getAreaName().empty() ? "none" : pos.getAreaName()) << ","; out << zoneId << "," << areaId << "," << (pos.getAreaName().empty() ? "none" : pos.getAreaName()) << ",";
@@ -302,7 +298,7 @@ bool DebugAction::Execute(Event event)
for (auto p : ppath) for (auto p : ppath)
{ {
Creature* wpCreature = Creature* wpCreature =
bot->SummonCreature(1, p.GetPositionX(), p.GetPositionY(), p.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 20000.0f); bot->SummonCreature(1, p.getX(), p.getY(), p.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 20000.0f);
// addAura(246, wpCreature); // addAura(246, wpCreature);
units.push_back(wpCreature->GetGUID()); units.push_back(wpCreature->GetGUID());
@@ -329,11 +325,11 @@ bool DebugAction::Execute(Event event)
WorldPosition botPos(bot); WorldPosition botPos(bot);
WorldPosition botPos1 = botPos; WorldPosition botPos1 = botPos;
botPos.setX(botPos.GetPositionX() + cos(ang) * dist); botPos.setX(botPos.getX() + cos(ang) * dist);
botPos.setY(botPos.GetPositionY() + sin(ang) * dist); botPos.setY(botPos.getY() + sin(ang) * dist);
botPos.setZ(botPos.getHeight() + 2); botPos.setZ(botPos.getHeight() + 2);
Creature* wpCreature = bot->SummonCreature(2334, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f); TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
FakeSpell(spellEffect, wpCreature, wpCreature, prev->GetGUID(), {}, {}, botPos, botPos); FakeSpell(spellEffect, wpCreature, wpCreature, prev->GetGUID(), {}, {}, botPos, botPos);
@@ -356,11 +352,11 @@ bool DebugAction::Execute(Event event)
WorldPosition botPos(bot); WorldPosition botPos(bot);
WorldPosition botPos1 = botPos; WorldPosition botPos1 = botPos;
botPos.setX(botPos.GetPositionX() + cos(ang) * dist); botPos.setX(botPos.getX() + cos(ang) * dist);
botPos.setY(botPos.GetPositionY() + sin(ang) * dist); botPos.setY(botPos.getY() + sin(ang) * dist);
botPos.setZ(botPos.getHeight() + 2); botPos.setZ(botPos.getHeight() + 2);
Creature* wpCreature = bot->SummonCreature(2334, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f); TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature) if (wpCreature)
@@ -387,11 +383,11 @@ bool DebugAction::Execute(Event event)
WorldPosition botPos(bot); WorldPosition botPos(bot);
WorldPosition botPos1 = botPos; WorldPosition botPos1 = botPos;
botPos.setX(botPos.GetPositionX() + cos(ang) * dist); botPos.setX(botPos.getX() + cos(ang) * dist);
botPos.setY(botPos.GetPositionY() + sin(ang) * dist); botPos.setY(botPos.getY() + sin(ang) * dist);
botPos.setZ(botPos.getHeight() + 2); botPos.setZ(botPos.getHeight() + 2);
Creature* wpCreature = bot->SummonCreature(2334, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 5000.0f + i * 100.0f); TEMPSUMMON_TIMED_DESPAWN, 5000.0f + i * 100.0f);
wpCreature->SetObjectScale(0.5f); wpCreature->SetObjectScale(0.5f);
@@ -415,11 +411,11 @@ bool DebugAction::Execute(Event event)
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + cos(ang) * dist); botPos.setX(botPos.getX() + cos(ang) * dist);
botPos.setY(botPos.GetPositionY() + sin(ang) * dist); botPos.setY(botPos.getY() + sin(ang) * dist);
botPos.setZ(botPos.getHeight() + 2); botPos.setZ(botPos.getHeight() + 2);
Creature* wpCreature = bot->SummonCreature(2334, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f); TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
units.push_back(wpCreature->GetGUID()); units.push_back(wpCreature->GetGUID());
@@ -484,13 +480,13 @@ bool DebugAction::Execute(Event event)
uint32 effect = dx + dy * 10 + spellEffect * 100; uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
Creature* wpCreature = Creature* wpCreature =
bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.GetPositionX(), botPos.GetPositionY(), bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.getX(), botPos.getY(),
botPos.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f); botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature) if (wpCreature)
{ {
@@ -516,11 +512,11 @@ bool DebugAction::Execute(Event event)
uint32 effect = dx + dy * 10 + spellEffect * 100; uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
Creature* wpCreature = bot->SummonCreature(effect, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, Creature* wpCreature = bot->SummonCreature(effect, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f); TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
} }
} }
@@ -536,8 +532,8 @@ bool DebugAction::Execute(Event event)
uint32 effect = dx + dy * 10 + spellEffect * 100; uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
FakeSpell(effect, bot, nullptr, ObjectGuid::Empty, {}, {}, botPos, botPos, true); FakeSpell(effect, bot, nullptr, ObjectGuid::Empty, {}, {}, botPos, botPos, true);
@@ -556,11 +552,11 @@ bool DebugAction::Execute(Event event)
uint32 effect = dx + dy * 10 + spellEffect * 100; uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
Creature* wpCreature = bot->SummonCreature(2334, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f); TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature) if (wpCreature)
@@ -572,7 +568,7 @@ bool DebugAction::Execute(Event event)
// wpCreature->SendMessageToSet(&data, true); // wpCreature->SendMessageToSet(&data, true);
datMap.push_back(data); datMap.push_back(data);
// wpCreature->MonsterMoveWithSpeed(botPos.GetPositionX(), botPos.GetPositionY() + 80, botPos.GetPositionZ(), 8.0f, true, // wpCreature->MonsterMoveWithSpeed(botPos.getX(), botPos.getY() + 80, botPos.getZ(), 8.0f, true,
// true); // true);
} }
} }
@@ -604,13 +600,13 @@ bool DebugAction::Execute(Event event)
uint32 effect = dx + dy * 10 + spellEffect * 100; uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
Creature* wpCreature = Creature* wpCreature =
bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.GetPositionX(), botPos.GetPositionY(), bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.getX(), botPos.getY(),
botPos.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f); botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature) if (wpCreature)
{ {
@@ -650,12 +646,12 @@ bool DebugAction::Execute(Event event)
uint32 effect = dx + dy * 10 + spellEffect * 100; uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
wpCreature = bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.GetPositionX(), wpCreature = bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.getX(),
botPos.GetPositionY(), botPos.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f); botPos.getY(), botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature && lCreature) if (wpCreature && lCreature)
{ {
@@ -679,11 +675,11 @@ bool DebugAction::Execute(Event event)
uint32 effect = dx + dy * 10 + spellEffect * 100; uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
wpCreature = bot->SummonCreature(2334, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f); TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature) if (wpCreature)
@@ -712,11 +708,11 @@ bool DebugAction::Execute(Event event)
{ {
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
Creature* wpCreature = bot->SummonCreature(2334, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f); TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
all_targets.push_back(wpCreature->GetGUID()); all_targets.push_back(wpCreature->GetGUID());
@@ -792,11 +788,11 @@ bool DebugAction::Execute(Event event)
{ {
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
Creature* wpCreature = bot->SummonCreature(2334, botPos.GetPositionX(), botPos.GetPositionY(), botPos.GetPositionZ(), 0, Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f); TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
all_targets.push_back(wpCreature->GetGUID()); all_targets.push_back(wpCreature->GetGUID());
@@ -872,13 +868,13 @@ bool DebugAction::Execute(Event event)
uint32 effect = dx + dy * 10 + soundEffects * 100; uint32 effect = dx + dy * 10 + soundEffects * 100;
WorldPosition botPos(bot); WorldPosition botPos(bot);
botPos.setX(botPos.GetPositionX() + (dx - 5) * 5); botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.GetPositionY() + (dy - 5) * 5); botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight()); botPos.setZ(botPos.getHeight());
Creature* wpCreature = Creature* wpCreature =
bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.GetPositionX(), botPos.GetPositionY(), bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.getX(), botPos.getY(),
botPos.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f); botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
wpCreature->PlayDistanceSound(effect); wpCreature->PlayDistanceSound(effect);
} }
@@ -968,7 +964,7 @@ void DebugAction::FakeSpell(uint32 spellId, Unit* truecaster, Unit* caster, Obje
m_targets.SetDst(dest); m_targets.SetDst(dest);
if ((spellInfo && spellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION) || forceDest) if ((spellInfo && spellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION) || forceDest)
m_targets.SetSrc(source.GetPositionX(), source.GetPositionY(), source.GetPositionZ()); m_targets.SetSrc(source.getX(), source.getY(), source.getZ());
if (!forceDest && target) if (!forceDest && target)
if (!spellInfo || if (!spellInfo ||

View File

@@ -6,19 +6,15 @@
#include "DelayAction.h" #include "DelayAction.h"
#include "Event.h" #include "Event.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
#include "PlayerbotAIConfig.h"
bool DelayAction::Execute(Event /*event*/) bool DelayAction::Execute(Event event)
{ {
const uint32 delay = PlayerbotAIConfig::instance().passiveDelay + PlayerbotAIConfig::instance().globalCoolDown; uint32 delay = sPlayerbotAIConfig.passiveDelay + sPlayerbotAIConfig.globalCoolDown;
botAI->SetNextCheckDelay(delay); botAI->SetNextCheckDelay(delay);
return true; return true;
} }
bool DelayAction::isUseful() bool DelayAction::isUseful() { return !botAI->AllowActivity(ALL_ACTIVITY); }
{
return !botAI->AllowActivity(ALL_ACTIVITY);
}

View File

@@ -39,7 +39,7 @@ void DestroyItemAction::DestroyItem(FindItemVisitor* visitor)
bool SmartDestroyItemAction::isUseful() { return !botAI->HasActivePlayerMaster(); } bool SmartDestroyItemAction::isUseful() { return !botAI->HasActivePlayerMaster(); }
bool SmartDestroyItemAction::Execute(Event /*event*/) bool SmartDestroyItemAction::Execute(Event event)
{ {
uint8 bagSpace = AI_VALUE(uint8, "bag space"); uint8 bagSpace = AI_VALUE(uint8, "bag space");

View File

@@ -6,6 +6,7 @@
#include "EmoteAction.h" #include "EmoteAction.h"
#include "Event.h" #include "Event.h"
#include "PlayerbotTextMgr.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
@@ -786,7 +787,7 @@ bool EmoteAction::isUseful()
return time(nullptr) >= lastEmote; return time(nullptr) >= lastEmote;
} }
bool TalkAction::Execute(Event /*event*/) bool TalkAction::Execute(Event event)
{ {
Unit* target = botAI->GetUnit(AI_VALUE(ObjectGuid, "talk target")); Unit* target = botAI->GetUnit(AI_VALUE(ObjectGuid, "talk target"));
if (!target) if (!target)

View File

@@ -328,48 +328,12 @@ void EquipAction::EquipItem(Item* item)
botAI->TellMaster(out); botAI->TellMaster(out);
} }
ItemIds EquipAction::SelectInventoryItemsToEquip() bool EquipUpgradesAction::Execute(Event event)
{
CollectItemsVisitor visitor;
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
ItemIds items;
for (auto i = visitor.items.begin(); i != visitor.items.end(); ++i)
{
Item* item = *i;
if (!item)
continue;
ItemTemplate const* itemTemplate = item->GetTemplate();
if (!itemTemplate)
continue;
//TODO Expand to Glyphs and Gems, that can be placed in equipment
//Pre-filter non-equipable items
if (itemTemplate->InventoryType == INVTYPE_NON_EQUIP)
continue;
int32 randomProperty = item->GetItemRandomPropertyId();
uint32 itemId = item->GetTemplate()->ItemId;
std::string itemUsageParam;
if (randomProperty != 0)
itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty);
else
itemUsageParam = std::to_string(itemId);
ItemUsage usage = AI_VALUE2(ItemUsage, "item upgrade", itemUsageParam);
if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP)
items.insert(itemId);
}
return items;
}
bool EquipUpgradesPacketAction::Execute(Event event)
{ {
if (!sPlayerbotAIConfig.autoEquipUpgradeLoot && !sRandomPlayerbotMgr.IsRandomBot(bot)) if (!sPlayerbotAIConfig.autoEquipUpgradeLoot && !sRandomPlayerbotMgr.IsRandomBot(bot))
return false; return false;
std::string const source = event.GetSource();
if (source == "trade status") if (event.GetSource() == "trade status")
{ {
WorldPacket p(event.getPacket()); WorldPacket p(event.getPacket());
p.rpos(0); p.rpos(0);
@@ -380,7 +344,7 @@ bool EquipUpgradesPacketAction::Execute(Event event)
return false; return false;
} }
else if (source == "item push result") if (event.GetSource() == "item push result")
{ {
WorldPacket p(event.getPacket()); WorldPacket p(event.getPacket());
p.rpos(0); p.rpos(0);
@@ -397,18 +361,72 @@ bool EquipUpgradesPacketAction::Execute(Event event)
p >> itemId; p >> itemId;
ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId); ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
if (item->InventoryType == INVTYPE_NON_EQUIP) if (item->Class == ITEM_CLASS_TRADE_GOODS && item->SubClass == ITEM_SUBCLASS_MEAT)
return false; return false;
} }
ItemIds items = SelectInventoryItemsToEquip(); CollectItemsVisitor visitor;
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
ItemIds items;
for (auto i = visitor.items.begin(); i != visitor.items.end(); ++i)
{
Item* item = *i;
if (!item)
break;
int32 randomProperty = item->GetItemRandomPropertyId();
uint32 itemId = item->GetTemplate()->ItemId;
std::string itemUsageParam;
if (randomProperty != 0)
{
itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty);
}
else
{
itemUsageParam = std::to_string(itemId);
}
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam);
if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP)
{
items.insert(itemId);
}
}
EquipItems(items); EquipItems(items);
return true; return true;
} }
bool EquipUpgradeAction::Execute(Event /*event*/) bool EquipUpgradeAction::Execute(Event event)
{ {
ItemIds items = SelectInventoryItemsToEquip(); CollectItemsVisitor visitor;
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
ItemIds items;
for (auto i = visitor.items.begin(); i != visitor.items.end(); ++i)
{
Item* item = *i;
if (!item)
break;
int32 randomProperty = item->GetItemRandomPropertyId();
uint32 itemId = item->GetTemplate()->ItemId;
std::string itemUsageParam;
if (randomProperty != 0)
{
itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty);
}
else
{
itemUsageParam = std::to_string(itemId);
}
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam);
if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP)
{
items.insert(itemId);
}
}
EquipItems(items); EquipItems(items);
return true; return true;
} }

View File

@@ -8,7 +8,6 @@
#include "ChatHelper.h" #include "ChatHelper.h"
#include "InventoryAction.h" #include "InventoryAction.h"
#include "Item.h"
class FindItemVisitor; class FindItemVisitor;
class Item; class Item;
@@ -21,7 +20,6 @@ public:
bool Execute(Event event) override; bool Execute(Event event) override;
void EquipItems(ItemIds ids); void EquipItems(ItemIds ids);
ItemIds SelectInventoryItemsToEquip();
private: private:
void EquipItem(FindItemVisitor* visitor); void EquipItem(FindItemVisitor* visitor);
@@ -29,10 +27,10 @@ private:
void EquipItem(Item* item); void EquipItem(Item* item);
}; };
class EquipUpgradesPacketAction : public EquipAction class EquipUpgradesAction : public EquipAction
{ {
public: public:
explicit EquipUpgradesPacketAction(PlayerbotAI* botAI, std::string const name = "equip upgrades packet action") : EquipAction(botAI, name) {} EquipUpgradesAction(PlayerbotAI* botAI, std::string const name = "equip upgrades") : EquipAction(botAI, name) {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };
@@ -40,7 +38,7 @@ public:
class EquipUpgradeAction : public EquipAction class EquipUpgradeAction : public EquipAction
{ {
public: public:
explicit EquipUpgradeAction(PlayerbotAI* botAI, std::string const name = "equip upgrade") : EquipAction(botAI, name) {} EquipUpgradeAction(PlayerbotAI* botAI, std::string const name = "equip upgrade") : EquipAction(botAI, name) {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };

View File

@@ -246,7 +246,7 @@ WorldPosition FindFishingHole(PlayerbotAI* botAI)
return WorldPosition(); return WorldPosition();
} }
bool MoveNearWaterAction::Execute(Event /*event*/) bool MoveNearWaterAction::Execute(Event event)
{ {
WorldPosition landSpot = AI_VALUE(WorldPosition, "fishing spot"); WorldPosition landSpot = AI_VALUE(WorldPosition, "fishing spot");
if (landSpot.IsValid()) if (landSpot.IsValid())
@@ -336,7 +336,7 @@ bool MoveNearWaterAction::isPossible()
return false; return false;
} }
bool EquipFishingPoleAction::Execute(Event /*event*/) bool EquipFishingPoleAction::Execute(Event event)
{ {
if (!_pole) if (!_pole)
return false; return false;
@@ -463,7 +463,7 @@ bool UseBobberAction::isUseful()
return AI_VALUE(bool, "can use fishing bobber"); return AI_VALUE(bool, "can use fishing bobber");
} }
bool UseBobberAction::Execute(Event /*event*/) bool UseBobberAction::Execute(Event event)
{ {
GuidVector gos = AI_VALUE(GuidVector, "nearest game objects no los"); GuidVector gos = AI_VALUE(GuidVector, "nearest game objects no los");
for (auto const& guid : gos) for (auto const& guid : gos)
@@ -485,7 +485,7 @@ bool UseBobberAction::Execute(Event /*event*/)
return false; return false;
} }
bool EndMasterFishingAction::Execute(Event /*event*/) bool EndMasterFishingAction::Execute(Event event)
{ {
botAI->ChangeStrategy("-master fishing", BOT_STATE_NON_COMBAT); botAI->ChangeStrategy("-master fishing", BOT_STATE_NON_COMBAT);
return true; return true;
@@ -503,7 +503,7 @@ bool EndMasterFishingAction::isUseful()
return !nearWater.IsValid(); return !nearWater.IsValid();
} }
bool RemoveBobberStrategyAction::Execute(Event /*event*/) bool RemoveBobberStrategyAction::Execute(Event event)
{ {
botAI->ChangeStrategy("-use bobber", BOT_STATE_NON_COMBAT); botAI->ChangeStrategy("-use bobber", BOT_STATE_NON_COMBAT);
return true; return true;

View File

@@ -7,16 +7,15 @@
#define _PLAYERBOT_FISHINGACTION_H #define _PLAYERBOT_FISHINGACTION_H
#include "Action.h" #include "Action.h"
#include "Event.h"
#include "MovementActions.h" #include "MovementActions.h"
#include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
extern const uint32 FISHING_SPELL; extern const uint32 FISHING_SPELL;
extern const uint32 FISHING_POLE; extern const uint32 FISHING_POLE;
extern const uint32 FISHING_BOBBER; extern const uint32 FISHING_BOBBER;
WorldPosition FindWaterRadial(Player* bot, float x, float y, float z, Map* map, uint32 phaseMask, float minDistance, WorldPosition FindWaterRadial(Player* bot, float x, float y, float z, Map* map, uint32 phaseMask, float minDistance, float maxDistance, float increment, bool checkLOS=false, int numDirections = 16);
float maxDistance, float increment, bool checkLOS = false, int numDirections = 16);
class PlayerbotAI; class PlayerbotAI;
@@ -24,7 +23,6 @@ class FishingAction : public Action
{ {
public: public:
FishingAction(PlayerbotAI* botAI) : Action(botAI, "go fishing"){} FishingAction(PlayerbotAI* botAI) : Action(botAI, "go fishing"){}
bool Execute(Event event) override; bool Execute(Event event) override;
bool isUseful() override; bool isUseful() override;
}; };
@@ -33,10 +31,8 @@ class EquipFishingPoleAction : public Action
{ {
public: public:
EquipFishingPoleAction(PlayerbotAI* botAI) : Action(botAI, "equip fishing pole") {} EquipFishingPoleAction(PlayerbotAI* botAI) : Action(botAI, "equip fishing pole") {}
bool Execute(Event event) override; bool Execute(Event event) override;
bool isUseful() override; bool isUseful() override;
private: private:
Item* _pole = nullptr; Item* _pole = nullptr;
}; };
@@ -45,7 +41,6 @@ class MoveNearWaterAction : public MovementAction
{ {
public: public:
MoveNearWaterAction(PlayerbotAI* botAI): MovementAction(botAI, "move near water") {} MoveNearWaterAction(PlayerbotAI* botAI): MovementAction(botAI, "move near water") {}
bool Execute(Event event) override; bool Execute(Event event) override;
bool isUseful() override; bool isUseful() override;
bool isPossible() override; bool isPossible() override;
@@ -55,7 +50,6 @@ class UseBobberAction : public Action
{ {
public: public:
UseBobberAction(PlayerbotAI* botAI) : Action(botAI, "use fishing bobber") {} UseBobberAction(PlayerbotAI* botAI) : Action(botAI, "use fishing bobber") {}
bool Execute(Event event) override; bool Execute(Event event) override;
bool isUseful() override; bool isUseful() override;
}; };
@@ -64,7 +58,6 @@ class EndMasterFishingAction : public Action
{ {
public: public:
EndMasterFishingAction(PlayerbotAI* botAI) : Action(botAI, "end master fishing") {} EndMasterFishingAction(PlayerbotAI* botAI) : Action(botAI, "end master fishing") {}
bool Execute(Event event) override; bool Execute(Event event) override;
bool isUseful() override; bool isUseful() override;
}; };
@@ -73,8 +66,6 @@ class RemoveBobberStrategyAction : public Action
{ {
public: public:
RemoveBobberStrategyAction(PlayerbotAI* botAI) : Action(botAI, "remove bobber strategy") {} RemoveBobberStrategyAction(PlayerbotAI* botAI) : Action(botAI, "remove bobber strategy") {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };
#endif #endif

View File

@@ -5,14 +5,17 @@
#include "FollowActions.h" #include "FollowActions.h"
#include <cstddef>
#include "Event.h" #include "Event.h"
#include "Formations.h" #include "Formations.h"
#include "LastMovementValue.h" #include "LastMovementValue.h"
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
#include "SharedDefines.h"
bool FollowAction::Execute(Event /*event*/) bool FollowAction::Execute(Event event)
{ {
Formation* formation = AI_VALUE(Formation*, "formation"); Formation* formation = AI_VALUE(Formation*, "formation");
std::string const target = formation->GetTargetName(); std::string const target = formation->GetTargetName();
@@ -113,7 +116,7 @@ bool FollowAction::CanDeadFollow(Unit* target)
return true; return true;
} }
bool FleeToGroupLeaderAction::Execute(Event /*event*/) bool FleeToGroupLeaderAction::Execute(Event event)
{ {
Unit* fTarget = AI_VALUE(Unit*, "group leader"); Unit* fTarget = AI_VALUE(Unit*, "group leader");
bool canFollow = Follow(fTarget); bool canFollow = Follow(fTarget);

View File

@@ -11,6 +11,8 @@
#include "CreatureAI.h" #include "CreatureAI.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "CharmInfo.h" #include "CharmInfo.h"
#include "SharedDefines.h"
#include "ObjectGuid.h"
#include "SpellMgr.h" #include "SpellMgr.h"
#include "SpellInfo.h" #include "SpellInfo.h"
#include <vector> #include <vector>
@@ -52,7 +54,7 @@ bool MeleeAction::isUseful()
return true; return true;
} }
bool TogglePetSpellAutoCastAction::Execute(Event /*event*/) bool TogglePetSpellAutoCastAction::Execute(Event event)
{ {
Pet* pet = bot->GetPet(); Pet* pet = bot->GetPet();
if (!pet) if (!pet)
@@ -117,7 +119,7 @@ bool TogglePetSpellAutoCastAction::Execute(Event /*event*/)
return toggled; return toggled;
} }
bool PetAttackAction::Execute(Event /*event*/) bool PetAttackAction::Execute(Event event)
{ {
Guardian* pet = bot->GetGuardianPet(); Guardian* pet = bot->GetGuardianPet();
if (!pet) if (!pet)

View File

@@ -17,17 +17,19 @@
#include "WorldPacket.h" #include "WorldPacket.h"
#include "Group.h" #include "Group.h"
#include "Chat.h" #include "Chat.h"
#include "Language.h"
#include "GenericBuffUtils.h" #include "GenericBuffUtils.h"
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
using ai::buff::MakeAuraQualifierForBuff; using ai::buff::MakeAuraQualifierForBuff;
using ai::buff::UpgradeToGroupIfAppropriate;
CastSpellAction::CastSpellAction(PlayerbotAI* botAI, std::string const spell) CastSpellAction::CastSpellAction(PlayerbotAI* botAI, std::string const spell)
: Action(botAI, spell), range(botAI->GetRange("spell")), spell(spell) : Action(botAI, spell), range(botAI->GetRange("spell")), spell(spell)
{ {
} }
bool CastSpellAction::Execute(Event /*event*/) bool CastSpellAction::Execute(Event event)
{ {
if (spell == "conjure food" || spell == "conjure water") if (spell == "conjure food" || spell == "conjure water")
{ {
@@ -76,35 +78,6 @@ bool CastSpellAction::Execute(Event /*event*/)
return botAI->CastSpell(spell, GetTarget()); return botAI->CastSpell(spell, GetTarget());
} }
bool CastSpellAction::isUseful()
{
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true))
return false;
if (spell == "mount" && !bot->IsMounted() && !bot->IsInCombat())
return true;
if (spell == "mount" && bot->IsInCombat())
{
bot->Dismount();
return false;
}
Unit* spellTarget = GetTarget();
if (!spellTarget)
return false;
if (!spellTarget->IsInWorld() || spellTarget->GetMapId() != bot->GetMapId())
return false;
// float combatReach = bot->GetCombatReach() + target->GetCombatReach();
// if (!botAI->IsRanged(bot))
// combatReach += 4.0f / 3.0f;
return AI_VALUE2(bool, "spell cast useful", spell);
// && ServerFacade::instance().GetDistance2d(bot, target) <= (range + combatReach);
}
bool CastSpellAction::isPossible() bool CastSpellAction::isPossible()
{ {
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true)) if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true))
@@ -133,6 +106,36 @@ bool CastSpellAction::isPossible()
return botAI->CanCastSpell(spell, GetTarget()); return botAI->CanCastSpell(spell, GetTarget());
} }
bool CastSpellAction::isUseful()
{
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true))
return false;
if (spell == "mount" && !bot->IsMounted() && !bot->IsInCombat())
return true;
if (spell == "mount" && bot->IsInCombat())
{
bot->Dismount();
return false;
}
Unit* spellTarget = GetTarget();
if (!spellTarget)
return false;
if (!spellTarget->IsInWorld() || spellTarget->GetMapId() != bot->GetMapId())
return false;
// float combatReach = bot->GetCombatReach() + spellTarget->GetCombatReach();
// if (!botAI->IsRanged(bot))
// combatReach += 4.0f / 3.0f;
return spellTarget &&
AI_VALUE2(bool, "spell cast useful",
spell); // && ServerFacade::instance().GetDistance2d(bot, spellTarget) <= (range + combatReach);
}
CastMeleeSpellAction::CastMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) CastMeleeSpellAction::CastMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell)
{ {
range = ATTACK_DISTANCE; range = ATTACK_DISTANCE;
@@ -230,7 +233,7 @@ Value<Unit*>* BuffOnPartyAction::GetTargetValue()
return context->GetValue<Unit*>("party member without aura", MakeAuraQualifierForBuff(spell)); return context->GetValue<Unit*>("party member without aura", MakeAuraQualifierForBuff(spell));
} }
bool BuffOnPartyAction::Execute(Event /*event*/) bool BuffOnPartyAction::Execute(Event event)
{ {
std::string castName = spell; // default = mono std::string castName = spell; // default = mono
@@ -287,7 +290,7 @@ Value<Unit*>* CastSnareSpellAction::GetTargetValue() { return context->GetValue<
Value<Unit*>* CastCrowdControlSpellAction::GetTargetValue() { return context->GetValue<Unit*>("cc target", getName()); } Value<Unit*>* CastCrowdControlSpellAction::GetTargetValue() { return context->GetValue<Unit*>("cc target", getName()); }
bool CastCrowdControlSpellAction::Execute(Event /*event*/) { return botAI->CastSpell(getName(), GetTarget()); } bool CastCrowdControlSpellAction::Execute(Event event) { return botAI->CastSpell(getName(), GetTarget()); }
bool CastCrowdControlSpellAction::isPossible() { return botAI->CanCastSpell(getName(), GetTarget()); } bool CastCrowdControlSpellAction::isPossible() { return botAI->CanCastSpell(getName(), GetTarget()); }
@@ -305,13 +308,13 @@ bool CastVehicleSpellAction::isPossible()
bool CastVehicleSpellAction::isUseful() { return botAI->IsInVehicle(false, true); } bool CastVehicleSpellAction::isUseful() { return botAI->IsInVehicle(false, true); }
bool CastVehicleSpellAction::Execute(Event /*event*/) bool CastVehicleSpellAction::Execute(Event event)
{ {
uint32 spellId = AI_VALUE2(uint32, "vehicle spell id", spell); uint32 spellId = AI_VALUE2(uint32, "vehicle spell id", spell);
return botAI->CastVehicleSpell(spellId, GetTarget()); return botAI->CastVehicleSpell(spellId, GetTarget());
} }
bool UseTrinketAction::Execute(Event /*event*/) bool UseTrinketAction::Execute(Event event)
{ {
Item* trinket1 = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TRINKET1); Item* trinket1 = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TRINKET1);

View File

@@ -23,8 +23,8 @@ public:
std::string const GetTargetName() override { return "current target"; }; std::string const GetTargetName() override { return "current target"; };
bool Execute(Event event) override; bool Execute(Event event) override;
bool isUseful() override;
bool isPossible() override; bool isPossible() override;
bool isUseful() override;
ActionThreatType getThreatType() override { return ActionThreatType::Single; } ActionThreatType getThreatType() override { return ActionThreatType::Single; }
std::vector<NextAction> getPrerequisites() override std::vector<NextAction> getPrerequisites() override

View File

@@ -11,7 +11,7 @@
std::vector<std::string> split(std::string const s, char delim); std::vector<std::string> split(std::string const s, char delim);
bool GiveItemAction::Execute(Event /*event*/) bool GiveItemAction::Execute(Event event)
{ {
Unit* target = GetTarget(); Unit* target = GetTarget();
if (!target) if (!target)

View File

@@ -10,7 +10,7 @@
GreetAction::GreetAction(PlayerbotAI* botAI) : Action(botAI, "greet") {} GreetAction::GreetAction(PlayerbotAI* botAI) : Action(botAI, "greet") {}
bool GreetAction::Execute(Event /*event*/) bool GreetAction::Execute(Event event)
{ {
ObjectGuid guid = AI_VALUE(ObjectGuid, "new player nearby"); ObjectGuid guid = AI_VALUE(ObjectGuid, "new player nearby");
if (!guid || !guid.IsPlayer()) if (!guid || !guid.IsPlayer())

View File

@@ -6,8 +6,7 @@
#include "GuildBankAction.h" #include "GuildBankAction.h"
#include "GuildMgr.h" #include "GuildMgr.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
#include "AiObjectContext.h"
bool GuildBankAction::Execute(Event event) bool GuildBankAction::Execute(Event event)
{ {

View File

@@ -12,9 +12,9 @@
#include "Playerbots.h" #include "Playerbots.h"
#include "RandomPlayerbotFactory.h" #include "RandomPlayerbotFactory.h"
#include "ServerFacade.h" #include "ServerFacade.h"
#include "SharedDefines.h" #include "SharedDefines.h" // GOLD
bool BuyPetitionAction::Execute(Event /*event*/) bool BuyPetitionAction::Execute(Event event)
{ {
GuidVector vendors = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get(); GuidVector vendors = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get();
bool vendored = false, result = false; bool vendored = false, result = false;
@@ -152,7 +152,7 @@ bool PetitionOfferAction::Execute(Event event)
bool PetitionOfferAction::isUseful() { return !bot->GetGuildId(); } bool PetitionOfferAction::isUseful() { return !bot->GetGuildId(); }
bool PetitionOfferNearbyAction::Execute(Event /*event*/) bool PetitionOfferNearbyAction::Execute(Event event)
{ {
uint32 found = 0; uint32 found = 0;
@@ -209,7 +209,7 @@ bool PetitionOfferNearbyAction::isUseful()
AI_VALUE(uint8, "petition signs") < sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); AI_VALUE(uint8, "petition signs") < sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS);
} }
bool PetitionTurnInAction::Execute(Event /*event*/) bool PetitionTurnInAction::Execute(Event event)
{ {
GuidVector vendors = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get(); GuidVector vendors = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get();
bool vendored = false, result = false; bool vendored = false, result = false;
@@ -297,7 +297,7 @@ bool PetitionTurnInAction::isUseful()
!context->GetValue<TravelTarget*>("travel target")->Get()->isTraveling(); !context->GetValue<TravelTarget*>("travel target")->Get()->isTraveling();
} }
bool BuyTabardAction::Execute(Event /*event*/) bool BuyTabardAction::Execute(Event event)
{ {
bool canBuy = botAI->DoSpecificAction("buy", Event("buy tabard", "Hitem:5976:")); bool canBuy = botAI->DoSpecificAction("buy", Event("buy tabard", "Hitem:5976:"));
if (canBuy && AI_VALUE2(uint32, "item count", chat->FormatQItem(5976))) if (canBuy && AI_VALUE2(uint32, "item count", chat->FormatQItem(5976)))

View File

@@ -128,7 +128,7 @@ bool GuildRemoveAction::PlayerIsValid(Player* member)
return member->GetGuildId() == bot->GetGuildId() && GetRankId(bot) < GetRankId(member); return member->GetGuildId() == bot->GetGuildId() && GetRankId(bot) < GetRankId(member);
}; };
bool GuildManageNearbyAction::Execute(Event /*event*/) bool GuildManageNearbyAction::Execute(Event event)
{ {
uint32 found = 0; uint32 found = 0;
@@ -149,6 +149,7 @@ bool GuildManageNearbyAction::Execute(Event /*event*/)
// Promote or demote nearby members based on chance. // Promote or demote nearby members based on chance.
if (player->GetGuildId() && player->GetGuildId() == bot->GetGuildId()) if (player->GetGuildId() && player->GetGuildId() == bot->GetGuildId())
{ {
Guild::Member* member = guild->GetMember(player->GetGUID());
uint32 dCount = AI_VALUE(uint32, "death count"); uint32 dCount = AI_VALUE(uint32, "death count");
if (!urand(0, 30) && dCount < 2 && guild->GetRankRights(botMember->GetRankId()) & GR_RIGHT_PROMOTE) if (!urand(0, 30) && dCount < 2 && guild->GetRankRights(botMember->GetRankId()) & GR_RIGHT_PROMOTE)

View File

@@ -7,13 +7,13 @@
#include "ChatActionContext.h" #include "ChatActionContext.h"
#include "Event.h" #include "Event.h"
#include "AiObjectContext.h" #include "Playerbots.h"
HelpAction::HelpAction(PlayerbotAI* botAI) : Action(botAI, "help") { chatContext = new ChatActionContext(); } HelpAction::HelpAction(PlayerbotAI* botAI) : Action(botAI, "help") { chatContext = new ChatActionContext(); }
HelpAction::~HelpAction() { delete chatContext; } HelpAction::~HelpAction() { delete chatContext; }
bool HelpAction::Execute(Event /*event*/) bool HelpAction::Execute(Event event)
{ {
TellChatCommands(); TellChatCommands();
TellStrategies(); TellStrategies();

View File

@@ -6,16 +6,15 @@
#include "HireAction.h" #include "HireAction.h"
#include "Event.h" #include "Event.h"
#include "RandomPlayerbotMgr.h" #include "Playerbots.h"
#include "PlayerbotAI.h"
bool HireAction::Execute(Event /*event*/) bool HireAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
return false; return false;
if (!RandomPlayerbotMgr::instance().IsRandomBot(bot)) if (!sRandomPlayerbotMgr.IsRandomBot(bot))
return false; return false;
uint32 account = master->GetSession()->GetAccountId(); uint32 account = master->GetSession()->GetAccountId();
@@ -40,7 +39,7 @@ bool HireAction::Execute(Event /*event*/)
return false; return false;
} }
uint32 discount = RandomPlayerbotMgr::instance().GetTradeDiscount(bot, master); uint32 discount = sRandomPlayerbotMgr.GetTradeDiscount(bot, master);
uint32 m = 1 + (bot->GetLevel() / 10); uint32 m = 1 + (bot->GetLevel() / 10);
uint32 moneyReq = m * 5000 * bot->GetLevel(); uint32 moneyReq = m * 5000 * bot->GetLevel();
if (discount < moneyReq) if (discount < moneyReq)
@@ -55,7 +54,7 @@ bool HireAction::Execute(Event /*event*/)
botAI->TellMaster("I will join you at your next relogin"); botAI->TellMaster("I will join you at your next relogin");
bot->SetMoney(moneyReq); bot->SetMoney(moneyReq);
RandomPlayerbotMgr::instance().Remove(bot); sRandomPlayerbotMgr.Remove(bot);
CharacterDatabase.Execute("UPDATE characters SET account = {} WHERE guid = {}", account, CharacterDatabase.Execute("UPDATE characters SET account = {} WHERE guid = {}", account,
bot->GetGUID().GetCounter()); bot->GetGUID().GetCounter());

View File

@@ -10,7 +10,7 @@
ImbueWithPoisonAction::ImbueWithPoisonAction(PlayerbotAI* botAI) : Action(botAI, "apply poison") {} ImbueWithPoisonAction::ImbueWithPoisonAction(PlayerbotAI* botAI) : Action(botAI, "apply poison") {}
bool ImbueWithPoisonAction::Execute(Event /*event*/) bool ImbueWithPoisonAction::Execute(Event event)
{ {
if (bot->IsInCombat()) if (bot->IsInCombat())
return false; return false;
@@ -103,7 +103,7 @@ bool ImbueWithPoisonAction::Execute(Event /*event*/)
// Search and apply stone to weapons // Search and apply stone to weapons
ImbueWithStoneAction::ImbueWithStoneAction(PlayerbotAI* botAI) : Action(botAI, "apply stone") {} ImbueWithStoneAction::ImbueWithStoneAction(PlayerbotAI* botAI) : Action(botAI, "apply stone") {}
bool ImbueWithStoneAction::Execute(Event /*event*/) bool ImbueWithStoneAction::Execute(Event event)
{ {
if (bot->IsInCombat()) if (bot->IsInCombat())
return false; return false;
@@ -148,7 +148,7 @@ bool ImbueWithStoneAction::Execute(Event /*event*/)
// Search and apply oil to weapons // Search and apply oil to weapons
ImbueWithOilAction::ImbueWithOilAction(PlayerbotAI* botAI) : Action(botAI, "apply oil") {} ImbueWithOilAction::ImbueWithOilAction(PlayerbotAI* botAI) : Action(botAI, "apply oil") {}
bool ImbueWithOilAction::Execute(Event /*event*/) bool ImbueWithOilAction::Execute(Event event)
{ {
if (bot->IsInCombat()) if (bot->IsInCombat())
return false; return false;
@@ -201,7 +201,7 @@ static const uint32 uPrioritizedHealingItemIds[19] = {
TryEmergencyAction::TryEmergencyAction(PlayerbotAI* botAI) : Action(botAI, "try emergency") {} TryEmergencyAction::TryEmergencyAction(PlayerbotAI* botAI) : Action(botAI, "try emergency") {}
bool TryEmergencyAction::Execute(Event /*event*/) bool TryEmergencyAction::Execute(Event event)
{ {
// Do not use consumable if bot can heal self // Do not use consumable if bot can heal self
if ((botAI->IsHeal(bot)) && (bot->GetPowerPct(POWER_MANA) > 20)) if ((botAI->IsHeal(bot)) && (bot->GetPowerPct(POWER_MANA) > 20))

View File

@@ -351,7 +351,9 @@ uint32 InventoryAction::GetItemCount(FindItemVisitor* visitor, IterateItemsMask
std::vector<Item*>& items = visitor->GetResult(); std::vector<Item*>& items = visitor->GetResult();
for (Item* item : items) for (Item* item : items)
{
count += item->GetCount(); count += item->GetCount();
}
return count; return count;
} }

View File

@@ -8,6 +8,7 @@
#include "BroadcastHelper.h" #include "BroadcastHelper.h"
#include "Event.h" #include "Event.h"
#include "GuildMgr.h" #include "GuildMgr.h"
#include "Log.h"
#include "PlayerbotOperations.h" #include "PlayerbotOperations.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "PlayerbotWorldThreadProcessor.h" #include "PlayerbotWorldThreadProcessor.h"
@@ -43,7 +44,7 @@ bool InviteToGroupAction::Invite(Player* inviter, Player* player)
return true; return true;
} }
bool InviteNearbyToGroupAction::Execute(Event /*event*/) bool InviteNearbyToGroupAction::Execute(Event event)
{ {
GuidVector nearGuids = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest friendly players")->Get(); GuidVector nearGuids = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest friendly players")->Get();
for (auto& i : nearGuids) for (auto& i : nearGuids)
@@ -61,7 +62,7 @@ bool InviteNearbyToGroupAction::Execute(Event /*event*/)
if (player->GetGroup()) if (player->GetGroup())
continue; continue;
if (!PlayerbotAIConfig::instance().randomBotInvitePlayer && GET_PLAYERBOT_AI(player)->IsRealPlayer()) if (!sPlayerbotAIConfig.randomBotInvitePlayer && GET_PLAYERBOT_AI(player)->IsRealPlayer())
continue; continue;
Group* group = bot->GetGroup(); Group* group = bot->GetGroup();
@@ -87,7 +88,7 @@ bool InviteNearbyToGroupAction::Execute(Event /*event*/)
if (abs(int32(player->GetLevel() - bot->GetLevel())) > 2) if (abs(int32(player->GetLevel() - bot->GetLevel())) > 2)
continue; continue;
if (ServerFacade::instance().GetDistance2d(bot, player) > PlayerbotAIConfig::instance().sightDistance) if (ServerFacade::instance().GetDistance2d(bot, player) > sPlayerbotAIConfig.sightDistance)
continue; continue;
// When inviting the 5th member of the group convert to raid for future invites. // When inviting the 5th member of the group convert to raid for future invites.
@@ -98,7 +99,7 @@ bool InviteNearbyToGroupAction::Execute(Event /*event*/)
PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp)); PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp));
} }
if (PlayerbotAIConfig::instance().inviteChat && RandomPlayerbotMgr::instance().IsRandomBot(bot)) if (sPlayerbotAIConfig.inviteChat && sRandomPlayerbotMgr.IsRandomBot(bot))
{ {
std::map<std::string, std::string> placeholders; std::map<std::string, std::string> placeholders;
placeholders["%player"] = player->GetName(); placeholders["%player"] = player->GetName();
@@ -119,7 +120,7 @@ bool InviteNearbyToGroupAction::Execute(Event /*event*/)
bool InviteNearbyToGroupAction::isUseful() bool InviteNearbyToGroupAction::isUseful()
{ {
if (!PlayerbotAIConfig::instance().randomBotGroupNearby) if (!sPlayerbotAIConfig.randomBotGroupNearby)
return false; return false;
if (bot->InBattleground()) if (bot->InBattleground())
@@ -165,7 +166,7 @@ std::vector<Player*> InviteGuildToGroupAction::getGuildMembers()
return worker.GetResult(); return worker.GetResult();
} }
bool InviteGuildToGroupAction::Execute(Event /*event*/) bool InviteGuildToGroupAction::Execute(Event event)
{ {
Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId());
@@ -185,7 +186,7 @@ bool InviteGuildToGroupAction::Execute(Event /*event*/)
if (player->isDND()) if (player->isDND())
continue; continue;
if (!PlayerbotAIConfig::instance().randomBotInvitePlayer && GET_PLAYERBOT_AI(player)->IsRealPlayer()) if (!sPlayerbotAIConfig.randomBotInvitePlayer && GET_PLAYERBOT_AI(player)->IsRealPlayer())
continue; continue;
if (player->IsBeingTeleported()) if (player->IsBeingTeleported())
@@ -220,7 +221,7 @@ bool InviteGuildToGroupAction::Execute(Event /*event*/)
player->GetLevel() + 5) // Do not invite members that too low level or risk dragging them to deadly places. player->GetLevel() + 5) // Do not invite members that too low level or risk dragging them to deadly places.
continue; continue;
if (!playerAi && ServerFacade::instance().GetDistance2d(bot, player) > PlayerbotAIConfig::instance().sightDistance) if (!playerAi && ServerFacade::instance().GetDistance2d(bot, player) > sPlayerbotAIConfig.sightDistance)
continue; continue;
Group* group = bot->GetGroup(); Group* group = bot->GetGroup();
@@ -232,8 +233,8 @@ bool InviteGuildToGroupAction::Execute(Event /*event*/)
PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp)); PlayerbotWorldThreadProcessor::instance().QueueOperation(std::move(convertOp));
} }
if (PlayerbotAIConfig::instance().inviteChat && if (sPlayerbotAIConfig.inviteChat &&
(RandomPlayerbotMgr::instance().IsRandomBot(bot) || !botAI->HasActivePlayerMaster())) (sRandomPlayerbotMgr.IsRandomBot(bot) || !botAI->HasActivePlayerMaster()))
{ {
BroadcastHelper::BroadcastGuildGroupOrRaidInvite(botAI, bot, player, group); BroadcastHelper::BroadcastGuildGroupOrRaidInvite(botAI, bot, player, group);
} }

View File

@@ -92,7 +92,7 @@ bool LeaveGroupAction::Leave()
return true; return true;
} }
bool LeaveFarAwayAction::Execute(Event /*event*/) bool LeaveFarAwayAction::Execute(Event event)
{ {
// allow bot to leave party when they want // allow bot to leave party when they want
return Leave(); return Leave();

View File

@@ -8,11 +8,11 @@
#include "AiFactory.h" #include "AiFactory.h"
#include "ItemVisitors.h" #include "ItemVisitors.h"
#include "LFGMgr.h" #include "LFGMgr.h"
#include "LFGPackets.h"
#include "Opcodes.h" #include "Opcodes.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "World.h" #include "World.h"
#include "WorldPacket.h" #include "WorldPacket.h"
#include "RandomPlayerbotMgr.h"
using namespace lfg; using namespace lfg;
@@ -20,7 +20,7 @@ bool LfgJoinAction::Execute(Event event) { return JoinLFG(); }
uint32 LfgJoinAction::GetRoles() uint32 LfgJoinAction::GetRoles()
{ {
if (!RandomPlayerbotMgr::instance().IsRandomBot(bot)) if (!sRandomPlayerbotMgr.IsRandomBot(bot))
{ {
if (botAI->IsTank(bot)) if (botAI->IsTank(bot))
return PLAYER_ROLE_TANK; return PLAYER_ROLE_TANK;
@@ -101,7 +101,7 @@ bool LfgJoinAction::JoinLFG()
LfgDungeonSet list; LfgDungeonSet list;
std::vector<uint32> selected; std::vector<uint32> selected;
std::vector<uint32> dungeons = RandomPlayerbotMgr::instance().LfgDungeons[bot->GetTeamId()]; std::vector<uint32> dungeons = sRandomPlayerbotMgr.LfgDungeons[bot->GetTeamId()];
if (!dungeons.size()) if (!dungeons.size())
return false; return false;
@@ -170,7 +170,7 @@ bool LfgJoinAction::JoinLFG()
return true; return true;
} }
bool LfgRoleCheckAction::Execute(Event /*event*/) bool LfgRoleCheckAction::Execute(Event event)
{ {
if (Group* group = bot->GetGroup()) if (Group* group = bot->GetGroup())
{ {
@@ -216,9 +216,9 @@ bool LfgAcceptAction::Execute(Event event)
*packet << id << true; *packet << id << true;
bot->GetSession()->QueuePacket(packet); bot->GetSession()->QueuePacket(packet);
if (RandomPlayerbotMgr::instance().IsRandomBot(bot) && !bot->GetGroup()) if (sRandomPlayerbotMgr.IsRandomBot(bot) && !bot->GetGroup())
{ {
RandomPlayerbotMgr::instance().Refresh(bot); sRandomPlayerbotMgr.Refresh(bot);
botAI->ResetStrategies(); botAI->ResetStrategies();
} }
@@ -251,9 +251,9 @@ bool LfgAcceptAction::Execute(Event event)
*packet << id << true; *packet << id << true;
bot->GetSession()->QueuePacket(packet); bot->GetSession()->QueuePacket(packet);
if (RandomPlayerbotMgr::instance().IsRandomBot(bot) && !bot->GetGroup()) if (sRandomPlayerbotMgr.IsRandomBot(bot) && !bot->GetGroup())
{ {
RandomPlayerbotMgr::instance().Refresh(bot); sRandomPlayerbotMgr.Refresh(bot);
botAI->ResetStrategies(); botAI->ResetStrategies();
} }
@@ -265,7 +265,7 @@ bool LfgAcceptAction::Execute(Event event)
return false; return false;
} }
bool LfgLeaveAction::Execute(Event /*event*/) bool LfgLeaveAction::Execute(Event event)
{ {
// Don't leave if lfg strategy enabled // Don't leave if lfg strategy enabled
// if (botAI->HasStrategy("lfg", BOT_STATE_NON_COMBAT)) // if (botAI->HasStrategy("lfg", BOT_STATE_NON_COMBAT))
@@ -337,7 +337,7 @@ bool LfgJoinAction::isUseful()
if (bot->isDead()) if (bot->isDead())
return false; return false;
if (!RandomPlayerbotMgr::instance().IsRandomBot(bot)) if (!sRandomPlayerbotMgr.IsRandomBot(bot))
return false; return false;
Map* map = bot->GetMap(); Map* map = bot->GetMap();

View File

@@ -13,7 +13,7 @@
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "Playerbots.h" #include "Playerbots.h"
bool LootRollAction::Execute(Event /*event*/) bool LootRollAction::Execute(Event event)
{ {
Group* group = bot->GetGroup(); Group* group = bot->GetGroup();
if (!group) if (!group)
@@ -90,8 +90,6 @@ bool LootRollAction::Execute(Event /*event*/)
} }
else if (sPlayerbotAIConfig.lootRollLevel == 1) else if (sPlayerbotAIConfig.lootRollLevel == 1)
{ {
// Level 1 = "greed" mode: bots greed on useful items but never need
// Only downgrade NEED to GREED, preserve GREED votes as-is
if (vote == NEED) if (vote == NEED)
{ {
if (RollUniqueCheck(proto, bot)) if (RollUniqueCheck(proto, bot))
@@ -103,6 +101,10 @@ bool LootRollAction::Execute(Event /*event*/)
vote = GREED; vote = GREED;
} }
} }
else if (vote == GREED)
{
vote = PASS;
}
} }
switch (group->GetLootMethod()) switch (group->GetLootMethod())
{ {

View File

@@ -11,16 +11,20 @@
#include "LastMovementValue.h" #include "LastMovementValue.h"
#include "Playerbots.h" #include "Playerbots.h"
bool MoveToRpgTargetAction::Execute(Event /*event*/) bool MoveToRpgTargetAction::Execute(Event event)
{ {
GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target");
Unit* unit = botAI->GetUnit(guidP); Unit* unit = botAI->GetUnit(guidP);
if (unit && !unit->IsInWorld()) if (unit && !unit->IsInWorld())
{
return false; return false;
}
GameObject* go = botAI->GetGameObject(guidP); GameObject* go = botAI->GetGameObject(guidP);
if (go && !go->IsInWorld()) if (go && !go->IsInWorld())
{
return false; return false;
}
Player* player = guidP.GetPlayer();
WorldObject* wo = nullptr; WorldObject* wo = nullptr;
if (unit) if (unit)

View File

@@ -7,9 +7,10 @@
#include "ChooseRpgTargetAction.h" #include "ChooseRpgTargetAction.h"
#include "LootObjectStack.h" #include "LootObjectStack.h"
#include "PathGenerator.h"
#include "Playerbots.h" #include "Playerbots.h"
bool MoveToTravelTargetAction::Execute(Event /*event*/) bool MoveToTravelTargetAction::Execute(Event event)
{ {
TravelTarget* target = AI_VALUE(TravelTarget*, "travel target"); TravelTarget* target = AI_VALUE(TravelTarget*, "travel target");

View File

@@ -15,6 +15,7 @@
#include "FleeManager.h" #include "FleeManager.h"
#include "G3D/Vector3.h" #include "G3D/Vector3.h"
#include "GameObject.h" #include "GameObject.h"
#include "Geometry.h"
#include "LastMovementValue.h" #include "LastMovementValue.h"
#include "LootObjectStack.h" #include "LootObjectStack.h"
#include "Map.h" #include "Map.h"
@@ -35,7 +36,9 @@
#include "SpellAuraEffects.h" #include "SpellAuraEffects.h"
#include "SpellInfo.h" #include "SpellInfo.h"
#include "Stances.h" #include "Stances.h"
#include "TargetedMovementGenerator.h"
#include "Timer.h" #include "Timer.h"
#include "Transport.h"
#include "Unit.h" #include "Unit.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "WaypointMovementGenerator.h" #include "WaypointMovementGenerator.h"
@@ -64,14 +67,18 @@ bool MovementAction::JumpTo(uint32 mapId, float x, float y, float z, MovementPri
{ {
UpdateMovementState(); UpdateMovementState();
if (!IsMovingAllowed(mapId, x, y, z)) if (!IsMovingAllowed(mapId, x, y, z))
{
return false; return false;
}
if (IsDuplicateMove(mapId, x, y, z)) if (IsDuplicateMove(mapId, x, y, z))
{
return false; return false;
}
if (IsWaitingForLastMove(priority)) if (IsWaitingForLastMove(priority))
{
return false; return false;
}
float botZ = bot->GetPositionZ();
float speed = bot->GetSpeed(MOVE_RUN); float speed = bot->GetSpeed(MOVE_RUN);
MotionMaster& mm = *bot->GetMotionMaster(); MotionMaster& mm = *bot->GetMotionMaster();
mm.Clear(); mm.Clear();
@@ -363,7 +370,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// { // {
// movePosition = endPosition; // movePosition = endPosition;
// if (startPosition.GetMapId() != endPosition.GetMapId() || totalDistance > maxDist) // if (startPosition.getMapId() != endPosition.getMapId() || totalDistance > maxDist)
// { // {
// if (!TravelNodeMap::instance().getNodes().empty() && !bot->InBattleground()) // if (!TravelNodeMap::instance().getNodes().empty() && !bot->InBattleground())
// { // {
@@ -414,7 +421,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// { // {
// //Use standard PathGenerator to find a route. // //Use standard PathGenerator to find a route.
// PathGenerator path(mover); // PathGenerator path(mover);
// path.CalculatePath(movePosition.GetPositionX(), movePosition.GetPositionY(), movePosition.GetPositionZ(), false); // path.CalculatePath(movePosition.getX(), movePosition.getY(), movePosition.getZ(), false);
// PathType type = path.GetPathType(); // PathType type = path.GetPathType();
// Movement::PointsArray const& points = path.GetPath(); // Movement::PointsArray const& points = path.GetPath();
// movePath.addPath(startPosition.fromPointsArray(points)); // movePath.addPath(startPosition.fromPointsArray(points));
@@ -478,8 +485,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// else // else
// { // {
// LOG_DEBUG("playerbots", "!entry"); // LOG_DEBUG("playerbots", "!entry");
// return bot->TeleportTo(movePosition.GetMapId(), movePosition.GetPositionX(), movePosition.GetPositionY(), // return bot->TeleportTo(movePosition.getMapId(), movePosition.getX(), movePosition.getY(),
// movePosition.GetPositionZ(), movePosition.GetOrientation(), 0); // movePosition.getZ(), movePosition.getO(), 0);
// } // }
// } // }
@@ -556,14 +563,14 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// AI_VALUE(LastMovement&, "last movement").setPath(movePath); // AI_VALUE(LastMovement&, "last movement").setPath(movePath);
// if (!movePosition || movePosition.GetMapId() != bot->GetMapId()) // if (!movePosition || movePosition.getMapId() != bot->GetMapId())
// { // {
// movePath.clear(); // movePath.clear();
// AI_VALUE(LastMovement&, "last movement").setPath(movePath); // AI_VALUE(LastMovement&, "last movement").setPath(movePath);
// if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT)) // if (botAI->HasStrategy("debug move", BOT_STATE_NON_COMBAT))
// botAI->TellMasterNoFacing("No point. Rebuilding."); // botAI->TellMasterNoFacing("No point. Rebuilding.");
// LOG_DEBUG("playerbots", "!movePosition || movePosition.GetMapId() != bot->GetMapId()"); // LOG_DEBUG("playerbots", "!movePosition || movePosition.getMapId() != bot->GetMapId()");
// return false; // return false;
// } // }
@@ -602,15 +609,15 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// float cz = z; // float cz = z;
// for (auto i : movePath.getPath()) // for (auto i : movePath.getPath())
// { // {
// CreateWp(bot, i.point.GetPositionX(), i.point.GetPositionY(), i.point.GetPositionZ(), 0.f, 2334); // CreateWp(bot, i.point.getX(), i.point.getY(), i.point.getZ(), 0.f, 2334);
// cx = i.point.GetPositionX(); // cx = i.point.getX();
// cy = i.point.GetPositionY(); // cy = i.point.getY();
// cz = i.point.GetPositionZ(); // cz = i.point.getZ();
// } // }
// } // }
// else // else
// CreateWp(bot, movePosition.GetPositionX(), movePosition.GetPositionY(), movePosition.GetPositionZ(), 0, 2334, true); // CreateWp(bot, movePosition.getX(), movePosition.getY(), movePosition.getZ(), 0, 2334, true);
// } // }
// //Log bot movement // //Log bot movement
@@ -627,8 +634,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// sPlayerbotAIConfig.log("bot_movement.csv", out.str().c_str()); // sPlayerbotAIConfig.log("bot_movement.csv", out.str().c_str());
// } // }
// // LOG_DEBUG("playerbots", "({}, {}) -> ({}, {})", startPosition.GetPositionX(), startPosition.GetPositionY(), // // LOG_DEBUG("playerbots", "({}, {}) -> ({}, {})", startPosition.getX(), startPosition.getY(),
// movePosition.GetPositionX(), movePosition.GetPositionY()); if (!react) // movePosition.getX(), movePosition.getY()); if (!react)
// if (totalDistance > maxDist) // if (totalDistance > maxDist)
// WaitForReach(startPosition.distance(movePosition) - 10.0f); // WaitForReach(startPosition.distance(movePosition) - 10.0f);
// else // else
@@ -664,7 +671,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// // else // // else
// // { // // {
// // mover->GetMotionMaster()->GetDestination(x, y, z); // // mover->GetMotionMaster()->GetDestination(x, y, z);
// // if (movePosition.distance(WorldPosition(movePosition.GetMapId(), x, y, z, 0)) > minDist) // // if (movePosition.distance(WorldPosition(movePosition.getMapId(), x, y, z, 0)) > minDist)
// // { // // {
// // mover->StopMoving(); // // mover->StopMoving();
// // mover->GetMotionMaster()->Clear(); // // mover->GetMotionMaster()->Clear();
@@ -678,8 +685,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// AI_VALUE(LastMovement&, "last movement").nextTeleport = now + // AI_VALUE(LastMovement&, "last movement").nextTeleport = now +
// (time_t)MoveDelay(startPosition.distance(movePosition)); LOG_DEBUG("playerbots", "totalDistance > maxDist && // (time_t)MoveDelay(startPosition.distance(movePosition)); LOG_DEBUG("playerbots", "totalDistance > maxDist &&
// !detailedMove && !botAI->HasPlayerNearby(&movePosition)"); return bot->TeleportTo(movePosition.GetMapId(), // !detailedMove && !botAI->HasPlayerNearby(&movePosition)"); return bot->TeleportTo(movePosition.getMapId(),
// movePosition.GetPositionX(), movePosition.GetPositionY(), movePosition.GetPositionZ(), startPosition.getAngleTo(movePosition)); // movePosition.getX(), movePosition.getY(), movePosition.getZ(), startPosition.getAngleTo(movePosition));
// } // }
// // walk if master walks and is close // // walk if master walks and is close
@@ -701,9 +708,9 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// if (!bot->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !bot->HasAuraType(SPELL_AURA_FLY)) // if (!bot->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !bot->HasAuraType(SPELL_AURA_FLY))
// { // {
// bot->SetWalk(masterWalking); // bot->SetWalk(masterWalking);
// bot->GetMotionMaster()->MovePoint(movePosition.GetMapId(), movePosition.GetPositionX(), movePosition.GetPositionY(), // bot->GetMotionMaster()->MovePoint(movePosition.getMapId(), movePosition.getX(), movePosition.getY(),
// movePosition.GetPositionZ(), generatePath); WaitForReach(startPosition.distance(movePosition)); // movePosition.getZ(), generatePath); WaitForReach(startPosition.distance(movePosition));
// // LOG_DEBUG("playerbots", "Movepoint to ({}, {})", movePosition.GetPositionX(), movePosition.GetPositionY()); // // LOG_DEBUG("playerbots", "Movepoint to ({}, {})", movePosition.getX(), movePosition.getY());
// } // }
// else // else
// { // {
@@ -749,9 +756,9 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// } // }
// } // }
// bot->GetMotionMaster()->MovePoint(movePosition.GetMapId(), Position(movePosition.GetPositionX(), movePosition.GetPositionY(), // bot->GetMotionMaster()->MovePoint(movePosition.getMapId(), Position(movePosition.getX(), movePosition.getY(),
// movePosition.GetPositionZ(), 0.f)); WaitForReach(startPosition.distance(movePosition)); LOG_DEBUG("playerbots", // movePosition.getZ(), 0.f)); WaitForReach(startPosition.distance(movePosition)); LOG_DEBUG("playerbots",
// "Movepoint to ({}, {})", movePosition.GetPositionX(), movePosition.GetPositionY()); // "Movepoint to ({}, {})", movePosition.getX(), movePosition.getY());
// } // }
// AI_VALUE(LastMovement&, "last movement").setShort(movePosition); // AI_VALUE(LastMovement&, "last movement").setShort(movePosition);
@@ -947,69 +954,67 @@ bool MovementAction::Follow(Unit* target, float distance) { return Follow(target
void MovementAction::UpdateMovementState() void MovementAction::UpdateMovementState()
{ {
const bool isCurrentlyRestricted = // see if the bot is currently slowed, rooted, or otherwise unable to move const bool isCurrentlyRestricted = // see if the bot is currently slowed, rooted, or otherwise unable to move
bot->HasUnitState(UNIT_STATE_LOST_CONTROL) || bot->IsRooted() || bot->isFrozen() || bot->IsPolymorphed(); bot->HasUnitState(UNIT_STATE_LOST_CONTROL) ||
bot->IsRooted() ||
bot->isFrozen() ||
bot->IsPolymorphed();
// no update movement flags while movement is current restricted. // no update movement flags while movement is current restricted.
if (!isCurrentlyRestricted && bot->IsAlive()) if (!isCurrentlyRestricted && bot->IsAlive())
{ {
// state flags // state flags
const auto master = botAI ? botAI->GetMaster() : nullptr; const auto master = botAI ? botAI->GetMaster() : nullptr; // real player or not
const auto liquidState = bot->GetLiquidData().Status; const bool masterIsFlying = master ? master->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) : true;
const bool masterIsSwimming = master ? master->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING) : true;
const auto liquidState = bot->GetLiquidData().Status; // default LIQUID_MAP_NO_WATER
const float gZ = bot->GetMapWaterOrGroundLevel(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()); const float gZ = bot->GetMapWaterOrGroundLevel(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ());
const bool onGroundZ = bot->GetPositionZ() < gZ + 1.f; const bool wantsToFly = bot->HasIncreaseMountedFlightSpeedAura() || bot->HasFlyAura();
const bool canSwim = liquidState == LIQUID_MAP_IN_WATER || liquidState == LIQUID_MAP_UNDER_WATER;
const bool canFly = bot->HasIncreaseMountedFlightSpeedAura() || bot->HasFlyAura();
const bool canWaterWalk = bot->HasWaterWalkAura();
const bool isMasterFlying = master ? master->HasUnitMovementFlag(MOVEMENTFLAG_FLYING) : true;
const bool isMasterSwimming = master ? master->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING) : true;
const bool isFlying = bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING); const bool isFlying = bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING);
const bool isSwimming = bot->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING); const bool isWaterArea = liquidState != LIQUID_MAP_NO_WATER;
const bool isUnderWater = liquidState == LIQUID_MAP_UNDER_WATER;
const bool isInWater = liquidState == LIQUID_MAP_IN_WATER;
const bool isWaterWalking = bot->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); const bool isWaterWalking = bot->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
const bool isSwimming = bot->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
const bool wantsToWaterWalk = bot->HasWaterWalkAura();
const bool wantsToSwim = isInWater || isUnderWater;
const bool onGroundZ = (bot->GetPositionZ() < gZ + 1.f) && !isWaterArea;
bool movementFlagsUpdated = false; bool movementFlagsUpdated = false;
// handle water (fragile logic do not alter without testing every detail, animation and transition) // handle water state
if (liquidState != LIQUID_MAP_NO_WATER && !isFlying) if (isWaterArea && !isFlying)
{ {
if (canWaterWalk && !isMasterSwimming && !isWaterWalking) // water walking
if (wantsToWaterWalk && !isWaterWalking && !masterIsSwimming)
{ {
bot->SetSwim(false); bot->RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
bot->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); bot->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
movementFlagsUpdated = true; movementFlagsUpdated = true;
} }
else if ((!canWaterWalk || isMasterSwimming) && isWaterWalking) // swimming
else if (wantsToSwim && !isSwimming && masterIsSwimming)
{ {
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); bot->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
if (canSwim) bot->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
bot->SetSwim(true);
movementFlagsUpdated = true;
}
else if (!canSwim && isSwimming)
{
bot->SetSwim(false);
movementFlagsUpdated = true; movementFlagsUpdated = true;
} }
} }
else if (isSwimming || isWaterWalking)
// reset when not around water while swimming or water walking
if (liquidState == LIQUID_MAP_NO_WATER && (isSwimming || isWaterWalking))
{ {
bot->SetSwim(false); // reset water flags
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); bot->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
movementFlagsUpdated = true; movementFlagsUpdated = true;
} }
// handle flying // handle flying state
if ((canFly && !isFlying) && isMasterFlying) if (wantsToFly && !isFlying && masterIsFlying)
{ {
bot->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); bot->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
bot->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); bot->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
bot->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); bot->AddUnitMovementFlag(MOVEMENTFLAG_FLYING);
movementFlagsUpdated = true;
// required for transition and state monitoring.
if (MotionMaster* mm = bot->GetMotionMaster())
mm->MoveTakeoff(0, {bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ() + 1.F}, 0.F, true);
} }
else if ((!canFly && !isWaterWalking && isFlying) || (!isMasterFlying && isFlying && onGroundZ)) else if ((!wantsToFly || onGroundZ) && isFlying)
{ {
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); bot->RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY);
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); bot->RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
@@ -1017,11 +1022,10 @@ void MovementAction::UpdateMovementState()
movementFlagsUpdated = true; movementFlagsUpdated = true;
} }
// detect if movement/CC restrictions have been ended, refresh movement state for animations. // detect if movement restrictions have been lifted, CC just ended.
if (wasMovementRestricted) if (wasMovementRestricted)
movementFlagsUpdated = true; movementFlagsUpdated = true; // refresh movement state to ensure animations play correctly
// movement flags should only be updated between state changes, if not it will break certain effects.
if (movementFlagsUpdated) if (movementFlagsUpdated)
bot->SendMovementFlagUpdate(); bot->SendMovementFlagUpdate();
} }
@@ -1186,7 +1190,7 @@ bool MovementAction::Follow(Unit* target, float distance, float angle)
WorldPosition cPos(corpse); WorldPosition cPos(corpse);
if (botPos.fDist(cPos) > sPlayerbotAIConfig.spellDistance) if (botPos.fDist(cPos) > sPlayerbotAIConfig.spellDistance)
return MoveTo(cPos.GetMapId(), cPos.GetPositionX(), cPos.GetPositionY(), cPos.GetPositionZ()); return MoveTo(cPos.getMapId(), cPos.getX(), cPos.getY(), cPos.getZ());
} }
} }
@@ -1213,7 +1217,7 @@ bool MovementAction::Follow(Unit* target, float distance, float angle)
if ((lDist * 1.5 < tDist && ang < static_cast<float>(M_PI) / 2) || if ((lDist * 1.5 < tDist && ang < static_cast<float>(M_PI) / 2) ||
target->HasUnitState(UNIT_STATE_IN_FLIGHT)) target->HasUnitState(UNIT_STATE_IN_FLIGHT))
{ {
return MoveTo(longMove.GetMapId(), longMove.GetPositionX(), longMove.GetPositionY(), longMove.GetPositionZ()); return MoveTo(longMove.getMapId(), longMove.getX(), longMove.getY(), longMove.getZ());
} }
} }
} }
@@ -1809,11 +1813,12 @@ void MovementAction::DoMovePoint(Unit* unit, float x, float y, float z, bool gen
if (!mm) if (!mm)
return; return;
// bot water collision correction // enable water walking
if (unit->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING) && unit->HasWaterWalkAura()) if (unit->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING))
{ {
float gZ = unit->GetMapWaterOrGroundLevel(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ()); float gZ = unit->GetMapWaterOrGroundLevel(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ());
unit->UpdatePosition(unit->GetPositionX(), unit->GetPositionY(), gZ, false); unit->UpdatePosition(unit->GetPositionX(), unit->GetPositionY(), gZ, false);
// z = gZ; no overwrite Z axe otherwise you cant steer the bots into swimming when water walking.
} }
mm->Clear(); mm->Clear();
@@ -1839,7 +1844,7 @@ void MovementAction::DoMovePoint(Unit* unit, float x, float y, float z, bool gen
} }
} }
bool FleeAction::Execute(Event /*event*/) bool FleeAction::Execute(Event event)
{ {
return MoveAway(AI_VALUE(Unit*, "current target"), sPlayerbotAIConfig.fleeDistance, true); return MoveAway(AI_VALUE(Unit*, "current target"), sPlayerbotAIConfig.fleeDistance, true);
} }
@@ -1847,8 +1852,9 @@ bool FleeAction::Execute(Event /*event*/)
bool FleeAction::isUseful() bool FleeAction::isUseful()
{ {
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr)
{
return false; return false;
}
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
if (target && target->IsInWorld() && !bot->IsWithinMeleeRange(target)) if (target && target->IsInWorld() && !bot->IsWithinMeleeRange(target))
return false; return false;
@@ -1856,10 +1862,12 @@ bool FleeAction::isUseful()
return true; return true;
} }
bool FleeWithPetAction::Execute(Event /*event*/) bool FleeWithPetAction::Execute(Event event)
{ {
if (Pet* pet = bot->GetPet()) if (Pet* pet = bot->GetPet())
{
botAI->PetFollow(); botAI->PetFollow();
}
return Flee(AI_VALUE(Unit*, "current target")); return Flee(AI_VALUE(Unit*, "current target"));
} }
@@ -1867,14 +1875,15 @@ bool FleeWithPetAction::Execute(Event /*event*/)
bool AvoidAoeAction::isUseful() bool AvoidAoeAction::isUseful()
{ {
if (getMSTime() - moveInterval < lastMoveTimer) if (getMSTime() - moveInterval < lastMoveTimer)
{
return false; return false;
}
GuidVector traps = AI_VALUE(GuidVector, "nearest trap with damage"); GuidVector traps = AI_VALUE(GuidVector, "nearest trap with damage");
GuidVector triggers = AI_VALUE(GuidVector, "possible triggers"); GuidVector triggers = AI_VALUE(GuidVector, "possible triggers");
return AI_VALUE(Aura*, "area debuff") || !traps.empty() || !triggers.empty(); return AI_VALUE(Aura*, "area debuff") || !traps.empty() || !triggers.empty();
} }
bool AvoidAoeAction::Execute(Event /*event*/) bool AvoidAoeAction::Execute(Event event)
{ {
// Case #1: Aura with dynamic object (e.g. rain of fire) // Case #1: Aura with dynamic object (e.g. rain of fire)
if (AvoidAuraWithDynamicObj()) if (AvoidAuraWithDynamicObj())
@@ -2298,15 +2307,17 @@ bool MovementAction::CheckLastFlee(float curAngle, std::list<FleeInfo>& infoList
bool CombatFormationMoveAction::isUseful() bool CombatFormationMoveAction::isUseful()
{ {
if (getMSTime() - moveInterval < lastMoveTimer) if (getMSTime() - moveInterval < lastMoveTimer)
{
return false; return false;
}
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr)
{
return false; return false;
}
return true; return true;
} }
bool CombatFormationMoveAction::Execute(Event /*event*/) bool CombatFormationMoveAction::Execute(Event event)
{ {
float dis = AI_VALUE(float, "disperse distance"); float dis = AI_VALUE(float, "disperse distance");
if (dis <= 0.0f || (!bot->IsInCombat() && botAI->HasStrategy("stay", BotState::BOT_STATE_NON_COMBAT)) || if (dis <= 0.0f || (!bot->IsInCombat() && botAI->HasStrategy("stay", BotState::BOT_STATE_NON_COMBAT)) ||
@@ -2437,7 +2448,7 @@ Player* CombatFormationMoveAction::NearestGroupMember(float dis)
return result; return result;
} }
bool TankFaceAction::Execute(Event /*event*/) bool TankFaceAction::Execute(Event event)
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
if (!target) if (!target)
@@ -2521,7 +2532,7 @@ bool RearFlankAction::isUseful()
return inFront || inRear; return inFront || inRear;
} }
bool RearFlankAction::Execute(Event /*event*/) bool RearFlankAction::Execute(Event event)
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
if (!target) if (!target)
@@ -2632,9 +2643,9 @@ bool DisperseSetAction::Execute(Event event)
return true; return true;
} }
bool RunAwayAction::Execute(Event /*event*/) { return Flee(AI_VALUE(Unit*, "group leader")); } bool RunAwayAction::Execute(Event event) { return Flee(AI_VALUE(Unit*, "group leader")); }
bool MoveToLootAction::Execute(Event /*event*/) bool MoveToLootAction::Execute(Event event)
{ {
LootObject loot = AI_VALUE(LootObject, "loot target"); LootObject loot = AI_VALUE(LootObject, "loot target");
if (!loot.IsLootPossible(bot)) if (!loot.IsLootPossible(bot))
@@ -2643,7 +2654,7 @@ bool MoveToLootAction::Execute(Event /*event*/)
return MoveNear(loot.GetWorldObject(bot), sPlayerbotAIConfig.contactDistance); return MoveNear(loot.GetWorldObject(bot), sPlayerbotAIConfig.contactDistance);
} }
bool MoveOutOfEnemyContactAction::Execute(Event /*event*/) bool MoveOutOfEnemyContactAction::Execute(Event event)
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
if (!target) if (!target)
@@ -2654,7 +2665,7 @@ bool MoveOutOfEnemyContactAction::Execute(Event /*event*/)
bool MoveOutOfEnemyContactAction::isUseful() { return AI_VALUE2(bool, "inside target", "current target"); } bool MoveOutOfEnemyContactAction::isUseful() { return AI_VALUE2(bool, "inside target", "current target"); }
bool SetFacingTargetAction::Execute(Event /*event*/) bool SetFacingTargetAction::Execute(Event event)
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
if (!target) if (!target)
@@ -2680,7 +2691,7 @@ bool SetFacingTargetAction::isPossible()
return true; return true;
} }
bool SetBehindTargetAction::Execute(Event /*event*/) bool SetBehindTargetAction::Execute(Event event)
{ {
Unit* target = AI_VALUE(Unit*, "current target"); Unit* target = AI_VALUE(Unit*, "current target");
if (!target) if (!target)
@@ -2740,7 +2751,7 @@ bool SetBehindTargetAction::Execute(Event /*event*/)
false, true, MovementPriority::MOVEMENT_COMBAT); false, true, MovementPriority::MOVEMENT_COMBAT);
} }
bool MoveOutOfCollisionAction::Execute(Event /*event*/) bool MoveOutOfCollisionAction::Execute(Event event)
{ {
float angle = M_PI * 2000 / frand(1.f, 1000.f); float angle = M_PI * 2000 / frand(1.f, 1000.f);
float distance = sPlayerbotAIConfig.followDistance; float distance = sPlayerbotAIConfig.followDistance;
@@ -2758,7 +2769,7 @@ bool MoveOutOfCollisionAction::isUseful()
botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest friendly players")->Get().size() < 15; botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest friendly players")->Get().size() < 15;
} }
bool MoveRandomAction::Execute(Event /*event*/) bool MoveRandomAction::Execute(Event event)
{ {
float distance = sPlayerbotAIConfig.tooCloseDistance + urand(10, 30); float distance = sPlayerbotAIConfig.tooCloseDistance + urand(10, 30);
@@ -2790,9 +2801,9 @@ bool MoveRandomAction::Execute(Event /*event*/)
bool MoveRandomAction::isUseful() { return !AI_VALUE(GuidPosition, "rpg target"); } bool MoveRandomAction::isUseful() { return !AI_VALUE(GuidPosition, "rpg target"); }
bool MoveInsideAction::Execute(Event /*event*/) { return MoveInside(bot->GetMapId(), x, y, bot->GetPositionZ(), distance); } bool MoveInsideAction::Execute(Event event) { return MoveInside(bot->GetMapId(), x, y, bot->GetPositionZ(), distance); }
bool RotateAroundTheCenterPointAction::Execute(Event /*event*/) bool RotateAroundTheCenterPointAction::Execute(Event event)
{ {
uint32 next_point = GetCurrWaypoint(); uint32 next_point = GetCurrWaypoint();
if (MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ(), false, if (MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ(), false,
@@ -2812,9 +2823,10 @@ bool MoveFromGroupAction::Execute(Event event)
return MoveFromGroup(distance); return MoveFromGroup(distance);
} }
bool MoveAwayFromCreatureAction::Execute(Event /*event*/) bool MoveAwayFromCreatureAction::Execute(Event event)
{ {
GuidVector targets = AI_VALUE(GuidVector, "nearest npcs"); GuidVector targets = AI_VALUE(GuidVector, "nearest npcs");
Creature* nearestCreature = bot->FindNearestCreature(creatureId, range, alive);
// Find all creatures with the specified Id // Find all creatures with the specified Id
std::vector<Unit*> creatures; std::vector<Unit*> creatures;
@@ -2892,14 +2904,16 @@ bool MoveAwayFromCreatureAction::Execute(Event /*event*/)
bool MoveAwayFromCreatureAction::isPossible() { return bot->CanFreeMove(); } bool MoveAwayFromCreatureAction::isPossible() { return bot->CanFreeMove(); }
bool MoveAwayFromPlayerWithDebuffAction::Execute(Event /*event*/) bool MoveAwayFromPlayerWithDebuffAction::Execute(Event event)
{ {
Player* closestPlayer = nullptr; Player* closestPlayer = nullptr;
float minDistance = 0.0f; float minDistance = 0.0f;
Group* group = bot->GetGroup(); Group* group = bot->GetGroup();
if (!group) if (!group)
{
return false; return false;
}
std::vector<Player*> debuffedPlayers; std::vector<Player*> debuffedPlayers;

View File

@@ -49,15 +49,17 @@ bool DrinkAction::Execute(Event event)
bool DrinkAction::isUseful() bool DrinkAction::isUseful()
{ {
return UseItemAction::isUseful() && AI_VALUE2(bool, "has mana", "self target") && return UseItemAction::isUseful() &&
AI_VALUE2(bool, "has mana", "self target") &&
AI_VALUE2(uint8, "mana", "self target") < 100; AI_VALUE2(uint8, "mana", "self target") < 100;
} }
bool DrinkAction::isPossible() bool DrinkAction::isPossible()
{ {
return !bot->IsInCombat() && !bot->IsMounted() && return !bot->IsInCombat() &&
!botAI->HasAnyAuraOf(GetTarget(), "dire bear form", "bear form", "cat form", "travel form", "aquatic form", !bot->IsMounted() &&
"flight form", "swift flight form", nullptr) && !botAI->HasAnyAuraOf(GetTarget(), "dire bear form", "bear form", "cat form", "travel form",
"aquatic form","flight form", "swift flight form", nullptr) &&
(botAI->HasCheat(BotCheatMask::food) || UseItemAction::isPossible()); (botAI->HasCheat(BotCheatMask::food) || UseItemAction::isPossible());
} }
@@ -100,12 +102,17 @@ bool EatAction::Execute(Event event)
return UseItemAction::Execute(event); return UseItemAction::Execute(event);
} }
bool EatAction::isUseful() { return UseItemAction::isUseful() && AI_VALUE2(uint8, "health", "self target") < 100; } bool EatAction::isUseful()
{
return UseItemAction::isUseful() &&
AI_VALUE2(uint8, "health", "self target") < 100;
}
bool EatAction::isPossible() bool EatAction::isPossible()
{ {
return !bot->IsInCombat() && !bot->IsMounted() && return !bot->IsInCombat() &&
!botAI->HasAnyAuraOf(GetTarget(), "dire bear form", "bear form", "cat form", "travel form", "aquatic form", !bot->IsMounted() &&
"flight form", "swift flight form", nullptr) && !botAI->HasAnyAuraOf(GetTarget(), "dire bear form", "bear form", "cat form", "travel form",
"aquatic form","flight form", "swift flight form", nullptr) &&
(botAI->HasCheat(BotCheatMask::food) || UseItemAction::isPossible()); (botAI->HasCheat(BotCheatMask::food) || UseItemAction::isPossible());
} }

View File

@@ -7,7 +7,7 @@
#include "LootObjectStack.h" #include "LootObjectStack.h"
#include "AiObjectContext.h" #include "AiObjectContext.h"
bool OpenItemAction::Execute(Event /*event*/) bool OpenItemAction::Execute(Event event)
{ {
bool foundOpenable = false; bool foundOpenable = false;

View File

@@ -7,9 +7,10 @@
#include "Event.h" #include "Event.h"
#include "PlayerbotOperations.h" #include "PlayerbotOperations.h"
#include "Playerbots.h"
#include "PlayerbotWorldThreadProcessor.h" #include "PlayerbotWorldThreadProcessor.h"
bool PassLeadershipToMasterAction::Execute(Event /*event*/) bool PassLeadershipToMasterAction::Execute(Event event)
{ {
if (Player* master = GetMaster()) if (Player* master = GetMaster())
if (master && master != bot && bot->GetGroup() && bot->GetGroup()->IsMember(master->GetGUID())) if (master && master != bot && bot->GetGroup() && bot->GetGroup()->IsMember(master->GetGUID()))

View File

@@ -9,6 +9,8 @@
#include <string> #include <string>
#include "Action.h" #include "Action.h"
#include "PlayerbotFactory.h"
#include "Unit.h"
class PlayerbotAI; class PlayerbotAI;

View File

@@ -102,7 +102,7 @@ bool PositionAction::Execute(Event event)
return false; return false;
} }
bool MoveToPositionAction::Execute(Event /*event*/) bool MoveToPositionAction::Execute(Event event)
{ {
PositionInfo pos = context->GetValue<PositionMap&>("position")->Get()[qualifier]; PositionInfo pos = context->GetValue<PositionMap&>("position")->Get()[qualifier];
if (!pos.isSet()) if (!pos.isSet())
@@ -123,7 +123,7 @@ bool MoveToPositionAction::isUseful()
return pos.isSet() && distance > sPlayerbotAIConfig.followDistance && distance < sPlayerbotAIConfig.reactDistance; return pos.isSet() && distance > sPlayerbotAIConfig.followDistance && distance < sPlayerbotAIConfig.reactDistance;
} }
bool SetReturnPositionAction::Execute(Event /*event*/) bool SetReturnPositionAction::Execute(Event event)
{ {
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get(); PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
PositionInfo returnPos = posMap["return"]; PositionInfo returnPos = posMap["return"];

View File

@@ -7,7 +7,7 @@
#include "ChatHelper.h" #include "ChatHelper.h"
#include "Event.h" #include "Event.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
void QueryQuestAction::TellObjective(std::string const name, uint32 available, uint32 required) void QueryQuestAction::TellObjective(std::string const name, uint32 available, uint32 required)
{ {

View File

@@ -5,7 +5,6 @@
#include "QuestAction.h" #include "QuestAction.h"
#include <sstream> #include <sstream>
#include <algorithm>
#include "Chat.h" #include "Chat.h"
#include "ChatHelper.h" #include "ChatHelper.h"
@@ -117,8 +116,7 @@ bool QuestAction::CompleteQuest(Player* player, uint32 entry)
player->CastedCreatureOrGO(creature, ObjectGuid(), spell_id); player->CastedCreatureOrGO(creature, ObjectGuid(), spell_id);
} }
}*/ }*/
/*else*/ /*else*/ if (creature > 0)
if (creature > 0)
{ {
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature)) if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature))
for (uint16 z = 0; z < creaturecount; ++z) for (uint16 z = 0; z < creaturecount; ++z)
@@ -434,7 +432,7 @@ bool QuestItemPushResultAction::Execute(Event event)
return false; return false;
} }
bool QuestUpdateFailedAction::Execute(Event /*event*/) bool QuestUpdateFailedAction::Execute(Event event)
{ {
//opcode SMSG_QUESTUPDATE_FAILED is never sent...(yet?) //opcode SMSG_QUESTUPDATE_FAILED is never sent...(yet?)
return false; return false;

View File

@@ -8,7 +8,7 @@
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
bool RandomBotUpdateAction::Execute(Event /*event*/) bool RandomBotUpdateAction::Execute(Event event)
{ {
if (!sRandomPlayerbotMgr.IsRandomBot(bot)) if (!sRandomPlayerbotMgr.IsRandomBot(bot))
return false; return false;

View File

@@ -10,7 +10,7 @@
#include "Playerbots.h" #include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
bool ReachTargetAction::Execute(Event /*event*/) { return ReachCombatTo(AI_VALUE(Unit*, GetTargetName()), distance); } bool ReachTargetAction::Execute(Event event) { return ReachCombatTo(AI_VALUE(Unit*, GetTargetName()), distance); }
bool ReachTargetAction::isUseful() bool ReachTargetAction::isUseful()
{ {

View File

@@ -78,7 +78,7 @@ void ReleaseSpiritAction::LogRelease(const std::string& releaseMsg, bool isAutoR
} }
// AutoReleaseSpiritAction implementation // AutoReleaseSpiritAction implementation
bool AutoReleaseSpiritAction::Execute(Event /*event*/) bool AutoReleaseSpiritAction::Execute(Event event)
{ {
IncrementDeathCount(); IncrementDeathCount();
bot->DurabilityRepairAll(false, 1.0f, false); bot->DurabilityRepairAll(false, 1.0f, false);
@@ -214,7 +214,7 @@ bool AutoReleaseSpiritAction::ShouldDelayBattlegroundRelease() const
return true; return true;
} }
bool RepopAction::Execute(Event /*event*/) bool RepopAction::Execute(Event event)
{ {
const GraveyardStruct* graveyard = GetGrave( const GraveyardStruct* graveyard = GetGrave(
AI_VALUE(uint32, "death count") > 10 || AI_VALUE(uint32, "death count") > 10 ||
@@ -250,7 +250,7 @@ void RepopAction::PerformGraveyardTeleport(const GraveyardStruct* graveyard) con
} }
// SelfResurrectAction implementation for Warlock's Soulstone Resurrection/Shaman's Reincarnation // SelfResurrectAction implementation for Warlock's Soulstone Resurrection/Shaman's Reincarnation
bool SelfResurrectAction::Execute(Event /*event*/) bool SelfResurrectAction::Execute(Event event)
{ {
if (!bot->IsAlive() && bot->GetUInt32Value(PLAYER_SELF_RES_SPELL)) if (!bot->IsAlive() && bot->GetUInt32Value(PLAYER_SELF_RES_SPELL))
{ {

View File

@@ -7,7 +7,7 @@
#include "Event.h" #include "Event.h"
#include "LastMovementValue.h" #include "LastMovementValue.h"
#include "AiObjectContext.h" #include "Playerbots.h"
bool RememberTaxiAction::Execute(Event event) bool RememberTaxiAction::Execute(Event event)
{ {

View File

@@ -9,7 +9,7 @@
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
bool RepairAllAction::Execute(Event /*event*/) bool RepairAllAction::Execute(Event event)
{ {
GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs"); GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs");
for (ObjectGuid const guid : npcs) for (ObjectGuid const guid : npcs)

View File

@@ -5,13 +5,14 @@
#include "ResetInstancesAction.h" #include "ResetInstancesAction.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
bool ResetInstancesAction::Execute(Event /*event*/) bool ResetInstancesAction::Execute(Event event)
{ {
WorldPacket packet(CMSG_RESET_INSTANCES, 0); WorldPacket packet(CMSG_RESET_INSTANCES, 0);
bot->GetSession()->HandleResetInstancesOpcode(packet); bot->GetSession()->HandleResetInstancesOpcode(packet);
botAI->TellMaster("Resetting all instances");
return true; return true;
} }

View File

@@ -10,11 +10,11 @@
#include "Event.h" #include "Event.h"
#include "GridNotifiers.h" #include "GridNotifiers.h"
#include "GridNotifiersImpl.h" #include "GridNotifiersImpl.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
#include "NearestGameObjects.h" #include "NearestGameObjects.h"
bool RevealGatheringItemAction::Execute(Event /*event*/) bool RevealGatheringItemAction::Execute(Event event)
{ {
if (!bot->GetGroup()) if (!bot->GetGroup())
return false; return false;

View File

@@ -9,6 +9,7 @@
#include "FleeManager.h" #include "FleeManager.h"
#include "GameGraveyard.h" #include "GameGraveyard.h"
#include "MapMgr.h" #include "MapMgr.h"
#include "PlayerbotFactory.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "RandomPlayerbotMgr.h" #include "RandomPlayerbotMgr.h"
#include "ServerFacade.h" #include "ServerFacade.h"
@@ -73,7 +74,7 @@ bool ReviveFromCorpseAction::Execute(Event event)
return true; return true;
} }
bool FindCorpseAction::Execute(Event /*event*/) bool FindCorpseAction::Execute(Event event)
{ {
if (bot->InBattleground()) if (bot->InBattleground())
return false; return false;
@@ -149,7 +150,7 @@ bool FindCorpseAction::Execute(Event /*event*/)
{ {
float rx, ry, rz; float rx, ry, rz;
if (manager.CalculateDestination(&rx, &ry, &rz)) if (manager.CalculateDestination(&rx, &ry, &rz))
moveToPos = WorldPosition(moveToPos.GetMapId(), rx, ry, rz, 0.0); moveToPos = WorldPosition(moveToPos.getMapId(), rx, ry, rz, 0.0);
else if (!moveToPos.GetReachableRandomPointOnGround(bot, reclaimDist, urand(0, 1))) else if (!moveToPos.GetReachableRandomPointOnGround(bot, reclaimDist, urand(0, 1)))
moveToPos = corpsePos; moveToPos = corpsePos;
} }
@@ -169,7 +170,7 @@ bool FindCorpseAction::Execute(Event /*event*/)
{ {
bot->GetMotionMaster()->Clear(); bot->GetMotionMaster()->Clear();
bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP);
bot->TeleportTo(moveToPos.GetMapId(), moveToPos.GetPositionX(), moveToPos.GetPositionY(), moveToPos.GetPositionZ(), 0); bot->TeleportTo(moveToPos.getMapId(), moveToPos.getX(), moveToPos.getY(), moveToPos.getZ(), 0);
} }
moved = true; moved = true;
@@ -183,7 +184,7 @@ bool FindCorpseAction::Execute(Event /*event*/)
if (deadTime < 10 * MINUTE && dCount < 5) // Look for corpse up to 30 minutes. if (deadTime < 10 * MINUTE && dCount < 5) // Look for corpse up to 30 minutes.
{ {
moved = moved =
MoveTo(moveToPos.GetMapId(), moveToPos.GetPositionX(), moveToPos.GetPositionY(), moveToPos.GetPositionZ(), false, false); MoveTo(moveToPos.getMapId(), moveToPos.getX(), moveToPos.getY(), moveToPos.getZ(), false, false);
} }
if (!moved) if (!moved)
@@ -236,10 +237,10 @@ GraveyardStruct const* SpiritHealerAction::GetGrave(bool startZone)
{ {
uint32 areaId = 0; uint32 areaId = 0;
uint32 zoneId = 0; uint32 zoneId = 0;
sMapMgr->GetZoneAndAreaId(bot->GetPhaseMask(), zoneId, areaId, travelPos.GetMapId(), travelPos.GetPositionX(), sMapMgr->GetZoneAndAreaId(bot->GetPhaseMask(), zoneId, areaId, travelPos.getMapId(), travelPos.getX(),
travelPos.GetPositionY(), travelPos.GetPositionZ()); travelPos.getY(), travelPos.getZ());
ClosestGrave = sGraveyard->GetClosestGraveyard(travelPos.GetMapId(), travelPos.GetPositionX(), travelPos.GetPositionY(), ClosestGrave = sGraveyard->GetClosestGraveyard(travelPos.getMapId(), travelPos.getX(), travelPos.getY(),
travelPos.GetPositionZ(), bot->GetTeamId(), areaId, zoneId, travelPos.getZ(), bot->GetTeamId(), areaId, zoneId,
bot->getClass() == CLASS_DEATH_KNIGHT); bot->getClass() == CLASS_DEATH_KNIGHT);
if (ClosestGrave) if (ClosestGrave)
@@ -292,7 +293,7 @@ GraveyardStruct const* SpiritHealerAction::GetGrave(bool startZone)
return ClosestGrave; return ClosestGrave;
} }
bool SpiritHealerAction::Execute(Event /*event*/) bool SpiritHealerAction::Execute(Event event)
{ {
Corpse* corpse = bot->GetCorpse(); Corpse* corpse = bot->GetCorpse();
if (!corpse) if (!corpse)

View File

@@ -7,6 +7,7 @@
#include <random> #include <random>
#include "BattlegroundMgr.h"
#include "ChatHelper.h" #include "ChatHelper.h"
#include "EmoteAction.h" #include "EmoteAction.h"
#include "Event.h" #include "Event.h"
@@ -15,7 +16,7 @@
#include "ServerFacade.h" #include "ServerFacade.h"
#include "RpgSubActions.h" #include "RpgSubActions.h"
bool RpgAction::Execute(Event /*event*/) bool RpgAction::Execute(Event event)
{ {
GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target");
if (!guidP && botAI->GetMaster()) if (!guidP && botAI->GetMaster())
@@ -84,7 +85,7 @@ bool RpgAction::SetNextRpgAction()
isChecked = true; isChecked = true;
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction.getName()); Action* action = botAI->GetAiObjectContext()->GetAction(nextAction.getName());
if (!dynamic_cast<RpgEnabled*>(action) || !action->isUseful() || !action->isPossible()) if (!dynamic_cast<RpgEnabled*>(action) || !action->isPossible() || !action->isUseful())
continue; continue;
actions.push_back(action); actions.push_back(action);

View File

@@ -99,7 +99,7 @@ Event RpgSubAction::ActionEvent(Event event) { return event; }
bool RpgStayAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); } bool RpgStayAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); }
bool RpgStayAction::Execute(Event /*event*/) bool RpgStayAction::Execute(Event event)
{ {
bot->PlayerTalkClass->SendCloseGossip(); bot->PlayerTalkClass->SendCloseGossip();
@@ -109,7 +109,7 @@ bool RpgStayAction::Execute(Event /*event*/)
bool RpgWorkAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); } bool RpgWorkAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); }
bool RpgWorkAction::Execute(Event /*event*/) bool RpgWorkAction::Execute(Event event)
{ {
bot->HandleEmoteCommand(EMOTE_STATE_USE_STANDING); bot->HandleEmoteCommand(EMOTE_STATE_USE_STANDING);
rpg->AfterExecute(); rpg->AfterExecute();
@@ -118,7 +118,7 @@ bool RpgWorkAction::Execute(Event /*event*/)
bool RpgEmoteAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); } bool RpgEmoteAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); }
bool RpgEmoteAction::Execute(Event /*event*/) bool RpgEmoteAction::Execute(Event event)
{ {
uint32 type = TalkAction::GetRandomEmote(rpg->guidP().GetUnit()); uint32 type = TalkAction::GetRandomEmote(rpg->guidP().GetUnit());
@@ -133,7 +133,7 @@ bool RpgEmoteAction::Execute(Event /*event*/)
return true; return true;
} }
bool RpgCancelAction::Execute(Event /*event*/) bool RpgCancelAction::Execute(Event event)
{ {
RESET_AI_VALUE(GuidPosition, "rpg target"); RESET_AI_VALUE(GuidPosition, "rpg target");
rpg->OnExecute(""); rpg->OnExecute("");
@@ -142,7 +142,7 @@ bool RpgCancelAction::Execute(Event /*event*/)
bool RpgTaxiAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); } bool RpgTaxiAction::isUseful() { return rpg->InRange() && !botAI->HasRealPlayerMaster(); }
bool RpgTaxiAction::Execute(Event /*event*/) bool RpgTaxiAction::Execute(Event event)
{ {
GuidPosition guidP = rpg->guidP(); GuidPosition guidP = rpg->guidP();
@@ -150,7 +150,7 @@ bool RpgTaxiAction::Execute(Event /*event*/)
bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket); bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket);
uint32 node = uint32 node =
sObjectMgr->GetNearestTaxiNode(guidP.GetPositionX(), guidP.GetPositionY(), guidP.GetPositionZ(), guidP.GetMapId(), bot->GetTeamId()); sObjectMgr->GetNearestTaxiNode(guidP.getX(), guidP.getY(), guidP.getZ(), guidP.getMapId(), bot->GetTeamId());
std::vector<uint32> nodes; std::vector<uint32> nodes;
for (uint32 i = 0; i < sTaxiPathStore.GetNumRows(); ++i) for (uint32 i = 0; i < sTaxiPathStore.GetNumRows(); ++i)
@@ -203,12 +203,12 @@ bool RpgTaxiAction::Execute(Event /*event*/)
return true; return true;
} }
bool RpgDiscoverAction::Execute(Event /*event*/) bool RpgDiscoverAction::Execute(Event event)
{ {
GuidPosition guidP = rpg->guidP(); GuidPosition guidP = rpg->guidP();
uint32 node = uint32 node =
sObjectMgr->GetNearestTaxiNode(guidP.GetPositionX(), guidP.GetPositionY(), guidP.GetPositionZ(), guidP.GetMapId(), bot->GetTeamId()); sObjectMgr->GetNearestTaxiNode(guidP.getX(), guidP.getY(), guidP.getZ(), guidP.getMapId(), bot->GetTeamId());
if (!node) if (!node)
return false; return false;
@@ -222,7 +222,7 @@ bool RpgDiscoverAction::Execute(Event /*event*/)
std::string const RpgStartQuestAction::ActionName() { return "accept all quests"; } std::string const RpgStartQuestAction::ActionName() { return "accept all quests"; }
Event RpgStartQuestAction::ActionEvent(Event /*event*/) Event RpgStartQuestAction::ActionEvent(Event event)
{ {
WorldPacket p(CMSG_QUESTGIVER_ACCEPT_QUEST); WorldPacket p(CMSG_QUESTGIVER_ACCEPT_QUEST);
p << rpg->guid(); p << rpg->guid();
@@ -232,7 +232,7 @@ Event RpgStartQuestAction::ActionEvent(Event /*event*/)
std::string const RpgEndQuestAction::ActionName() { return "talk to quest giver"; } std::string const RpgEndQuestAction::ActionName() { return "talk to quest giver"; }
Event RpgEndQuestAction::ActionEvent(Event /*event*/) Event RpgEndQuestAction::ActionEvent(Event event)
{ {
WorldPacket p(CMSG_QUESTGIVER_COMPLETE_QUEST); WorldPacket p(CMSG_QUESTGIVER_COMPLETE_QUEST);
p << rpg->guid(); p << rpg->guid();
@@ -242,17 +242,17 @@ Event RpgEndQuestAction::ActionEvent(Event /*event*/)
std::string const RpgBuyAction::ActionName() { return "buy"; } std::string const RpgBuyAction::ActionName() { return "buy"; }
Event RpgBuyAction::ActionEvent(Event /*event*/) { return Event("rpg action", "vendor"); } Event RpgBuyAction::ActionEvent(Event event) { return Event("rpg action", "vendor"); }
std::string const RpgSellAction::ActionName() { return "sell"; } std::string const RpgSellAction::ActionName() { return "sell"; }
Event RpgSellAction::ActionEvent(Event /*event*/) { return Event("rpg action", "vendor"); } Event RpgSellAction::ActionEvent(Event event) { return Event("rpg action", "vendor"); }
std::string const RpgRepairAction::ActionName() { return "repair"; } std::string const RpgRepairAction::ActionName() { return "repair"; }
std::string const RpgTrainAction::ActionName() { return "trainer"; } std::string const RpgTrainAction::ActionName() { return "trainer"; }
bool RpgHealAction::Execute(Event /*event*/) bool RpgHealAction::Execute(Event event)
{ {
bool retVal = false; bool retVal = false;
@@ -287,21 +287,21 @@ std::string const RpgBuyPetitionAction::ActionName() { return "buy petition"; }
std::string const RpgUseAction::ActionName() { return "use"; } std::string const RpgUseAction::ActionName() { return "use"; }
Event RpgUseAction::ActionEvent(Event /*event*/) Event RpgUseAction::ActionEvent(Event event)
{ {
return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject())); return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject()));
} }
std::string const RpgSpellAction::ActionName() { return "cast random spell"; } std::string const RpgSpellAction::ActionName() { return "cast random spell"; }
Event RpgSpellAction::ActionEvent(Event /*event*/) Event RpgSpellAction::ActionEvent(Event event)
{ {
return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject())); return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject()));
} }
std::string const RpgCraftAction::ActionName() { return "craft random item"; } std::string const RpgCraftAction::ActionName() { return "craft random item"; }
Event RpgCraftAction::ActionEvent(Event /*event*/) Event RpgCraftAction::ActionEvent(Event event)
{ {
return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject())); return Event("rpg action", chat->FormatWorldobject(rpg->guidP().GetWorldObject()));
} }
@@ -341,7 +341,7 @@ std::vector<Item*> RpgTradeUsefulAction::CanGiveItems(GuidPosition guidPosition)
return giveItems; return giveItems;
} }
bool RpgTradeUsefulAction::Execute(Event /*event*/) bool RpgTradeUsefulAction::Execute(Event event)
{ {
GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target");
@@ -416,7 +416,7 @@ bool RpgDuelAction::isUseful()
return true; return true;
} }
bool RpgDuelAction::Execute(Event /*event*/) bool RpgDuelAction::Execute(Event event)
{ {
GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target"); GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target");
@@ -434,7 +434,7 @@ bool RpgMountAnimAction::isUseful()
return AI_VALUE2(bool, "mounted", "self target") && !AI_VALUE2(bool, "moving", "self target"); return AI_VALUE2(bool, "mounted", "self target") && !AI_VALUE2(bool, "moving", "self target");
} }
bool RpgMountAnimAction::Execute(Event /*event*/) bool RpgMountAnimAction::Execute(Event event)
{ {
WorldPacket p; WorldPacket p;
bot->GetSession()->HandleMountSpecialAnimOpcode(p); bot->GetSession()->HandleMountSpecialAnimOpcode(p);

View File

@@ -55,7 +55,7 @@ void RtiAction::AppendRti(std::ostringstream& out, std::string const type)
out << " (" << target->GetName() << ")"; out << " (" << target->GetName() << ")";
} }
bool MarkRtiAction::Execute(Event /*event*/) bool MarkRtiAction::Execute(Event event)
{ {
Group* group = bot->GetGroup(); Group* group = bot->GetGroup();
if (!group) if (!group)

View File

@@ -80,9 +80,8 @@ bool RTSCAction::Execute(Event event)
SET_AI_VALUE2(WorldPosition, "RTSC saved location", locationName, spellPosition); SET_AI_VALUE2(WorldPosition, "RTSC saved location", locationName, spellPosition);
Creature* wpCreature = Creature* wpCreature =
bot->SummonCreature(15631, spellPosition.GetPositionX(), spellPosition.GetPositionY(), bot->SummonCreature(15631, spellPosition.getX(), spellPosition.getY(), spellPosition.getZ(),
spellPosition.GetPositionZ(), spellPosition.GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, spellPosition.getO(), TEMPSUMMON_TIMED_DESPAWN, 2000.0f);
2000.0f);
wpCreature->SetObjectScale(0.5f); wpCreature->SetObjectScale(0.5f);
return true; return true;
@@ -111,9 +110,8 @@ bool RTSCAction::Execute(Event event)
if (spellPosition) if (spellPosition)
{ {
Creature* wpCreature = Creature* wpCreature =
bot->SummonCreature(15631, spellPosition.GetPositionX(), spellPosition.GetPositionY(), bot->SummonCreature(15631, spellPosition.getX(), spellPosition.getY(), spellPosition.getZ(),
spellPosition.GetPositionZ(), spellPosition.GetOrientation(), spellPosition.getO(), TEMPSUMMON_TIMED_DESPAWN, 2000.0f);
TEMPSUMMON_TIMED_DESPAWN, 2000.0f);
wpCreature->SetObjectScale(0.5f); wpCreature->SetObjectScale(0.5f);
} }

View File

@@ -9,7 +9,9 @@
#include <regex> #include <regex>
#include <string> #include <string>
#include "ChannelMgr.h"
#include "Event.h" #include "Event.h"
#include "GuildMgr.h"
#include "PlayerbotTextMgr.h" #include "PlayerbotTextMgr.h"
#include "Playerbots.h" #include "Playerbots.h"
@@ -54,7 +56,7 @@ static const std::unordered_set<std::string> noReplyMsgStarts = {"e ", "accept "
SayAction::SayAction(PlayerbotAI* botAI) : Action(botAI, "say"), Qualified() {} SayAction::SayAction(PlayerbotAI* botAI) : Action(botAI, "say"), Qualified() {}
bool SayAction::Execute(Event /*event*/) bool SayAction::Execute(Event event)
{ {
std::string text = ""; std::string text = "";
std::map<std::string, std::string> placeholders; std::map<std::string, std::string> placeholders;
@@ -90,6 +92,7 @@ bool SayAction::Execute(Event /*event*/)
} }
// set delay before next say // set delay before next say
time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier);
uint32 nextTime = time(nullptr) + urand(1, 30); uint32 nextTime = time(nullptr) + urand(1, 30);
botAI->GetAiObjectContext()->GetValue<time_t>("last said", qualifier)->Set(nextTime); botAI->GetAiObjectContext()->GetValue<time_t>("last said", qualifier)->Set(nextTime);

View File

@@ -14,7 +14,7 @@ bool SecurityCheckAction::isUseful()
botAI->GetMaster()->GetSession()->GetSecurity() < SEC_GAMEMASTER && !GET_PLAYERBOT_AI(botAI->GetMaster()); botAI->GetMaster()->GetSession()->GetSecurity() < SEC_GAMEMASTER && !GET_PLAYERBOT_AI(botAI->GetMaster());
} }
bool SecurityCheckAction::Execute(Event /*event*/) bool SecurityCheckAction::Execute(Event event)
{ {
if (Group* group = bot->GetGroup()) if (Group* group = bot->GetGroup())
{ {

View File

@@ -7,6 +7,7 @@
#include "Event.h" #include "Event.h"
#include "Formations.h" #include "Formations.h"
#include "PathGenerator.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "RTSCValues.h" #include "RTSCValues.h"
#include "RtscAction.h" #include "RtscAction.h"
@@ -133,8 +134,8 @@ bool SeeSpellAction::Execute(Event event)
SET_AI_VALUE2(WorldPosition, "RTSC saved location", locationName, spellPosition); SET_AI_VALUE2(WorldPosition, "RTSC saved location", locationName, spellPosition);
Creature* wpCreature = Creature* wpCreature =
bot->SummonCreature(15631, spellPosition.GetPositionX(), spellPosition.GetPositionY(), spellPosition.GetPositionZ(), bot->SummonCreature(15631, spellPosition.getX(), spellPosition.getY(), spellPosition.getZ(),
spellPosition.GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 2000.0f); spellPosition.getO(), TEMPSUMMON_TIMED_DESPAWN, 2000.0f);
wpCreature->SetObjectScale(0.5f); wpCreature->SetObjectScale(0.5f);
RESET_AI_VALUE(std::string, "RTSC next spell action"); RESET_AI_VALUE(std::string, "RTSC next spell action");
@@ -166,14 +167,14 @@ bool SeeSpellAction::MoveToSpell(WorldPosition& spellPosition, bool inFormation)
PositionMap& posMap = AI_VALUE(PositionMap&, "position"); PositionMap& posMap = AI_VALUE(PositionMap&, "position");
PositionInfo stayPosition = posMap["stay"]; PositionInfo stayPosition = posMap["stay"];
stayPosition.Set(spellPosition.GetPositionX(), spellPosition.GetPositionY(), spellPosition.GetPositionZ(), spellPosition.GetMapId()); stayPosition.Set(spellPosition.getX(), spellPosition.getY(), spellPosition.getZ(), spellPosition.getMapId());
posMap["stay"] = stayPosition; posMap["stay"] = stayPosition;
} }
if (bot->IsWithinLOS(spellPosition.GetPositionX(), spellPosition.GetPositionY(), spellPosition.GetPositionZ())) if (bot->IsWithinLOS(spellPosition.getX(), spellPosition.getY(), spellPosition.getZ()))
return MoveNear(spellPosition.GetMapId(), spellPosition.GetPositionX(), spellPosition.GetPositionY(), spellPosition.GetPositionZ(), 0); return MoveNear(spellPosition.getMapId(), spellPosition.getX(), spellPosition.getY(), spellPosition.getZ(), 0);
return MoveTo(spellPosition.GetMapId(), spellPosition.GetPositionX(), spellPosition.GetPositionY(), spellPosition.GetPositionZ(), false, return MoveTo(spellPosition.getMapId(), spellPosition.getX(), spellPosition.getY(), spellPosition.getZ(), false,
false); false);
} }

View File

@@ -49,8 +49,10 @@ bool SetCraftAction::Execute(Event event)
if (skillSpells.empty()) if (skillSpells.empty())
{ {
for (SkillLineAbilityEntry const* skillLine : sSkillLineAbilityStore) for (SkillLineAbilityEntry const* skillLine : sSkillLineAbilityStore)
{
skillSpells[skillLine->Spell] = skillLine; skillSpells[skillLine->Spell] = skillLine;
} }
}
data.required.clear(); data.required.clear();
data.obtained.clear(); data.obtained.clear();
@@ -76,7 +78,9 @@ bool SetCraftAction::Execute(Event event)
for (uint32 x = 0; x < MAX_SPELL_REAGENTS; ++x) for (uint32 x = 0; x < MAX_SPELL_REAGENTS; ++x)
{ {
if (spellInfo->Reagent[x] <= 0) if (spellInfo->Reagent[x] <= 0)
{
continue; continue;
}
uint32 itemid = spellInfo->Reagent[x]; uint32 itemid = spellInfo->Reagent[x];
uint32 reagentsRequired = spellInfo->ReagentCount[x]; uint32 reagentsRequired = spellInfo->ReagentCount[x];
@@ -128,8 +132,9 @@ void SetCraftAction::TellCraft()
if (ItemTemplate const* reagent = sObjectMgr->GetItemTemplate(item)) if (ItemTemplate const* reagent = sObjectMgr->GetItemTemplate(item))
{ {
if (first) if (first)
{
first = false; first = false;
}
else else
out << ", "; out << ", ";
@@ -137,9 +142,11 @@ void SetCraftAction::TellCraft()
uint32 given = data.obtained[item]; uint32 given = data.obtained[item];
if (given) if (given)
{
out << "|cffffff00(x" << given << " given)|r "; out << "|cffffff00(x" << given << " given)|r ";
} }
} }
}
out << " (craft fee: " << chat->formatMoney(GetCraftFee(data)) << ")"; out << " (craft fee: " << chat->formatMoney(GetCraftFee(data)) << ")";
botAI->TellMaster(out.str()); botAI->TellMaster(out.str());

View File

@@ -8,7 +8,7 @@
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
bool SetHomeAction::Execute(Event /*event*/) bool SetHomeAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();

View File

@@ -7,9 +7,9 @@
#include "ChatHelper.h" #include "ChatHelper.h"
#include "Event.h" #include "Event.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
bool StatsAction::Execute(Event /*event*/) bool StatsAction::Execute(Event event)
{ {
std::ostringstream out; std::ostringstream out;

View File

@@ -39,7 +39,7 @@ bool StayActionBase::Stay()
return true; return true;
} }
bool StayAction::Execute(Event /*event*/) { return Stay(); } bool StayAction::Execute(Event event) { return Stay(); }
bool StayAction::isUseful() bool StayAction::isUseful()
{ {
@@ -49,8 +49,10 @@ bool StayAction::isUseful()
{ {
const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z); const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z);
if (sPlayerbotAIConfig.followDistance) if (sPlayerbotAIConfig.followDistance)
{
return false; return false;
} }
}
// move from group takes priority over stay as it's added and removed automatically // move from group takes priority over stay as it's added and removed automatically
// (without removing/adding stay) // (without removing/adding stay)
@@ -62,7 +64,7 @@ bool StayAction::isUseful()
return AI_VALUE2(bool, "moving", "self target"); return AI_VALUE2(bool, "moving", "self target");
} }
bool SitAction::Execute(Event /*event*/) bool SitAction::Execute(Event event)
{ {
if (bot->isMoving()) if (bot->isMoving())
return false; return false;

View File

@@ -7,19 +7,25 @@
#include "SuggestWhatToDoAction.h" #include "SuggestWhatToDoAction.h"
#include "ServerFacade.h" #include "ServerFacade.h"
#include "ChannelMgr.h"
#include "Event.h" #include "Event.h"
#include "ItemVisitors.h" #include "ItemVisitors.h"
#include "AiFactory.h" #include "AiFactory.h"
#include "ChatHelper.h" #include "ChatHelper.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "PlayerbotTextMgr.h"
#include "Config.h"
#include "BroadcastHelper.h" #include "BroadcastHelper.h"
#include "AiFactory.h" #include "AiFactory.h"
#include "ChannelMgr.h"
#include "ChatHelper.h" #include "ChatHelper.h"
#include "Config.h"
#include "Event.h" #include "Event.h"
#include "GuildMgr.h"
#include "ItemVisitors.h" #include "ItemVisitors.h"
#include "PlayerbotTextMgr.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
#include "Channel.h"
enum eTalkType enum eTalkType
{ {
@@ -56,7 +62,7 @@ bool SuggestWhatToDoAction::isUseful()
return (time(0) - lastSaid) > 30; return (time(0) - lastSaid) > 30;
} }
bool SuggestWhatToDoAction::Execute(Event /*event*/) bool SuggestWhatToDoAction::Execute(Event event)
{ {
uint32 index = rand() % suggestions.size(); uint32 index = rand() % suggestions.size();
auto fnct_ptr = suggestions[index]; auto fnct_ptr = suggestions[index];
@@ -252,7 +258,7 @@ private:
SuggestDungeonAction::SuggestDungeonAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest dungeon") {} SuggestDungeonAction::SuggestDungeonAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest dungeon") {}
bool SuggestDungeonAction::Execute(Event /*event*/) bool SuggestDungeonAction::Execute(Event event)
{ {
// TODO: use PlayerbotDungeonRepository::instance() // TODO: use PlayerbotDungeonRepository::instance()
@@ -319,7 +325,7 @@ bool SuggestDungeonAction::Execute(Event /*event*/)
SuggestTradeAction::SuggestTradeAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest trade") {} SuggestTradeAction::SuggestTradeAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest trade") {}
bool SuggestTradeAction::Execute(Event /*event*/) bool SuggestTradeAction::Execute(Event event)
{ {
uint32 quality = urand(0, 100); uint32 quality = urand(0, 100);
if (quality > 95) if (quality > 95)

View File

@@ -6,10 +6,12 @@
#include "TameAction.h" #include "TameAction.h"
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <iomanip>
#include <random> #include <random>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include "DBCStructure.h" #include "DBCStructure.h"
#include "Log.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "Pet.h" #include "Pet.h"
#include "Player.h" #include "Player.h"

View File

@@ -7,12 +7,9 @@
#include "Event.h" #include "Event.h"
#include "LastMovementValue.h" #include "LastMovementValue.h"
#include "AiObjectContext.h" #include "Playerbots.h"
#include "PlayerbotAI.h"
#include "SpellMgr.h"
#include "Spell.h"
bool TeleportAction::Execute(Event /*event*/) bool TeleportAction::Execute(Event event)
{ {
/* /*
// List of allowed portal entries (you can populate this dynamically) // List of allowed portal entries (you can populate this dynamically)
@@ -77,7 +74,7 @@ bool TeleportAction::Execute(Event /*event*/)
continue; continue;
uint32 spellId = goInfo->spellcaster.spellId; uint32 spellId = goInfo->spellcaster.spellId;
SpellInfo const* spellInfo = SpellMgr::instance()->GetSpellInfo(spellId); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo || !spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS)) if (!spellInfo || !spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS))
continue; continue;

View File

@@ -4,9 +4,11 @@
*/ */
#include "TellLosAction.h" #include "TellLosAction.h"
#include <istream>
#include <sstream> #include <sstream>
#include "ChatHelper.h" #include "ChatHelper.h"
#include "DBCStores.h"
#include "Event.h" #include "Event.h"
#include "ItemTemplate.h" #include "ItemTemplate.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
@@ -75,7 +77,7 @@ void TellLosAction::ListGameObjects(std::string const title, GuidVector gos)
} }
} }
bool TellAuraAction::Execute(Event /*event*/) bool TellAuraAction::Execute(Event event)
{ {
botAI->TellMaster("--- Auras ---"); botAI->TellMaster("--- Auras ---");
sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "--- Auras ---"); sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "--- Auras ---");
@@ -128,7 +130,7 @@ bool TellAuraAction::Execute(Event /*event*/)
return true; return true;
} }
bool TellEstimatedDpsAction::Execute(Event /*event*/) bool TellEstimatedDpsAction::Execute(Event event)
{ {
float dps = AI_VALUE(float, "estimated group dps"); float dps = AI_VALUE(float, "estimated group dps");
botAI->TellMaster("Estimated Group DPS: " + std::to_string(dps)); botAI->TellMaster("Estimated Group DPS: " + std::to_string(dps));

View File

@@ -8,13 +8,13 @@
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
bool TellMasterAction::Execute(Event /*event*/) bool TellMasterAction::Execute(Event event)
{ {
botAI->TellMaster(text); botAI->TellMaster(text);
return true; return true;
} }
bool OutOfReactRangeAction::Execute(Event /*event*/) bool OutOfReactRangeAction::Execute(Event event)
{ {
botAI->TellMaster("Wait for me!"); botAI->TellMaster("Wait for me!");
return true; return true;

View File

@@ -1,100 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "TellPvpStatsAction.h"
#include <map>
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
#include "Event.h"
#include "Player.h"
#include "PlayerbotAI.h"
#include "PlayerbotTextMgr.h"
#include "Playerbots.h"
#include "SharedDefines.h"
#include "Language.h"
namespace
{
inline char const* BracketName(uint8 slot)
{
switch (slot)
{
case ARENA_SLOT_2v2: return "2v2";
case ARENA_SLOT_3v3: return "3v3";
default: return "5v5"; // ARENA_SLOT_5v5
}
}
}
bool TellPvpStatsAction::Execute(Event event)
{
if (!bot)
return false;
// Prefer the actual chat sender (whisper / say / etc.) if available.
Player* requester = nullptr;
if (Unit* owner = event.getOwner())
requester = owner->ToPlayer();
// Fallback to master if event owner is not available.
if (!requester)
requester = GetMaster();
// If we still do not have a valid player to answer to, bail out.
if (!requester)
return false;
// PVP currencies
std::map<std::string, std::string> currencyPlaceholders;
currencyPlaceholders["%arena_points"] = std::to_string(bot->GetArenaPoints());
currencyPlaceholders["%honor_points"] = std::to_string(bot->GetHonorPoints());
std::string const currencyText = PlayerbotTextMgr::instance().GetBotTextOrDefault(
"pvp_currency",
"[PVP] Arena points: %arena_points | Honor Points: %honor_points",
currencyPlaceholders);
bot->Whisper(currencyText, LANG_UNIVERSAL, requester);
// Arena Teams by slot
bool anyTeam = false;
for (uint8 slot = 0; slot < MAX_ARENA_SLOT; ++slot)
{
uint32 const teamId = bot->GetArenaTeamId(slot);
if (!teamId)
continue;
if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId))
{
anyTeam = true;
std::map<std::string, std::string> placeholders;
placeholders["%bracket"] = BracketName(slot);
placeholders["%team_name"] = team->GetName();
placeholders["%team_rating"] = std::to_string(team->GetRating());
std::string const teamText = PlayerbotTextMgr::instance().GetBotTextOrDefault(
"pvp_arena_team",
"[PVP] %bracket: <%team_name> (rating %team_rating)",
placeholders);
bot->Whisper(teamText, LANG_UNIVERSAL, requester);
}
}
if (!anyTeam)
{
std::string const noTeamText = PlayerbotTextMgr::instance().GetBotTextOrDefault(
"pvp_no_arena_team",
"[PVP] I have no Arena Team.",
std::map<std::string, std::string>());
bot->Whisper(noTeamText, LANG_UNIVERSAL, requester);
}
return true;
}

View File

@@ -1,20 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_TELLPVPSTATSACTION_H
#define _PLAYERBOT_TELLPVPSTATSACTION_H
#include "Action.h"
class PlayerbotAI;
class TellPvpStatsAction : public Action
{
public:
TellPvpStatsAction(PlayerbotAI* botAI) : Action(botAI, "tell pvp stats") {}
bool Execute(Event event) override;
};
#endif

View File

@@ -6,10 +6,10 @@
#include "TellReputationAction.h" #include "TellReputationAction.h"
#include "Event.h" #include "Event.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
#include "ReputationMgr.h" #include "ReputationMgr.h"
bool TellReputationAction::Execute(Event /*event*/) bool TellReputationAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)

View File

@@ -6,11 +6,10 @@
#include "TellTargetAction.h" #include "TellTargetAction.h"
#include "Event.h" #include "Event.h"
#include "Playerbots.h"
#include "ThreatMgr.h" #include "ThreatMgr.h"
#include "AiObjectContext.h"
#include "PlayerbotAI.h"
bool TellTargetAction::Execute(Event /*event*/) bool TellTargetAction::Execute(Event event)
{ {
Unit* target = context->GetValue<Unit*>("current target")->Get(); Unit* target = context->GetValue<Unit*>("current target")->Get();
if (target) if (target)
@@ -25,7 +24,7 @@ bool TellTargetAction::Execute(Event /*event*/)
return true; return true;
} }
bool TellAttackersAction::Execute(Event /*event*/) bool TellAttackersAction::Execute(Event event)
{ {
botAI->TellMaster("--- Attackers ---"); botAI->TellMaster("--- Attackers ---");

View File

@@ -8,7 +8,7 @@
#include "Event.h" #include "Event.h"
#include "ItemCountValue.h" #include "ItemCountValue.h"
#include "ItemVisitors.h" #include "ItemVisitors.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
bool TradeAction::Execute(Event event) bool TradeAction::Execute(Event event)
{ {
@@ -106,9 +106,11 @@ bool TradeAction::TradeItem(Item const* item, int8 slot)
for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT && tradeSlot == -1; i++) for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT && tradeSlot == -1; i++)
{ {
if (pTrade->GetItem(TradeSlots(i)) == nullptr) if (pTrade->GetItem(TradeSlots(i)) == nullptr)
{
tradeSlot = i; tradeSlot = i;
} }
} }
}
if (tradeSlot == -1) if (tradeSlot == -1)
return false; return false;

View File

@@ -276,11 +276,14 @@ bool TradeStatusAction::CheckTrade()
botAI->PlaySound(TEXT_EMOTE_NO); botAI->PlaySound(TEXT_EMOTE_NO);
return false; return false;
} }
success = true; success = true;
} }
} }
else else
{
success = true; success = true;
}
if (success) if (success)
{ {
@@ -337,7 +340,9 @@ int32 TradeStatusAction::CalculateCost(Player* player, bool sell)
if (!craftData.IsEmpty()) if (!craftData.IsEmpty())
{ {
if (player == trader && !sell && craftData.IsRequired(proto->ItemId)) if (player == trader && !sell && craftData.IsRequired(proto->ItemId))
{
continue; continue;
}
if (player == bot && sell && craftData.itemId == proto->ItemId && craftData.IsFulfilled()) if (player == bot && sell && craftData.itemId == proto->ItemId && craftData.IsFulfilled())
{ {
@@ -347,11 +352,13 @@ int32 TradeStatusAction::CalculateCost(Player* player, bool sell)
} }
if (sell) if (sell)
{
sum += item->GetCount() * proto->SellPrice * sRandomPlayerbotMgr.GetSellMultiplier(bot); sum += item->GetCount() * proto->SellPrice * sRandomPlayerbotMgr.GetSellMultiplier(bot);
}
else else
{
sum += item->GetCount() * proto->BuyPrice * sRandomPlayerbotMgr.GetBuyMultiplier(bot); sum += item->GetCount() * proto->BuyPrice * sRandomPlayerbotMgr.GetBuyMultiplier(bot);
}
} }
return sum; return sum;

View File

@@ -155,7 +155,7 @@ void TrainerAction::TellFooter(uint32 totalCost)
} }
} }
bool MaintenanceAction::Execute(Event /*event*/) bool MaintenanceAction::Execute(Event event)
{ {
if (!sPlayerbotAIConfig.maintenanceCommand) if (!sPlayerbotAIConfig.maintenanceCommand)
{ {
@@ -255,7 +255,7 @@ bool MaintenanceAction::Execute(Event /*event*/)
return true; return true;
} }
bool RemoveGlyphAction::Execute(Event /*event*/) bool RemoveGlyphAction::Execute(Event event)
{ {
for (uint32 slotIndex = 0; slotIndex < MAX_GLYPH_SLOT_INDEX; ++slotIndex) for (uint32 slotIndex = 0; slotIndex < MAX_GLYPH_SLOT_INDEX; ++slotIndex)
{ {
@@ -265,7 +265,7 @@ bool RemoveGlyphAction::Execute(Event /*event*/)
return true; return true;
} }
bool AutoGearAction::Execute(Event /*event*/) bool AutoGearAction::Execute(Event event)
{ {
if (!sPlayerbotAIConfig.autoGearCommand) if (!sPlayerbotAIConfig.autoGearCommand)
{ {

View File

@@ -10,7 +10,7 @@
#include "GridNotifiersImpl.h" #include "GridNotifiersImpl.h"
#include "Playerbots.h" #include "Playerbots.h"
bool TravelAction::Execute(Event /*event*/) bool TravelAction::Execute(Event event)
{ {
TravelTarget* target = AI_VALUE(TravelTarget*, "travel target"); TravelTarget* target = AI_VALUE(TravelTarget*, "travel target");
@@ -60,14 +60,12 @@ bool TravelAction::isUseful()
(!AI_VALUE(GuidPosition, "rpg target") || !AI_VALUE(ObjectGuid, "pull target")); (!AI_VALUE(GuidPosition, "rpg target") || !AI_VALUE(ObjectGuid, "pull target"));
} }
bool MoveToDarkPortalAction::Execute(Event /*event*/) bool MoveToDarkPortalAction::Execute(Event event)
{ {
if (bot->GetGroup()) if (bot->GetGroup())
{
if (bot->GetGroup()->GetLeaderGUID() != bot->GetGUID() && if (bot->GetGroup()->GetLeaderGUID() != bot->GetGUID() &&
!GET_PLAYERBOT_AI(GET_PLAYERBOT_AI(bot)->GetGroupLeader())) !GET_PLAYERBOT_AI(GET_PLAYERBOT_AI(bot)->GetGroupLeader()))
return false; return false;
}
if (bot->GetLevel() > 57) if (bot->GetLevel() > 57)
{ {
@@ -113,7 +111,7 @@ bool MoveToDarkPortalAction::Execute(Event /*event*/)
bool MoveToDarkPortalAction::isUseful() { return bot->GetLevel() > 54; } bool MoveToDarkPortalAction::isUseful() { return bot->GetLevel() > 54; }
bool DarkPortalAzerothAction::Execute(Event /*event*/) bool DarkPortalAzerothAction::Execute(Event event)
{ {
if (bot->GetLevel() > 57) if (bot->GetLevel() > 57)
{ {
@@ -128,7 +126,7 @@ bool DarkPortalAzerothAction::Execute(Event /*event*/)
bool DarkPortalAzerothAction::isUseful() { return bot->GetLevel() > 57; } bool DarkPortalAzerothAction::isUseful() { return bot->GetLevel() > 57; }
bool MoveFromDarkPortalAction::Execute(Event /*event*/) bool MoveFromDarkPortalAction::Execute(Event event)
{ {
RESET_AI_VALUE(GuidPosition, "rpg target"); RESET_AI_VALUE(GuidPosition, "rpg target");

View File

@@ -1,13 +1,14 @@
#include "UnlockItemAction.h" #include "UnlockItemAction.h"
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
#include "ItemTemplate.h" #include "ItemTemplate.h"
#include "WorldPacket.h"
#include "Player.h" #include "Player.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "SpellInfo.h" #include "SpellInfo.h"
inline constexpr uint32_t PICK_LOCK_SPELL_ID = 1804; #define PICK_LOCK_SPELL_ID 1804
bool UnlockItemAction::Execute(Event /*event*/) bool UnlockItemAction::Execute(Event event)
{ {
bool foundLockedItem = false; bool foundLockedItem = false;
@@ -31,5 +32,7 @@ void UnlockItemAction::UnlockItem(Item* item)
botAI->TellMaster(out.str()); botAI->TellMaster(out.str());
} }
else else
{
botAI->TellError("Failed to cast Pick Lock."); botAI->TellError("Failed to cast Pick Lock.");
} }
}

View File

@@ -1,11 +1,11 @@
#include "UnlockTradedItemAction.h" #include "UnlockTradedItemAction.h"
#include "PlayerbotAI.h" #include "Playerbots.h"
#include "TradeData.h" #include "TradeData.h"
#include "SpellInfo.h" #include "SpellInfo.h"
inline constexpr uint32_t PICK_LOCK_SPELL_ID = 1804; #define PICK_LOCK_SPELL_ID 1804
bool UnlockTradedItemAction::Execute(Event /*event*/) bool UnlockTradedItemAction::Execute(Event event)
{ {
Player* trader = bot->GetTrader(); Player* trader = bot->GetTrader();
if (!trader) if (!trader)

View File

@@ -7,9 +7,9 @@
#include "ChatHelper.h" #include "ChatHelper.h"
#include "Event.h" #include "Event.h"
#include "ItemPackets.h"
#include "ItemUsageValue.h" #include "ItemUsageValue.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "ItemPackets.h"
bool UseItemAction::Execute(Event event) bool UseItemAction::Execute(Event event)
{ {
@@ -416,7 +416,14 @@ bool UseHearthStone::Execute(Event event)
bool UseHearthStone::isUseful() { return !bot->InBattleground(); } bool UseHearthStone::isUseful() { return !bot->InBattleground(); }
bool UseRandomRecipe::Execute(Event /*event*/) bool UseRandomRecipe::isUseful()
{
return !bot->IsInCombat() && !botAI->HasActivePlayerMaster() && !bot->InBattleground();
}
bool UseRandomRecipe::isPossible() { return AI_VALUE2(uint32, "item count", "recipe") > 0; }
bool UseRandomRecipe::Execute(Event event)
{ {
std::vector<Item*> recipes = AI_VALUE2(std::vector<Item*>, "inventory items", "recipe"); std::vector<Item*> recipes = AI_VALUE2(std::vector<Item*>, "inventory items", "recipe");
@@ -438,14 +445,14 @@ bool UseRandomRecipe::Execute(Event /*event*/)
return used; return used;
} }
bool UseRandomRecipe::isUseful() bool UseRandomQuestItem::isUseful()
{ {
return !bot->IsInCombat() && !botAI->HasActivePlayerMaster() && !bot->InBattleground(); return !botAI->HasActivePlayerMaster() && !bot->InBattleground() && !bot->HasUnitState(UNIT_STATE_IN_FLIGHT);
} }
bool UseRandomRecipe::isPossible() { return AI_VALUE2(uint32, "item count", "recipe") > 0; } bool UseRandomQuestItem::isPossible() { return AI_VALUE2(uint32, "item count", "quest") > 0; }
bool UseRandomQuestItem::Execute(Event /*event*/) bool UseRandomQuestItem::Execute(Event event)
{ {
Unit* unitTarget = nullptr; Unit* unitTarget = nullptr;
ObjectGuid goTarget; ObjectGuid goTarget;
@@ -471,6 +478,7 @@ bool UseRandomQuestItem::Execute(Event /*event*/)
break; break;
} }
} }
} }
if (!item) if (!item)
@@ -482,10 +490,3 @@ bool UseRandomQuestItem::Execute(Event /*event*/)
return used; return used;
} }
bool UseRandomQuestItem::isUseful()
{
return !botAI->HasActivePlayerMaster() && !bot->InBattleground() && !bot->HasUnitState(UNIT_STATE_IN_FLIGHT);
}
bool UseRandomQuestItem::isPossible() { return AI_VALUE2(uint32, "item count", "quest") > 0; }

View File

@@ -69,8 +69,8 @@ class UseHearthStone : public UseItemAction
public: public:
UseHearthStone(PlayerbotAI* botAI) : UseItemAction(botAI, "hearthstone", true) {} UseHearthStone(PlayerbotAI* botAI) : UseItemAction(botAI, "hearthstone", true) {}
bool Execute(Event event) override;
bool isUseful() override; bool isUseful() override;
bool Execute(Event event) override;
}; };
class UseRandomRecipe : public UseItemAction class UseRandomRecipe : public UseItemAction
@@ -78,9 +78,9 @@ class UseRandomRecipe : public UseItemAction
public: public:
UseRandomRecipe(PlayerbotAI* botAI) : UseItemAction(botAI, "random recipe", true) {} UseRandomRecipe(PlayerbotAI* botAI) : UseItemAction(botAI, "random recipe", true) {}
bool Execute(Event event) override;
bool isUseful() override; bool isUseful() override;
bool isPossible() override; bool isPossible() override;
bool Execute(Event event) override;
}; };
class UseRandomQuestItem : public UseItemAction class UseRandomQuestItem : public UseItemAction
@@ -88,9 +88,9 @@ class UseRandomQuestItem : public UseItemAction
public: public:
UseRandomQuestItem(PlayerbotAI* botAI) : UseItemAction(botAI, "random quest item", true) {} UseRandomQuestItem(PlayerbotAI* botAI) : UseItemAction(botAI, "random quest item", true) {}
bool Execute(Event event) override;
bool isUseful() override; bool isUseful() override;
bool isPossible() override; bool isPossible() override;
bool Execute(Event event) override;
}; };
#endif #endif

View File

@@ -55,14 +55,16 @@ bool UseMeetingStoneAction::Execute(Event event)
return Teleport(master, bot, false); return Teleport(master, bot, false);
} }
bool SummonAction::Execute(Event /*event*/) bool SummonAction::Execute(Event event)
{ {
Player* master = GetMaster(); Player* master = GetMaster();
if (!master) if (!master)
return false; return false;
if (Pet* pet = bot->GetPet()) if (Pet* pet = bot->GetPet())
{
botAI->PetFollow(); botAI->PetFollow();
}
if (master->GetSession()->GetSecurity() >= SEC_PLAYER) if (master->GetSession()->GetSecurity() >= SEC_PLAYER)
{ {

View File

@@ -17,9 +17,9 @@ public:
SummonAction(PlayerbotAI* botAI, std::string const name = "summon") : MovementAction(botAI, name) {} SummonAction(PlayerbotAI* botAI, std::string const name = "summon") : MovementAction(botAI, name) {}
bool Execute(Event event) override; bool Execute(Event event) override;
bool Teleport(Player* summoner, Player* player, bool preserveAuras);
protected: protected:
bool Teleport(Player* summoner, Player* player, bool preserveAuras);
bool SummonUsingGos(Player* summoner, Player* player, bool preserveAuras); bool SummonUsingGos(Player* summoner, Player* player, bool preserveAuras);
bool SummonUsingNpcs(Player* summoner, Player* player, bool preserveAuras); bool SummonUsingNpcs(Player* summoner, Player* player, bool preserveAuras);
}; };

Some files were not shown because too many files have changed in this diff Show More