mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-31 09:23:47 +00:00
Compare commits
60 Commits
5f697e806e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00d19dbf9c | ||
|
|
caae524a0a | ||
|
|
13fff46fa0 | ||
|
|
a92886032c | ||
|
|
f5711dc6f7 | ||
|
|
43e8e31980 | ||
|
|
c59a02ed89 | ||
|
|
7abd836971 | ||
|
|
5365ba86b5 | ||
|
|
378254af3f | ||
|
|
3d467ce3bb | ||
|
|
3e21563669 | ||
|
|
bf456ee07f | ||
|
|
a5bd0b9a41 | ||
|
|
34bab48dd4 | ||
|
|
41c53365ae | ||
|
|
fd07e02a8a | ||
|
|
6cf7f1aaef | ||
|
|
9f54d7e702 | ||
|
|
aeaaee15da | ||
|
|
a1137dbddc | ||
|
|
2eb98c3233 | ||
|
|
29613e29b7 | ||
|
|
e2c203a35e | ||
|
|
1b1ed18a23 | ||
|
|
2ab73c1fd5 | ||
|
|
6b97c379ba | ||
|
|
965d300203 | ||
|
|
dc55ecfd9c | ||
|
|
59d6eb139e | ||
|
|
00171a8c82 | ||
|
|
02e8465a3b | ||
|
|
f53a8704eb | ||
|
|
e5525958c8 | ||
|
|
9ae457d069 | ||
|
|
c9e98a6b4e | ||
|
|
3d9623f119 | ||
|
|
c9cc4324d3 | ||
|
|
b13fb7d12a | ||
|
|
962fdeb3d1 | ||
|
|
83c6977de5 | ||
|
|
686fe513b2 | ||
|
|
61402e83a1 | ||
|
|
b16789fa54 | ||
|
|
8f638b6a66 | ||
|
|
33f5e733dc | ||
|
|
9917863ca1 | ||
|
|
2317652d72 | ||
|
|
1fcd6c5cda | ||
|
|
88016789ba | ||
|
|
6be860c967 | ||
|
|
9971622093 | ||
|
|
895df9b197 | ||
|
|
467b63b840 | ||
|
|
66f5f597bb | ||
|
|
cafbd4681e | ||
|
|
f5c84ee7ff | ||
|
|
b6f882886d | ||
|
|
c1222da8b0 | ||
|
|
00cb177c86 |
6
.github/workflows/windows_build.yml
vendored
6
.github/workflows/windows_build.yml
vendored
@@ -25,21 +25,25 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
repository: 'mod-playerbots/azerothcore-wotlk'
|
repository: 'mod-playerbots/azerothcore-wotlk'
|
||||||
ref: 'Playerbot'
|
ref: 'Playerbot'
|
||||||
|
path: 'ac'
|
||||||
- name: Checkout Playerbot Module
|
- name: Checkout Playerbot Module
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: 'mod-playerbots/mod-playerbots'
|
repository: 'mod-playerbots/mod-playerbots'
|
||||||
path: 'modules/mod-playerbots'
|
#path: 'modules/mod-playerbots'
|
||||||
|
path: ac/modules/mod-playerbots
|
||||||
- name: ccache
|
- name: ccache
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.13
|
uses: hendrikmuhs/ccache-action@v1.2.13
|
||||||
- name: Configure OS
|
- name: Configure OS
|
||||||
shell: bash
|
shell: bash
|
||||||
|
working-directory: ac
|
||||||
env:
|
env:
|
||||||
CONTINUOUS_INTEGRATION: true
|
CONTINUOUS_INTEGRATION: true
|
||||||
run: |
|
run: |
|
||||||
./acore.sh install-deps
|
./acore.sh install-deps
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
working-directory: ac
|
||||||
run: |
|
run: |
|
||||||
export CTOOLS_BUILD=all
|
export CTOOLS_BUILD=all
|
||||||
./acore.sh compiler build
|
./acore.sh compiler build
|
||||||
|
|||||||
127
PULL_REQUEST_TEMPLATE.md
Normal file
127
PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
# Pull Request
|
||||||
|
|
||||||
|
Describe what this change does and why it is needed...
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Design Philosophy
|
||||||
|
|
||||||
|
We prioritize **stability, performance, and predictability** over behavioral realism.
|
||||||
|
Complex player-mimicking logic is intentionally limited due to its negative impact on scalability, maintainability, and
|
||||||
|
long-term robustness.
|
||||||
|
|
||||||
|
Excessive processing overhead can lead to server hiccups, increased CPU usage, and degraded performance for all
|
||||||
|
participants. Because every action and
|
||||||
|
decision tree is executed **per bot and per trigger**, even small increases in logic complexity can scale poorly and
|
||||||
|
negatively affect both players and
|
||||||
|
world (random) bots. Bots are not expected to behave perfectly, and perfect simulation of human decision-making is not a
|
||||||
|
project goal. Increased behavioral
|
||||||
|
realism often introduces disproportionate cost, reduced predictability, and significantly higher maintenance overhead.
|
||||||
|
|
||||||
|
Every additional branch of logic increases long-term responsibility. All decision paths must be tested, validated, and
|
||||||
|
maintained continuously as the system evolves.
|
||||||
|
If advanced or AI-intensive behavior is introduced, the **default configuration must remain the lightweight decision
|
||||||
|
model**. More complex behavior should only be
|
||||||
|
available as an **explicit opt-in option**, clearly documented as having a measurable performance cost.
|
||||||
|
|
||||||
|
Principles:
|
||||||
|
|
||||||
|
- **Stability before intelligence**
|
||||||
|
A stable system is always preferred over a smarter one.
|
||||||
|
|
||||||
|
- **Performance is a shared resource**
|
||||||
|
Any increase in bot cost affects all players and all bots.
|
||||||
|
|
||||||
|
- **Simple logic scales better than smart logic**
|
||||||
|
Predictable behavior under load is more valuable than perfect decisions.
|
||||||
|
|
||||||
|
- **Complexity must justify itself**
|
||||||
|
If a feature cannot clearly explain its cost, it should not exist.
|
||||||
|
|
||||||
|
- **Defaults must be cheap**
|
||||||
|
Expensive behavior must always be optional and clearly communicated.
|
||||||
|
|
||||||
|
- **Bots should look reasonable, not perfect**
|
||||||
|
The goal is believable behavior, not human simulation.
|
||||||
|
|
||||||
|
Before submitting, confirm that this change aligns with those principles.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Feature Evaluation
|
||||||
|
|
||||||
|
Please answer the following:
|
||||||
|
|
||||||
|
- Describe the **minimum logic** required to achieve the intended behavior?
|
||||||
|
- Describe the **cheapest implementation** that produces an acceptable result?
|
||||||
|
- Describe the **runtime cost** when this logic executes across many bots?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Test the Changes
|
||||||
|
|
||||||
|
- Step-by-step instructions to test the change
|
||||||
|
- Any required setup (e.g. multiple players, bots, specific configuration)
|
||||||
|
- Expected behavior and how to verify it
|
||||||
|
|
||||||
|
## Complexity & Impact
|
||||||
|
|
||||||
|
- Does this change add new decision branches?
|
||||||
|
- [ ] No
|
||||||
|
- [ ] Yes (**explain below**)
|
||||||
|
|
||||||
|
- Does this change increase per-bot or per-tick processing?
|
||||||
|
- [ ] No
|
||||||
|
- [ ] Yes (**describe and justify impact**)
|
||||||
|
|
||||||
|
- Could this logic scale poorly under load?
|
||||||
|
- [ ] No
|
||||||
|
- [ ] Yes (**explain why**)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Defaults & Configuration
|
||||||
|
|
||||||
|
- Does this change modify default bot behavior?
|
||||||
|
- [ ] No
|
||||||
|
- [ ] Yes (**explain why**)
|
||||||
|
|
||||||
|
If this introduces more advanced or AI-heavy logic:
|
||||||
|
|
||||||
|
- [ ] Lightweight mode remains the default
|
||||||
|
- [ ] More complex behavior is optional and thereby configurable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## AI Assistance
|
||||||
|
|
||||||
|
- Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change?
|
||||||
|
- [ ] No
|
||||||
|
- [ ] Yes (**explain below**)
|
||||||
|
|
||||||
|
If yes, please specify:
|
||||||
|
|
||||||
|
- AI tool or model used (e.g. ChatGPT, GPT-4, Claude, etc.)
|
||||||
|
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation)
|
||||||
|
- Which parts of the change were influenced or generated
|
||||||
|
- Whether the result was manually reviewed and adapted
|
||||||
|
|
||||||
|
AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor.
|
||||||
|
Any AI-influenced changes must be verified against existing CORE and PB logic. We expect contributors to be honest
|
||||||
|
about what they do and do not understand.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final Checklist
|
||||||
|
|
||||||
|
- [ ] Stability is not compromised
|
||||||
|
- [ ] Performance impact is understood, tested, and acceptable
|
||||||
|
- [ ] Added logic complexity is justified and explained
|
||||||
|
- [ ] Documentation updated if needed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes for Reviewers
|
||||||
|
|
||||||
|
Anything that significantly improves realism at the cost of stability or performance should be carefully discussed
|
||||||
|
before merging.
|
||||||
@@ -3,8 +3,9 @@
|
|||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
# Overview
|
# Overview
|
||||||
# "Randombot": randomly generated bots that log in separately from players and populate the world. Depending on settings, randombots may automatically grind, quest, and upgrade equipment and can be invited to groups and given commands.
|
# "Randombot": randomly generated bots that log in separately from players and populate the world. Randombots may automatically grind, quest, level up, and upgrade equipment and can be invited to groups and given commands.
|
||||||
# "Altbot": characters created on player accounts, which may be logged in by the player and invited to groups and given commands like randombots. Depending on settings, altbots can be limited to characters on the active player's account or in the active player's guild.
|
# "AddClass bot": bots from the AddClassAccountPoolSize accounts. They are used for quickly adding a leveled and geared bot of any class to your party. They are recommended for a quick formation of a party.
|
||||||
|
# "Altbot": characters created on player accounts, which may be logged in by the player and invited to groups and given commands like randombots. They are best suited for long-progression playthroughs.
|
||||||
# Information about commands to control bots and set their strategies can be found on the wiki at https://github.com/mod-playerbots/mod-playerbots/wiki/Playerbot-Commands.
|
# Information about commands to control bots and set their strategies can be found on the wiki at https://github.com/mod-playerbots/mod-playerbots/wiki/Playerbot-Commands.
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
@@ -21,10 +22,11 @@
|
|||||||
# THRESHOLDS
|
# THRESHOLDS
|
||||||
# QUESTS
|
# QUESTS
|
||||||
# COMBAT
|
# COMBAT
|
||||||
# PALADIN BUFFS STRATEGIES
|
# GREATER BUFFS STRATEGIES
|
||||||
# CHEATS
|
# CHEATS
|
||||||
# SPELLS
|
# SPELLS
|
||||||
# FLIGHTPATH
|
# FLIGHTPATH
|
||||||
|
# PROFESSIONS
|
||||||
# RANDOMBOT-SPECIFIC SETTINGS
|
# RANDOMBOT-SPECIFIC SETTINGS
|
||||||
# GENERAL
|
# GENERAL
|
||||||
# LEVELS
|
# LEVELS
|
||||||
@@ -44,7 +46,7 @@
|
|||||||
# HUNTER
|
# HUNTER
|
||||||
# ROGUE
|
# ROGUE
|
||||||
# PRIEST
|
# PRIEST
|
||||||
# DEATHKNIGHT
|
# DEATH KNIGHT
|
||||||
# SHAMAN
|
# SHAMAN
|
||||||
# MAGE
|
# MAGE
|
||||||
# WARLOCK
|
# WARLOCK
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
# HUNTER
|
# HUNTER
|
||||||
# ROGUE
|
# ROGUE
|
||||||
# PRIEST
|
# PRIEST
|
||||||
# DEATHKNIGHT
|
# DEATH KNIGHT
|
||||||
# SHAMAN
|
# SHAMAN
|
||||||
# MAGE
|
# MAGE
|
||||||
# WARLOCK
|
# WARLOCK
|
||||||
@@ -90,17 +92,20 @@ AiPlayerbot.MinRandomBots = 500
|
|||||||
AiPlayerbot.MaxRandomBots = 500
|
AiPlayerbot.MaxRandomBots = 500
|
||||||
|
|
||||||
# Randombot accounts
|
# Randombot accounts
|
||||||
# If you are not using any expansion at all, you may have to set this manually, in which case please ensure that RandomBotAccountCount is at least greater than (MaxRandomBots / 10 + AddClassAccountPoolSize)
|
# If you are not using any expansion at all, you may have to set this manually, in which case please
|
||||||
|
# ensure that RandomBotAccountCount is at least greater than (MaxRandomBots / 10 + AddClassAccountPoolSize)
|
||||||
# Default: 0 (automatic)
|
# Default: 0 (automatic)
|
||||||
AiPlayerbot.RandomBotAccountCount = 0
|
AiPlayerbot.RandomBotAccountCount = 0
|
||||||
|
|
||||||
# Delete all randombot accounts
|
# Delete all randombot accounts
|
||||||
# To apply this, set the number to 1 and run the Worldserver. Once deletion is complete, if you would like to recreate randombots, set the number back to 0 and rerun the Worldserver.
|
# To apply this, set the number to 1 and run the Worldserver. Once deletion is complete, if you would
|
||||||
|
# like to recreate randombots, set the number back to 0 and rerun the Worldserver.
|
||||||
AiPlayerbot.DeleteRandomBotAccounts = 0
|
AiPlayerbot.DeleteRandomBotAccounts = 0
|
||||||
|
|
||||||
# Disable randombots when no real players are logged in
|
# Disable randombots when no real players are logged in
|
||||||
# Default: 0 (randombots will login when server starts)
|
# Default: 0 (randombots will login when server starts)
|
||||||
# If enabled, randombots will only log in 30 seconds (default) after a real player logs in, and will log out 300 seconds (default) after all real players log out
|
# If enabled, randombots will only log in 30 seconds (default) after a real player logs in, and will
|
||||||
|
# log out 300 seconds (default) after all real players log out
|
||||||
AiPlayerbot.DisabledWithoutRealPlayer = 0
|
AiPlayerbot.DisabledWithoutRealPlayer = 0
|
||||||
AiPlayerbot.DisabledWithoutRealPlayerLoginDelay = 30
|
AiPlayerbot.DisabledWithoutRealPlayerLoginDelay = 30
|
||||||
AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay = 300
|
AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay = 300
|
||||||
@@ -152,7 +157,8 @@ AiPlayerbot.AllowGuildBots = 1
|
|||||||
AiPlayerbot.AllowTrustedAccountBots = 1
|
AiPlayerbot.AllowTrustedAccountBots = 1
|
||||||
|
|
||||||
# Randombots will create guilds with nearby randombots
|
# Randombots will create guilds with nearby randombots
|
||||||
# Note: currently, randombots will not invite more bots after a guild is created (i.e., randombot guilds will have only the 10 initial randombots needed to sign the charter)
|
# Note: currently, randombots will not invite more bots after a guild is created,
|
||||||
|
# meaning randombot guilds will have only the 10 initial randombots needed to sign the charter
|
||||||
# Default: 0 (disabled)
|
# Default: 0 (disabled)
|
||||||
AiPlayerbot.RandomBotGuildNearby = 0
|
AiPlayerbot.RandomBotGuildNearby = 0
|
||||||
|
|
||||||
@@ -186,7 +192,8 @@ AiPlayerbot.AutoInitOnly = 0
|
|||||||
# Default: 1.0 (same with the player)
|
# Default: 1.0 (same with the player)
|
||||||
AiPlayerbot.AutoInitEquipLevelLimitRatio = 1.0
|
AiPlayerbot.AutoInitEquipLevelLimitRatio = 1.0
|
||||||
|
|
||||||
# Bot automatically trains spells when talking to trainer (yes = train all available spells as long as the bot has the money, free = auto trains with no money cost, no = only list spells)
|
# Bot automatically trains spells when talking to trainer
|
||||||
|
# yes = train all available spells as long as the bot has the money, free = auto trains with no money cost, no = only list spells
|
||||||
AiPlayerbot.AutoTrainSpells = yes
|
AiPlayerbot.AutoTrainSpells = yes
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -263,7 +270,7 @@ AiPlayerbot.UseFastFlyMountAtMinLevel = 70
|
|||||||
AiPlayerbot.RandomBotShowHelmet = 1
|
AiPlayerbot.RandomBotShowHelmet = 1
|
||||||
AiPlayerbot.RandomBotShowCloak = 1
|
AiPlayerbot.RandomBotShowCloak = 1
|
||||||
|
|
||||||
# Randombots and altbots automatically equip upgrades (bots will equip any item obtained from looting or a quest if they are sufficient upgrades)
|
# Toggles whether altbots will automatically equip items in their inventory that are sufficient upgrades
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.AutoEquipUpgradeLoot = 1
|
AiPlayerbot.AutoEquipUpgradeLoot = 1
|
||||||
|
|
||||||
@@ -311,7 +318,8 @@ AiPlayerbot.GlobalCooldown = 500
|
|||||||
# Max wait time when moving
|
# Max wait time when moving
|
||||||
AiPlayerbot.MaxWaitForMove = 5000
|
AiPlayerbot.MaxWaitForMove = 5000
|
||||||
|
|
||||||
# Disable use of MoveSplinePath for bot movement, will result in more erratic bot movement but means stun/snare/root/etc will work on bots (they wont reliably work when MoveSplinePath is enabled, though slowing effects still work ok)
|
# Enable/disable use of MoveSplinePath for bot movement
|
||||||
|
# Disabling will result in more erratic movement but is required for stuns, snares, and roots to work on bots
|
||||||
# Default: 0 - MoveSplinePath enabled
|
# Default: 0 - MoveSplinePath enabled
|
||||||
# 1 - MoveSplinePath disabled in BG/Arena only
|
# 1 - MoveSplinePath disabled in BG/Arena only
|
||||||
# 2 - MoveSplinePath disabled everywhere
|
# 2 - MoveSplinePath disabled everywhere
|
||||||
@@ -405,10 +413,11 @@ AiPlayerbot.HighMana = 65
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
# Bots pick their quest rewards (yes = picks the most useful item, no = list all rewards, ask = pick useful item and lists if multiple)
|
# Bots pick their quest rewards
|
||||||
|
# yes = picks the most useful item, no = list all rewards, ask = pick useful item and lists if multiple
|
||||||
AiPlayerbot.AutoPickReward = yes
|
AiPlayerbot.AutoPickReward = yes
|
||||||
|
|
||||||
# Sync quests with player (Bots will complete quests the moment you hand them in and will not loot quest items.)
|
# Sync quests with player (bots will complete quests the moment you hand them in and will not loot quest items.)
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.SyncQuestWithPlayer = 1
|
AiPlayerbot.SyncQuestWithPlayer = 1
|
||||||
|
|
||||||
@@ -433,7 +442,7 @@ AiPlayerbot.DropObsoleteQuests = 1
|
|||||||
# Auto add dungeon/raid strategies when entering the instance if implemented
|
# Auto add dungeon/raid strategies when entering the instance if implemented
|
||||||
AiPlayerbot.ApplyInstanceStrategies = 1
|
AiPlayerbot.ApplyInstanceStrategies = 1
|
||||||
|
|
||||||
# Enable auto avoid aoe strategy (experimental)
|
# Enable auto avoid aoe strategy
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.AutoAvoidAoe = 1
|
AiPlayerbot.AutoAvoidAoe = 1
|
||||||
|
|
||||||
@@ -460,7 +469,7 @@ AiPlayerbot.FleeingEnabled = 1
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# PALADIN BUFFS STRATEGIES
|
# GREATER BUFFS STRATEGIES
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
@@ -483,12 +492,13 @@ AiPlayerbot.RPWarningCooldown = 30
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Enable/Disable maintenance command
|
# Enable/Disable maintenance command
|
||||||
# Learn all available spells and skills, refresh consumables, repair, enchant equipment and socket gems if bot's level is above AiPlayerbot.MinEnchantingBotLevel
|
# Learn all available spells and skills, assign talent points, refresh consumables, repair, enchant equipment, socket gems, etc.
|
||||||
|
# Applies if bot's level is above AiPlayerbot.MinEnchantingBotLevel
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.MaintenanceCommand = 1
|
AiPlayerbot.MaintenanceCommand = 1
|
||||||
|
|
||||||
# Enable/Disable specific maintenance command functionality for alt bots
|
# Enable/Disable specific maintenance command functionality for alt bots
|
||||||
# Disable to prevent players from giving free bags, spells, skill levels etc to their alt bots
|
# Disable to prevent players from giving free bags, spells, skill levels, etc. to their alt bots
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.AltMaintenanceAmmo = 1
|
AiPlayerbot.AltMaintenanceAmmo = 1
|
||||||
AiPlayerbot.AltMaintenanceFood = 1
|
AiPlayerbot.AltMaintenanceFood = 1
|
||||||
@@ -500,6 +510,7 @@ AiPlayerbot.AltMaintenanceBags = 1
|
|||||||
AiPlayerbot.AltMaintenanceMounts = 1
|
AiPlayerbot.AltMaintenanceMounts = 1
|
||||||
AiPlayerbot.AltMaintenanceSkills = 1
|
AiPlayerbot.AltMaintenanceSkills = 1
|
||||||
|
|
||||||
|
# "Special Spells" consist of any spells listed in AiPlayerbot.RandomBotSpellIds and Death Gate for Death Knights
|
||||||
AiPlayerbot.AltMaintenanceClassSpells = 1
|
AiPlayerbot.AltMaintenanceClassSpells = 1
|
||||||
AiPlayerbot.AltMaintenanceAvailableSpells = 1
|
AiPlayerbot.AltMaintenanceAvailableSpells = 1
|
||||||
AiPlayerbot.AltMaintenanceSpecialSpells = 1
|
AiPlayerbot.AltMaintenanceSpecialSpells = 1
|
||||||
@@ -514,8 +525,8 @@ AiPlayerbot.AltMaintenanceReputation = 1
|
|||||||
AiPlayerbot.AltMaintenanceAttunementQuests = 1
|
AiPlayerbot.AltMaintenanceAttunementQuests = 1
|
||||||
AiPlayerbot.AltMaintenanceKeyring = 1
|
AiPlayerbot.AltMaintenanceKeyring = 1
|
||||||
|
|
||||||
|
# Enable/Disable autogear command, which automatically upgrades bots' gear
|
||||||
# Enable/Disable autogear command, which automatically upgrades bots' gear; the quality is limited by AutoGearQualityLimit and AutoGearScoreLimit
|
# The quality is limited by AutoGearQualityLimit and AutoGearScoreLimit
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.AutoGearCommand = 1
|
AiPlayerbot.AutoGearCommand = 1
|
||||||
|
|
||||||
@@ -533,8 +544,8 @@ AiPlayerbot.AutoGearQualityLimit = 3
|
|||||||
# Max iLVL Phase 1(MC, Ony, ZG) = 78 | Phase 2(BWL) = 83 | Phase 2.5(AQ40) = 88 | Phase 3(Naxx40) = 92
|
# Max iLVL Phase 1(MC, Ony, ZG) = 78 | Phase 2(BWL) = 83 | Phase 2.5(AQ40) = 88 | Phase 3(Naxx40) = 92
|
||||||
# TBC
|
# TBC
|
||||||
# Max iLVL Tier 4 = 120 | Tier 5 = 133 | Tier 6 = 164
|
# Max iLVL Tier 4 = 120 | Tier 5 = 133 | Tier 6 = 164
|
||||||
# Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 1.5(ZA) = 138 | Phase 2(SC, TK) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164
|
# Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 2(SSC, TK, ZA) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164
|
||||||
# Wotlk
|
# WotLK
|
||||||
# Max iLVL Tier 7(10/25) = 200/213 | Tier 8(10/25) = 225/232 | Tier 9(10/25) = 232/245 | Tier 10(10/25/HC) = 251/264/290
|
# Max iLVL Tier 7(10/25) = 200/213 | Tier 8(10/25) = 225/232 | Tier 9(10/25) = 232/245 | Tier 10(10/25/HC) = 251/264/290
|
||||||
# Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290
|
# Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290
|
||||||
# Default: 0 (no limit)
|
# Default: 0 (no limit)
|
||||||
@@ -579,6 +590,30 @@ AiPlayerbot.BotTaxiGapJitterMs = 100
|
|||||||
#
|
#
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
|
||||||
|
####################################################################################################
|
||||||
|
# PROFESSIONS
|
||||||
|
# Note: Random bots currently do not get professions
|
||||||
|
#
|
||||||
|
|
||||||
|
# Automatically adds the 'master fishing' strategy to bots that have the fishing skill when the bots master fishes.
|
||||||
|
# Default: 1 (Enabled)
|
||||||
|
AiPlayerbot.EnableFishingWithMaster = 1
|
||||||
|
|
||||||
|
# Distance from itself (in yards) that a bot with a master will search for water to fish
|
||||||
|
AiPlayerbot.FishingDistanceFromMaster = 10.0
|
||||||
|
|
||||||
|
# Distance from itself (in yards) that a bot without a master will search for water to fish
|
||||||
|
# Currently not relevant since masterless bots will not fish
|
||||||
|
AiPlayerbot.FishingDistance = 40.0
|
||||||
|
|
||||||
|
# Distance from water (in yards) beyond which a bot will remove the 'master fishing' strategy
|
||||||
|
AiPlayerbot.EndFishingWithMaster = 30.0
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# #
|
# #
|
||||||
# RANDOMBOT-SPECIFIC SETTINGS #
|
# RANDOMBOT-SPECIFIC SETTINGS #
|
||||||
@@ -635,7 +670,7 @@ AiPlayerbot.DisableDeathKnightLogin = 0
|
|||||||
# Default: 0 (disabled)
|
# Default: 0 (disabled)
|
||||||
AiPlayerbot.LimitTalentsExpansion = 0
|
AiPlayerbot.LimitTalentsExpansion = 0
|
||||||
|
|
||||||
# Configure randombots and addClass bot trading (0: Disabled, 1: Enabled, 2: Only Buy, 3: Only Sell)
|
# Configure randombot trading (0: Disabled, 1: Enabled, 2: Only Buy, 3: Only Sell)
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.EnableRandomBotTrading = 1
|
AiPlayerbot.EnableRandomBotTrading = 1
|
||||||
|
|
||||||
@@ -700,8 +735,8 @@ AiPlayerbot.RandomGearQualityLimit = 3
|
|||||||
# Max iLVL Phase 1(MC, Ony, ZG) = 78 | Phase 2(BWL) = 83 | Phase 2.5(AQ40) = 88 | Phase 3(Naxx40) = 92
|
# Max iLVL Phase 1(MC, Ony, ZG) = 78 | Phase 2(BWL) = 83 | Phase 2.5(AQ40) = 88 | Phase 3(Naxx40) = 92
|
||||||
# TBC
|
# TBC
|
||||||
# Max iLVL Tier 4 = 120 | Tier 5 = 133 | Tier 6 = 164
|
# Max iLVL Tier 4 = 120 | Tier 5 = 133 | Tier 6 = 164
|
||||||
# Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 1.5(ZA) = 138 | Phase 2(SC, TK) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164
|
# Max iLVL Phase 1(Kara, Gruul, Mag) = 125 | Phase 2(SSC, TK, ZA) = 141 | Phase 3(Hyjal, BT) = 156 | Phase 4(Sunwell) = 164
|
||||||
# Wotlk
|
# WotLK
|
||||||
# Max iLVL Tier 7(10/25) = 200/213 | Tier 8(10/25) = 225/232 | Tier 9(10/25) = 232/245 | Tier 10(10/25/HC) = 251/264/290
|
# Max iLVL Tier 7(10/25) = 200/213 | Tier 8(10/25) = 225/232 | Tier 9(10/25) = 232/245 | Tier 10(10/25/HC) = 251/264/290
|
||||||
# Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290
|
# Max iLVL Phase 1(Naxx) = 224 | Phase 2(Ulduar) = 245 | Phase 3(ToC) = 258 | Phase 4(ICC) = 290
|
||||||
# Default: 0 (no limit)
|
# Default: 0 (no limit)
|
||||||
@@ -711,7 +746,8 @@ AiPlayerbot.RandomGearScoreLimit = 0
|
|||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.IncrementalGearInit = 1
|
AiPlayerbot.IncrementalGearInit = 1
|
||||||
|
|
||||||
# Set minimum level of bots that will enchant their equipment (if greater than RandomBotMaxlevel, bots will not enchant equipment)
|
# Set minimum level of bots that will enchant and socket gems into their equipment with maintenance
|
||||||
|
# If greater than RandomBotMaxlevel, bots will not automatically enchant equipment or socket gems
|
||||||
# Default: 60
|
# Default: 60
|
||||||
AiPlayerbot.MinEnchantingBotLevel = 60
|
AiPlayerbot.MinEnchantingBotLevel = 60
|
||||||
|
|
||||||
@@ -863,13 +899,15 @@ AiPlayerbot.OpenGoSpell = 6477
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Additional randombot strategies
|
# Additional randombot strategies
|
||||||
# Strategies added here are applied to all randombots, in addition (or subtraction) to spec/role-based default strategies. These rules are processed after the defaults.
|
# Strategies added here are applied to all randombots, in addition (or subtraction) to spec/role-based default strategies.
|
||||||
|
# These rules are processed after the defaults.
|
||||||
# Example: "+threat,-potions"
|
# Example: "+threat,-potions"
|
||||||
AiPlayerbot.RandomBotCombatStrategies = ""
|
AiPlayerbot.RandomBotCombatStrategies = ""
|
||||||
AiPlayerbot.RandomBotNonCombatStrategies = ""
|
AiPlayerbot.RandomBotNonCombatStrategies = ""
|
||||||
|
|
||||||
# Additional altbot strategies
|
# Additional altbot strategies
|
||||||
# Strategies added here are applied to all altbots, in addition (or subtraction) to spec/role-based default strategies. These rules are processed after the defaults.
|
# Strategies added here are applied to all altbots, in addition (or subtraction) to spec/role-based default strategies.
|
||||||
|
# These rules are processed after the defaults.
|
||||||
AiPlayerbot.CombatStrategies = ""
|
AiPlayerbot.CombatStrategies = ""
|
||||||
AiPlayerbot.NonCombatStrategies = ""
|
AiPlayerbot.NonCombatStrategies = ""
|
||||||
|
|
||||||
@@ -1455,7 +1493,7 @@ AiPlayerbot.PremadeSpecLink.5.5.80 = 50332031003--005323241223112003102311351
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# DEATHKNIGHT
|
# DEATH KNIGHT
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
@@ -1586,7 +1624,7 @@ AiPlayerbot.PremadeSpecLink.9.1.60 = -003203301135112530135201051
|
|||||||
AiPlayerbot.PremadeSpecLink.9.1.70 = -003203301135112530135201051-55
|
AiPlayerbot.PremadeSpecLink.9.1.70 = -003203301135112530135201051-55
|
||||||
AiPlayerbot.PremadeSpecLink.9.1.80 = -003203301135112530135221351-55000005
|
AiPlayerbot.PremadeSpecLink.9.1.80 = -003203301135112530135221351-55000005
|
||||||
AiPlayerbot.PremadeSpecName.9.2 = destro pve
|
AiPlayerbot.PremadeSpecName.9.2 = destro pve
|
||||||
AiPlayerbot.PremadeSpecGlyph.9.2 = 45785,43390,50077,43394,43393,42454
|
AiPlayerbot.PremadeSpecGlyph.9.2 = 45785,43390,42454,43394,43393,45785
|
||||||
AiPlayerbot.PremadeSpecLink.9.2.60 = --05203215200231051305031151
|
AiPlayerbot.PremadeSpecLink.9.2.60 = --05203215200231051305031151
|
||||||
AiPlayerbot.PremadeSpecLink.9.2.80 = 23-0302-05203215220331051335231351
|
AiPlayerbot.PremadeSpecLink.9.2.80 = 23-0302-05203215220331051335231351
|
||||||
AiPlayerbot.PremadeSpecName.9.3 = affli pvp
|
AiPlayerbot.PremadeSpecName.9.3 = affli pvp
|
||||||
@@ -1778,7 +1816,7 @@ AiPlayerbot.RandomClassSpecIndex.5.2 = 2
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# DEATHKNIGHT
|
# DEATH KNIGHT
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
DELETE FROM ai_playerbot_texts WHERE name IN ('no_fishing_pole_error');
|
||||||
|
DELETE FROM ai_playerbot_texts_chance WHERE name IN ('no_fishing_pole_error');
|
||||||
|
|
||||||
|
INSERT INTO ai_playerbot_texts (id, name, text, say_type, reply_type, text_loc1, text_loc2, text_loc3, text_loc4, text_loc5, text_loc6, text_loc7, text_loc8) VALUES
|
||||||
|
(1736, 'no_fishing_pole_error', "I don't have a Fishing Pole", 0, 0,
|
||||||
|
"낚싯대가 없습니다",
|
||||||
|
"Je n’ai pas de canne à pêche",
|
||||||
|
"Ich habe keine Angelrute",
|
||||||
|
"我沒有釣魚竿",
|
||||||
|
"我没有钓鱼竿",
|
||||||
|
"No tengo una caña de pescar",
|
||||||
|
"No tengo una caña de pescar",
|
||||||
|
"У меня нет удочки");
|
||||||
|
|
||||||
|
INSERT INTO ai_playerbot_texts_chance (name, probability) VALUES ('no_fishing_pole_error', 100);
|
||||||
@@ -46,7 +46,6 @@
|
|||||||
#include "OutfitAction.h"
|
#include "OutfitAction.h"
|
||||||
#include "PositionAction.h"
|
#include "PositionAction.h"
|
||||||
#include "DropQuestAction.h"
|
#include "DropQuestAction.h"
|
||||||
#include "RaidNaxxActions.h"
|
|
||||||
#include "RandomBotUpdateAction.h"
|
#include "RandomBotUpdateAction.h"
|
||||||
#include "ReachTargetActions.h"
|
#include "ReachTargetActions.h"
|
||||||
#include "ReleaseSpiritAction.h"
|
#include "ReleaseSpiritAction.h"
|
||||||
@@ -64,6 +63,7 @@
|
|||||||
#include "WorldBuffAction.h"
|
#include "WorldBuffAction.h"
|
||||||
#include "XpGainAction.h"
|
#include "XpGainAction.h"
|
||||||
#include "NewRpgAction.h"
|
#include "NewRpgAction.h"
|
||||||
|
#include "FishingAction.h"
|
||||||
#include "CancelChannelAction.h"
|
#include "CancelChannelAction.h"
|
||||||
|
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
@@ -191,6 +191,11 @@ public:
|
|||||||
creators["buy tabard"] = &ActionContext::buy_tabard;
|
creators["buy tabard"] = &ActionContext::buy_tabard;
|
||||||
creators["guild manage nearby"] = &ActionContext::guild_manage_nearby;
|
creators["guild manage nearby"] = &ActionContext::guild_manage_nearby;
|
||||||
creators["clean quest log"] = &ActionContext::clean_quest_log;
|
creators["clean quest log"] = &ActionContext::clean_quest_log;
|
||||||
|
creators["move near water"] = &ActionContext::move_near_water;
|
||||||
|
creators["go fishing"] = &ActionContext::go_fishing;
|
||||||
|
creators["use fishing bobber"] = &ActionContext::use_fishing_bobber;
|
||||||
|
creators["end master fishing"] = &ActionContext::end_master_fishing;
|
||||||
|
creators["remove bobber strategy"] = &ActionContext::remove_bobber_strategy;
|
||||||
creators["roll"] = &ActionContext::roll_action;
|
creators["roll"] = &ActionContext::roll_action;
|
||||||
creators["cancel channel"] = &ActionContext::cancel_channel;
|
creators["cancel channel"] = &ActionContext::cancel_channel;
|
||||||
|
|
||||||
@@ -380,6 +385,11 @@ private:
|
|||||||
static Action* buy_tabard(PlayerbotAI* botAI) { return new BuyTabardAction(botAI); }
|
static Action* buy_tabard(PlayerbotAI* botAI) { return new BuyTabardAction(botAI); }
|
||||||
static Action* guild_manage_nearby(PlayerbotAI* botAI) { return new GuildManageNearbyAction(botAI); }
|
static Action* guild_manage_nearby(PlayerbotAI* botAI) { return new GuildManageNearbyAction(botAI); }
|
||||||
static Action* clean_quest_log(PlayerbotAI* botAI) { return new CleanQuestLogAction(botAI); }
|
static Action* clean_quest_log(PlayerbotAI* botAI) { return new CleanQuestLogAction(botAI); }
|
||||||
|
static Action* move_near_water(PlayerbotAI* botAI) { return new MoveNearWaterAction(botAI); }
|
||||||
|
static Action* go_fishing(PlayerbotAI* botAI) { return new FishingAction(botAI);}
|
||||||
|
static Action* use_fishing_bobber(PlayerbotAI* botAI) { return new UseBobberAction(botAI);}
|
||||||
|
static Action* end_master_fishing(PlayerbotAI* botAI) { return new EndMasterFishingAction(botAI); }
|
||||||
|
static Action* remove_bobber_strategy(PlayerbotAI* botAI) { return new RemoveBobberStrategyAction(botAI); }
|
||||||
static Action* roll_action(PlayerbotAI* botAI) { return new RollAction(botAI); }
|
static Action* roll_action(PlayerbotAI* botAI) { return new RollAction(botAI); }
|
||||||
|
|
||||||
// BG Tactics
|
// BG Tactics
|
||||||
@@ -46,10 +46,10 @@ bool AcceptInvitationAction::Execute(Event event)
|
|||||||
if (!bot->GetGroup() || !bot->GetGroup()->IsMember(inviter->GetGUID()))
|
if (!bot->GetGroup() || !bot->GetGroup()->IsMember(inviter->GetGUID()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (sRandomPlayerbotMgr->IsRandomBot(bot))
|
if (sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
botAI->SetMaster(inviter);
|
botAI->SetMaster(inviter);
|
||||||
// else
|
// else
|
||||||
// sPlayerbotDbStore->Save(botAI);
|
// PlayerbotRepository::instance().Save(botAI);
|
||||||
|
|
||||||
botAI->ResetStrategies();
|
botAI->ResetStrategies();
|
||||||
botAI->ChangeStrategy("+follow,-lfg,-bg", BOT_STATE_NON_COMBAT);
|
botAI->ChangeStrategy("+follow,-lfg,-bg", BOT_STATE_NON_COMBAT);
|
||||||
@@ -57,9 +57,9 @@ bool AcceptInvitationAction::Execute(Event event)
|
|||||||
|
|
||||||
botAI->TellMaster("Hello");
|
botAI->TellMaster("Hello");
|
||||||
|
|
||||||
if (sPlayerbotAIConfig->summonWhenGroup && bot->GetDistance(inviter) > sPlayerbotAIConfig->sightDistance)
|
if (sPlayerbotAIConfig.summonWhenGroup && bot->GetDistance(inviter) > sPlayerbotAIConfig.sightDistance)
|
||||||
{
|
{
|
||||||
Teleport(inviter, bot);
|
Teleport(inviter, bot, true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,5 @@ bool AcceptResurrectAction::Execute(Event event)
|
|||||||
packet << uint8(1); // accept
|
packet << uint8(1); // accept
|
||||||
bot->GetSession()->HandleResurrectResponseOpcode(packet); // queue the packet to get around race condition
|
bot->GetSession()->HandleResurrectResponseOpcode(packet); // queue the packet to get around race condition
|
||||||
|
|
||||||
botAI->ChangeEngine(BOT_STATE_NON_COMBAT);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ bool ReachAreaTriggerAction::Execute(Event event)
|
|||||||
/*forceDestination*/ false);
|
/*forceDestination*/ false);
|
||||||
|
|
||||||
float distance = bot->GetDistance(at->x, at->y, at->z);
|
float distance = bot->GetDistance(at->x, at->y, at->z);
|
||||||
float delay = 1000.0f * distance / bot->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig->reactDelay;
|
float delay = 1000.0f * distance / bot->GetSpeed(MOVE_RUN) + sPlayerbotAIConfig.reactDelay;
|
||||||
botAI->TellError("Wait for me");
|
botAI->TellError("Wait for me");
|
||||||
botAI->SetNextCheckDelay(delay);
|
botAI->SetNextCheckDelay(delay);
|
||||||
context->GetValue<LastMovement&>("last area trigger")->Get().lastAreaTrigger = triggerId;
|
context->GetValue<LastMovement&>("last area trigger")->Get().lastAreaTrigger = triggerId;
|
||||||
@@ -15,20 +15,19 @@
|
|||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
#include "Unit.h"
|
#include "Unit.h"
|
||||||
|
|
||||||
bool AttackAction::Execute(Event event)
|
bool AttackAction::Execute(Event /*event*/)
|
||||||
{
|
{
|
||||||
Unit* target = GetTarget();
|
Unit* target = GetTarget();
|
||||||
if (!target)
|
if (!target)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!target->IsInWorld())
|
if (!target->IsInWorld())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return Attack(target);
|
return Attack(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AttackMyTargetAction::Execute(Event event)
|
bool AttackMyTargetAction::Execute(Event /*event*/)
|
||||||
{
|
{
|
||||||
Player* master = GetMaster();
|
Player* master = GetMaster();
|
||||||
if (!master)
|
if (!master)
|
||||||
@@ -51,7 +50,7 @@ bool AttackMyTargetAction::Execute(Event event)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/)
|
||||||
{
|
{
|
||||||
Unit* oldTarget = context->GetValue<Unit*>("current target")->Get();
|
Unit* oldTarget = context->GetValue<Unit*>("current target")->Get();
|
||||||
bool shouldMelee = bot->IsWithinMeleeRange(target) || botAI->IsMelee(bot);
|
bool shouldMelee = bot->IsWithinMeleeRange(target) || botAI->IsMelee(bot);
|
||||||
@@ -81,13 +80,15 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
botAI->TellError(std::string(target->GetName()) + " is no longer in the world.");
|
botAI->TellError(std::string(target->GetName()) + " is no longer in the world.");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if bot OR target is in prohibited zone/area
|
// Check if bot OR target is in prohibited zone/area (skip for duels)
|
||||||
if ((target->IsPlayer() || target->IsPet()) &&
|
if ((target->IsPlayer() || target->IsPet()) &&
|
||||||
(sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) ||
|
(!bot->duel || bot->duel->Opponent != target) &&
|
||||||
sPlayerbotAIConfig->IsPvpProhibited(target->GetZoneId(), target->GetAreaId())))
|
(sPlayerbotAIConfig.IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId()) ||
|
||||||
|
sPlayerbotAIConfig.IsPvpProhibited(target->GetZoneId(), target->GetAreaId())))
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
botAI->TellError("I cannot attack other players in PvP prohibited areas.");
|
botAI->TellError("I cannot attack other players in PvP prohibited areas.");
|
||||||
@@ -99,6 +100,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
botAI->TellError(std::string(target->GetName()) + " is friendly to me.");
|
botAI->TellError(std::string(target->GetName()) + " is friendly to me.");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +108,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
botAI->TellError(std::string(target->GetName()) + " is dead.");
|
botAI->TellError(std::string(target->GetName()) + " is dead.");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +116,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
botAI->TellError(std::string(target->GetName()) + " is not in my sight.");
|
botAI->TellError(std::string(target->GetName()) + " is not in my sight.");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +124,7 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
botAI->TellError("I am already attacking " + std::string(target->GetName()) + ".");
|
botAI->TellError("I am already attacking " + std::string(target->GetName()) + ".");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,10 +159,9 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
bot->StopMoving();
|
bot->StopMoving();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsMovingAllowed() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target))
|
if (botAI->CanMove() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target))
|
||||||
{
|
ServerFacade::instance().SetFacingTo(bot, target);
|
||||||
sServerFacade->SetFacingTo(bot, target);
|
|
||||||
}
|
|
||||||
botAI->ChangeEngine(BOT_STATE_COMBAT);
|
botAI->ChangeEngine(BOT_STATE_COMBAT);
|
||||||
|
|
||||||
bot->Attack(target, shouldMelee);
|
bot->Attack(target, shouldMelee);
|
||||||
@@ -187,4 +191,4 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
|
|||||||
|
|
||||||
bool AttackDuelOpponentAction::isUseful() { return AI_VALUE(Unit*, "duel target"); }
|
bool AttackDuelOpponentAction::isUseful() { return AI_VALUE(Unit*, "duel target"); }
|
||||||
|
|
||||||
bool AttackDuelOpponentAction::Execute(Event event) { return Attack(AI_VALUE(Unit*, "duel target")); }
|
bool AttackDuelOpponentAction::Execute(Event /*event*/) { return Attack(AI_VALUE(Unit*, "duel target")); }
|
||||||
@@ -19,7 +19,7 @@ bool AutoMaintenanceOnLevelupAction::Execute(Event event)
|
|||||||
|
|
||||||
void AutoMaintenanceOnLevelupAction::AutoTeleportForLevel()
|
void AutoMaintenanceOnLevelupAction::AutoTeleportForLevel()
|
||||||
{
|
{
|
||||||
if (!sPlayerbotAIConfig->autoTeleportForLevel || !sRandomPlayerbotMgr->IsRandomBot(bot))
|
if (!sPlayerbotAIConfig.autoTeleportForLevel || !sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -27,13 +27,13 @@ void AutoMaintenanceOnLevelupAction::AutoTeleportForLevel()
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sRandomPlayerbotMgr->RandomTeleportForLevel(bot);
|
sRandomPlayerbotMgr.RandomTeleportForLevel(bot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoMaintenanceOnLevelupAction::AutoPickTalents()
|
void AutoMaintenanceOnLevelupAction::AutoPickTalents()
|
||||||
{
|
{
|
||||||
if (!sPlayerbotAIConfig->autoPickTalents || !sRandomPlayerbotMgr->IsRandomBot(bot))
|
if (!sPlayerbotAIConfig.autoPickTalents || !sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bot->GetFreeTalentPoints() <= 0)
|
if (bot->GetFreeTalentPoints() <= 0)
|
||||||
@@ -65,46 +65,89 @@ void AutoMaintenanceOnLevelupAction::AutoLearnSpell()
|
|||||||
void AutoMaintenanceOnLevelupAction::LearnSpells(std::ostringstream* out)
|
void AutoMaintenanceOnLevelupAction::LearnSpells(std::ostringstream* out)
|
||||||
{
|
{
|
||||||
BroadcastHelper::BroadcastLevelup(botAI, bot);
|
BroadcastHelper::BroadcastLevelup(botAI, bot);
|
||||||
if (sPlayerbotAIConfig->autoLearnTrainerSpells && sRandomPlayerbotMgr->IsRandomBot(bot))
|
if (sPlayerbotAIConfig.autoLearnTrainerSpells && sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
LearnTrainerSpells(out);
|
LearnTrainerSpells(out);
|
||||||
|
|
||||||
if (sPlayerbotAIConfig->autoLearnQuestSpells && sRandomPlayerbotMgr->IsRandomBot(bot))
|
if (sPlayerbotAIConfig.autoLearnQuestSpells && sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
LearnQuestSpells(out);
|
LearnQuestSpells(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoMaintenanceOnLevelupAction::LearnTrainerSpells(std::ostringstream* out)
|
void AutoMaintenanceOnLevelupAction::LearnTrainerSpells(std::ostringstream* out)
|
||||||
{
|
{
|
||||||
PlayerbotFactory factory(bot, bot->GetLevel());
|
PlayerbotFactory factory(bot, bot->GetLevel());
|
||||||
|
factory.InitSkills();
|
||||||
factory.InitClassSpells();
|
factory.InitClassSpells();
|
||||||
factory.InitAvailableSpells();
|
factory.InitAvailableSpells();
|
||||||
factory.InitSkills();
|
|
||||||
factory.InitPet();
|
factory.InitPet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoMaintenanceOnLevelupAction::LearnQuestSpells(std::ostringstream* out)
|
void AutoMaintenanceOnLevelupAction::LearnQuestSpells(std::ostringstream* out)
|
||||||
{
|
{
|
||||||
// CreatureTemplate const* co = sCreatureStorage.LookupEntry<CreatureTemplate>(id);
|
|
||||||
ObjectMgr::QuestMap const& questTemplates = sObjectMgr->GetQuestTemplates();
|
ObjectMgr::QuestMap const& questTemplates = sObjectMgr->GetQuestTemplates();
|
||||||
for (ObjectMgr::QuestMap::const_iterator i = questTemplates.begin(); i != questTemplates.end(); ++i)
|
for (ObjectMgr::QuestMap::const_iterator i = questTemplates.begin(); i != questTemplates.end(); ++i)
|
||||||
{
|
{
|
||||||
//uint32 questId = i->first; //not used, line marked for removal.
|
|
||||||
Quest const* quest = i->second;
|
Quest const* quest = i->second;
|
||||||
|
|
||||||
if (!quest->GetRequiredClasses() || quest->IsRepeatable() || quest->GetMinLevel() < 10)
|
// only process class-specific quests to learn class-related spells, cuz
|
||||||
|
// we don't want all these bunch of entries to be handled!
|
||||||
|
if (!quest->GetRequiredClasses())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!bot->SatisfyQuestClass(quest, false) || quest->GetMinLevel() > bot->GetLevel() ||
|
// skip quests that are repeatable, too low level, or above bots' level
|
||||||
!bot->SatisfyQuestRace(quest, false))
|
if (quest->IsRepeatable() || quest->GetMinLevel() < 10 || quest->GetMinLevel() > bot->GetLevel())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (quest->GetRewSpellCast() > 0)
|
// skip if bot doesnt satisfy class, race, or skill requirements
|
||||||
|
if (!bot->SatisfyQuestClass(quest, false) || !bot->SatisfyQuestRace(quest, false) ||
|
||||||
|
!bot->SatisfyQuestSkill(quest, false))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// use the same logic and impl from Player::learnQuestRewardedSpells
|
||||||
|
|
||||||
|
int32 spellId = quest->GetRewSpellCast();
|
||||||
|
if (!spellId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||||
|
if (!spellInfo)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// xinef: find effect with learn spell and check if we have this spell
|
||||||
|
bool found = false;
|
||||||
|
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||||
{
|
{
|
||||||
LearnSpell(quest->GetRewSpellCast(), out);
|
if (spellInfo->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL && spellInfo->Effects[i].TriggerSpell &&
|
||||||
|
!bot->HasSpell(spellInfo->Effects[i].TriggerSpell))
|
||||||
|
{
|
||||||
|
// pusywizard: don't re-add profession specialties!
|
||||||
|
if (SpellInfo const* triggeredInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[i].TriggerSpell))
|
||||||
|
if (triggeredInfo->Effects[0].Effect == SPELL_EFFECT_TRADE_SKILL)
|
||||||
|
break; // pussywizard: break and not cast the spell (found is false)
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (quest->GetRewSpell() > 0)
|
|
||||||
|
// xinef: we know the spell, continue
|
||||||
|
if (!found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bot->CastSpell(bot, spellId, true);
|
||||||
|
|
||||||
|
// Check if RewardDisplaySpell is set to output the proper spell learned
|
||||||
|
// after processing quests. Output the original RewardSpell otherwise.
|
||||||
|
uint32 rewSpellId = quest->GetRewSpell();
|
||||||
|
if (rewSpellId)
|
||||||
{
|
{
|
||||||
LearnSpell(quest->GetRewSpell(), out);
|
if (SpellInfo const* rewSpellInfo = sSpellMgr->GetSpellInfo(rewSpellId))
|
||||||
|
{
|
||||||
|
*out << FormatSpell(rewSpellInfo) << ", ";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*out << FormatSpell(spellInfo) << ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,42 +164,9 @@ std::string const AutoMaintenanceOnLevelupAction::FormatSpell(SpellInfo const* s
|
|||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoMaintenanceOnLevelupAction::LearnSpell(uint32 spellId, std::ostringstream* out)
|
|
||||||
{
|
|
||||||
SpellInfo const* proto = sSpellMgr->GetSpellInfo(spellId);
|
|
||||||
if (!proto)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool learned = false;
|
|
||||||
for (uint8 j = 0; j < 3; ++j)
|
|
||||||
{
|
|
||||||
if (proto->Effects[j].Effect == SPELL_EFFECT_LEARN_SPELL)
|
|
||||||
{
|
|
||||||
uint32 learnedSpell = proto->Effects[j].TriggerSpell;
|
|
||||||
|
|
||||||
if (!bot->HasSpell(learnedSpell))
|
|
||||||
{
|
|
||||||
bot->learnSpell(learnedSpell);
|
|
||||||
*out << FormatSpell(sSpellMgr->GetSpellInfo(learnedSpell)) << ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
learned = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!learned)
|
|
||||||
{
|
|
||||||
if (!bot->HasSpell(spellId))
|
|
||||||
{
|
|
||||||
bot->learnSpell(spellId);
|
|
||||||
*out << FormatSpell(proto) << ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip()
|
void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip()
|
||||||
{
|
{
|
||||||
if (!sPlayerbotAIConfig->autoUpgradeEquip || !sRandomPlayerbotMgr->IsRandomBot(bot))
|
if (!sPlayerbotAIConfig.autoUpgradeEquip || !sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PlayerbotFactory factory(bot, bot->GetLevel());
|
PlayerbotFactory factory(bot, bot->GetLevel());
|
||||||
@@ -170,9 +180,9 @@ void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip()
|
|||||||
factory.InitConsumables();
|
factory.InitConsumables();
|
||||||
factory.InitPotions();
|
factory.InitPotions();
|
||||||
|
|
||||||
if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel)
|
if (!sPlayerbotAIConfig.equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig.equipmentPersistenceLevel)
|
||||||
{
|
{
|
||||||
if (sPlayerbotAIConfig->incrementalGearInit)
|
if (sPlayerbotAIConfig.incrementalGearInit)
|
||||||
factory.InitEquipment(true);
|
factory.InitEquipment(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,6 @@ protected:
|
|||||||
void LearnSpells(std::ostringstream* out);
|
void LearnSpells(std::ostringstream* out);
|
||||||
void LearnTrainerSpells(std::ostringstream* out);
|
void LearnTrainerSpells(std::ostringstream* out);
|
||||||
void LearnQuestSpells(std::ostringstream* out);
|
void LearnQuestSpells(std::ostringstream* out);
|
||||||
void LearnSpell(uint32 spellId, std::ostringstream* out);
|
|
||||||
std::string const FormatSpell(SpellInfo const* sInfo);
|
std::string const FormatSpell(SpellInfo const* sInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ bool BGJoinAction::gatherArenaTeam(ArenaType type)
|
|||||||
// continue;
|
// continue;
|
||||||
|
|
||||||
if (offline)
|
if (offline)
|
||||||
sRandomPlayerbotMgr->AddPlayerBot(itr->Guid, 0);
|
sRandomPlayerbotMgr.AddPlayerBot(itr->Guid, 0);
|
||||||
|
|
||||||
if (member)
|
if (member)
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,7 @@ bool BGJoinAction::gatherArenaTeam(ArenaType type)
|
|||||||
if (member->GetGroup() && memberBotAI->HasRealPlayerMaster())
|
if (member->GetGroup() && memberBotAI->HasRealPlayerMaster())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!sPlayerbotAIConfig->IsInRandomAccountList(member->GetSession()->GetAccountId()))
|
if (!sPlayerbotAIConfig.IsInRandomAccountList(member->GetSession()->GetAccountId()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (member->IsInCombat())
|
if (member->IsInCombat())
|
||||||
@@ -250,13 +250,13 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun
|
|||||||
TeamSize = (uint32)type;
|
TeamSize = (uint32)type;
|
||||||
|
|
||||||
// Check if bots should join Rated Arena (Only captains can queue)
|
// Check if bots should join Rated Arena (Only captains can queue)
|
||||||
uint32 ratedArenaBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount;
|
uint32 ratedArenaBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount;
|
||||||
uint32 ratedArenaPlayerCount =
|
uint32 ratedArenaPlayerCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount;
|
||||||
uint32 ratedArenaInstanceCount =
|
uint32 ratedArenaInstanceCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaInstanceCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaInstanceCount;
|
||||||
uint32 activeRatedArenaQueue =
|
uint32 activeRatedArenaQueue =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeRatedArenaQueue;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeRatedArenaQueue;
|
||||||
|
|
||||||
bool isRated = (ratedArenaBotCount + ratedArenaPlayerCount) <
|
bool isRated = (ratedArenaBotCount + ratedArenaPlayerCount) <
|
||||||
(BracketSize * (activeRatedArenaQueue + ratedArenaInstanceCount));
|
(BracketSize * (activeRatedArenaQueue + ratedArenaInstanceCount));
|
||||||
@@ -265,7 +265,7 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun
|
|||||||
{
|
{
|
||||||
if (sArenaTeamMgr->GetArenaTeamByCaptain(bot->GetGUID(), type))
|
if (sArenaTeamMgr->GetArenaTeamByCaptain(bot->GetGUID(), type))
|
||||||
{
|
{
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount += TeamSize;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount += TeamSize;
|
||||||
ratedList.push_back(queueTypeId);
|
ratedList.push_back(queueTypeId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -274,13 +274,13 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun
|
|||||||
// Check if bots should join Skirmish Arena
|
// Check if bots should join Skirmish Arena
|
||||||
// We have extra bots queue because same faction can vs each other but can't be in the same group.
|
// We have extra bots queue because same faction can vs each other but can't be in the same group.
|
||||||
uint32 skirmishArenaBotCount =
|
uint32 skirmishArenaBotCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount;
|
||||||
uint32 skirmishArenaPlayerCount =
|
uint32 skirmishArenaPlayerCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount;
|
||||||
uint32 skirmishArenaInstanceCount =
|
uint32 skirmishArenaInstanceCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaInstanceCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaInstanceCount;
|
||||||
uint32 activeSkirmishArenaQueue =
|
uint32 activeSkirmishArenaQueue =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeSkirmishArenaQueue;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeSkirmishArenaQueue;
|
||||||
uint32 maxRequiredSkirmishBots = BracketSize * (activeSkirmishArenaQueue + skirmishArenaInstanceCount);
|
uint32 maxRequiredSkirmishBots = BracketSize * (activeSkirmishArenaQueue + skirmishArenaInstanceCount);
|
||||||
if (maxRequiredSkirmishBots != 0)
|
if (maxRequiredSkirmishBots != 0)
|
||||||
maxRequiredSkirmishBots = maxRequiredSkirmishBots + TeamSize;
|
maxRequiredSkirmishBots = maxRequiredSkirmishBots + TeamSize;
|
||||||
@@ -294,12 +294,12 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if bots should join Battleground
|
// Check if bots should join Battleground
|
||||||
uint32 bgAllianceBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount;
|
uint32 bgAllianceBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount;
|
||||||
uint32 bgAlliancePlayerCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAlliancePlayerCount;
|
uint32 bgAlliancePlayerCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAlliancePlayerCount;
|
||||||
uint32 bgHordeBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordeBotCount;
|
uint32 bgHordeBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordeBotCount;
|
||||||
uint32 bgHordePlayerCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordePlayerCount;
|
uint32 bgHordePlayerCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordePlayerCount;
|
||||||
uint32 activeBgQueue = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeBgQueue;
|
uint32 activeBgQueue = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeBgQueue;
|
||||||
uint32 bgInstanceCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgInstanceCount;
|
uint32 bgInstanceCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgInstanceCount;
|
||||||
|
|
||||||
if (teamId == TEAM_ALLIANCE)
|
if (teamId == TEAM_ALLIANCE)
|
||||||
{
|
{
|
||||||
@@ -318,7 +318,7 @@ bool BGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battlegroun
|
|||||||
bool BGJoinAction::isUseful()
|
bool BGJoinAction::isUseful()
|
||||||
{
|
{
|
||||||
// do not try if BG bots disabled
|
// do not try if BG bots disabled
|
||||||
if (!sPlayerbotAIConfig->randomBotJoinBG)
|
if (!sPlayerbotAIConfig.randomBotJoinBG)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// can't queue while in BG/Arena
|
// can't queue while in BG/Arena
|
||||||
@@ -440,7 +440,7 @@ bool BGJoinAction::JoinQueue(uint32 type)
|
|||||||
|
|
||||||
// get battlemaster
|
// get battlemaster
|
||||||
// Unit* unit = botAI->GetUnit(AI_VALUE2(CreatureData const*, "bg master", bgTypeId));
|
// Unit* unit = botAI->GetUnit(AI_VALUE2(CreatureData const*, "bg master", bgTypeId));
|
||||||
Unit* unit = botAI->GetUnit(sRandomPlayerbotMgr->GetBattleMasterGUID(bot, bgTypeId));
|
Unit* unit = botAI->GetUnit(sRandomPlayerbotMgr.GetBattleMasterGUID(bot, bgTypeId));
|
||||||
if (!unit && isArena)
|
if (!unit && isArena)
|
||||||
{
|
{
|
||||||
botAI->GetAiObjectContext()->GetValue<uint32>("bg type")->Set(0);
|
botAI->GetAiObjectContext()->GetValue<uint32>("bg type")->Set(0);
|
||||||
@@ -450,7 +450,7 @@ bool BGJoinAction::JoinQueue(uint32 type)
|
|||||||
|
|
||||||
// This breaks groups as refresh includes a remove from group function call.
|
// This breaks groups as refresh includes a remove from group function call.
|
||||||
// refresh food/regs
|
// refresh food/regs
|
||||||
// sRandomPlayerbotMgr->Refresh(bot);
|
// sRandomPlayerbotMgr.Refresh(bot);
|
||||||
|
|
||||||
bool joinAsGroup = bot->GetGroup() && bot->GetGroup()->GetLeaderGUID() == bot->GetGUID();
|
bool joinAsGroup = bot->GetGroup() && bot->GetGroup()->GetLeaderGUID() == bot->GetGUID();
|
||||||
|
|
||||||
@@ -523,23 +523,23 @@ bool BGJoinAction::JoinQueue(uint32 type)
|
|||||||
{
|
{
|
||||||
if (!isRated)
|
if (!isRated)
|
||||||
{
|
{
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount++;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!joinAsGroup)
|
else if (!joinAsGroup)
|
||||||
{
|
{
|
||||||
if (teamId == TEAM_ALLIANCE)
|
if (teamId == TEAM_ALLIANCE)
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount++;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount++;
|
||||||
else
|
else
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordeBotCount++;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordeBotCount++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (teamId == TEAM_ALLIANCE)
|
if (teamId == TEAM_ALLIANCE)
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount +=
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount +=
|
||||||
bot->GetGroup()->GetMembersCount();
|
bot->GetGroup()->GetMembersCount();
|
||||||
else
|
else
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordeBotCount +=
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordeBotCount +=
|
||||||
bot->GetGroup()->GetMembersCount();
|
bot->GetGroup()->GetMembersCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,13 +588,13 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg
|
|||||||
TeamSize = (uint32)type;
|
TeamSize = (uint32)type;
|
||||||
|
|
||||||
// Check if bots should join Rated Arena (Only captains can queue)
|
// Check if bots should join Rated Arena (Only captains can queue)
|
||||||
uint32 ratedArenaBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount;
|
uint32 ratedArenaBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount;
|
||||||
uint32 ratedArenaPlayerCount =
|
uint32 ratedArenaPlayerCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount;
|
||||||
uint32 ratedArenaInstanceCount =
|
uint32 ratedArenaInstanceCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaInstanceCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaInstanceCount;
|
||||||
uint32 activeRatedArenaQueue =
|
uint32 activeRatedArenaQueue =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeRatedArenaQueue;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeRatedArenaQueue;
|
||||||
|
|
||||||
bool isRated = (ratedArenaBotCount + ratedArenaPlayerCount) <
|
bool isRated = (ratedArenaBotCount + ratedArenaPlayerCount) <
|
||||||
(BracketSize * (activeRatedArenaQueue + ratedArenaInstanceCount));
|
(BracketSize * (activeRatedArenaQueue + ratedArenaInstanceCount));
|
||||||
@@ -603,7 +603,7 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg
|
|||||||
{
|
{
|
||||||
if (sArenaTeamMgr->GetArenaTeamByCaptain(bot->GetGUID(), type))
|
if (sArenaTeamMgr->GetArenaTeamByCaptain(bot->GetGUID(), type))
|
||||||
{
|
{
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount += TeamSize;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaBotCount += TeamSize;
|
||||||
ratedList.push_back(queueTypeId);
|
ratedList.push_back(queueTypeId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -612,13 +612,13 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg
|
|||||||
// Check if bots should join Skirmish Arena
|
// Check if bots should join Skirmish Arena
|
||||||
// We have extra bots queue because same faction can vs each other but can't be in the same group.
|
// We have extra bots queue because same faction can vs each other but can't be in the same group.
|
||||||
uint32 skirmishArenaBotCount =
|
uint32 skirmishArenaBotCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaBotCount;
|
||||||
uint32 skirmishArenaPlayerCount =
|
uint32 skirmishArenaPlayerCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount;
|
||||||
uint32 skirmishArenaInstanceCount =
|
uint32 skirmishArenaInstanceCount =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaInstanceCount;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaInstanceCount;
|
||||||
uint32 activeSkirmishArenaQueue =
|
uint32 activeSkirmishArenaQueue =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeSkirmishArenaQueue;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeSkirmishArenaQueue;
|
||||||
uint32 maxRequiredSkirmishBots = BracketSize * (activeSkirmishArenaQueue + skirmishArenaInstanceCount);
|
uint32 maxRequiredSkirmishBots = BracketSize * (activeSkirmishArenaQueue + skirmishArenaInstanceCount);
|
||||||
if (maxRequiredSkirmishBots != 0)
|
if (maxRequiredSkirmishBots != 0)
|
||||||
maxRequiredSkirmishBots = maxRequiredSkirmishBots + TeamSize;
|
maxRequiredSkirmishBots = maxRequiredSkirmishBots + TeamSize;
|
||||||
@@ -632,12 +632,12 @@ bool FreeBGJoinAction::shouldJoinBg(BattlegroundQueueTypeId queueTypeId, Battleg
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if bots should join Battleground
|
// Check if bots should join Battleground
|
||||||
uint32 bgAllianceBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount;
|
uint32 bgAllianceBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAllianceBotCount;
|
||||||
uint32 bgAlliancePlayerCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgAlliancePlayerCount;
|
uint32 bgAlliancePlayerCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgAlliancePlayerCount;
|
||||||
uint32 bgHordeBotCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordeBotCount;
|
uint32 bgHordeBotCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordeBotCount;
|
||||||
uint32 bgHordePlayerCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgHordePlayerCount;
|
uint32 bgHordePlayerCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgHordePlayerCount;
|
||||||
uint32 activeBgQueue = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].activeBgQueue;
|
uint32 activeBgQueue = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].activeBgQueue;
|
||||||
uint32 bgInstanceCount = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].bgInstanceCount;
|
uint32 bgInstanceCount = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].bgInstanceCount;
|
||||||
|
|
||||||
if (teamId == TEAM_ALLIANCE)
|
if (teamId == TEAM_ALLIANCE)
|
||||||
{
|
{
|
||||||
@@ -670,7 +670,7 @@ bool BGLeaveAction::Execute(Event event)
|
|||||||
uint16 unk = 0x1F90;
|
uint16 unk = 0x1F90;
|
||||||
uint8 unk2 = 0x0;
|
uint8 unk2 = 0x0;
|
||||||
bool isArena = false;
|
bool isArena = false;
|
||||||
bool IsRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot);
|
bool IsRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot);
|
||||||
|
|
||||||
ArenaType arenaType = ArenaType(BattlegroundMgr::BGArenaType(queueTypeId));
|
ArenaType arenaType = ArenaType(BattlegroundMgr::BGArenaType(queueTypeId));
|
||||||
if (arenaType)
|
if (arenaType)
|
||||||
@@ -709,7 +709,7 @@ bool BGStatusAction::LeaveBG(PlayerbotAI* botAI)
|
|||||||
if (!bg)
|
if (!bg)
|
||||||
return false;
|
return false;
|
||||||
bool isArena = bg->isArena();
|
bool isArena = bg->isArena();
|
||||||
bool isRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot);
|
bool isRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot);
|
||||||
|
|
||||||
if (isRandomBot)
|
if (isRandomBot)
|
||||||
botAI->SetMaster(nullptr);
|
botAI->SetMaster(nullptr);
|
||||||
@@ -805,7 +805,7 @@ bool BGStatusAction::Execute(Event event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot);
|
bool IsRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot);
|
||||||
BattlegroundQueueTypeId queueTypeId = bot->GetBattlegroundQueueTypeId(QueueSlot);
|
BattlegroundQueueTypeId queueTypeId = bot->GetBattlegroundQueueTypeId(QueueSlot);
|
||||||
BattlegroundTypeId _bgTypeId = BattlegroundMgr::BGTemplateId(queueTypeId);
|
BattlegroundTypeId _bgTypeId = BattlegroundMgr::BGTemplateId(queueTypeId);
|
||||||
if (!queueTypeId)
|
if (!queueTypeId)
|
||||||
@@ -958,10 +958,10 @@ bool BGStatusAction::Execute(Event event)
|
|||||||
//TeamId teamId = bot->GetTeamId(); //not used, line marked for removal.
|
//TeamId teamId = bot->GetTeamId(); //not used, line marked for removal.
|
||||||
bool realPlayers = false;
|
bool realPlayers = false;
|
||||||
if (isRated)
|
if (isRated)
|
||||||
realPlayers = sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount > 0;
|
realPlayers = sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].ratedArenaPlayerCount > 0;
|
||||||
else
|
else
|
||||||
realPlayers =
|
realPlayers =
|
||||||
sRandomPlayerbotMgr->BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount > 0;
|
sRandomPlayerbotMgr.BattlegroundData[queueTypeId][bracketId].skirmishArenaPlayerCount > 0;
|
||||||
|
|
||||||
if (realPlayers)
|
if (realPlayers)
|
||||||
return false;
|
return false;
|
||||||
@@ -1276,7 +1276,7 @@ static std::pair<uint32, uint32> IC_AttackObjectives[] = {
|
|||||||
// useful commands for fixing BG bugs and checking waypoints/paths
|
// useful commands for fixing BG bugs and checking waypoints/paths
|
||||||
bool BGTactics::HandleConsoleCommand(ChatHandler* handler, char const* args)
|
bool BGTactics::HandleConsoleCommand(ChatHandler* handler, char const* args)
|
||||||
{
|
{
|
||||||
if (!sPlayerbotAIConfig->enabled)
|
if (!sPlayerbotAIConfig.enabled)
|
||||||
{
|
{
|
||||||
handler->PSendSysMessage("|cffff0000Playerbot system is currently disabled!");
|
handler->PSendSysMessage("|cffff0000Playerbot system is currently disabled!");
|
||||||
return true;
|
return true;
|
||||||
@@ -2219,7 +2219,7 @@ bool BGTactics::selectObjective(bool reset)
|
|||||||
if (urand(0, 99) < 20 && teamFC)
|
if (urand(0, 99) < 20 && teamFC)
|
||||||
{
|
{
|
||||||
target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ());
|
target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ());
|
||||||
if (sServerFacade->GetDistance2d(bot, teamFC) < 33.0f)
|
if (ServerFacade::instance().GetDistance2d(bot, teamFC) < 33.0f)
|
||||||
Follow(teamFC);
|
Follow(teamFC);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2263,7 +2263,7 @@ bool BGTactics::selectObjective(bool reset)
|
|||||||
if (urand(0, 99) < 70)
|
if (urand(0, 99) < 70)
|
||||||
{
|
{
|
||||||
target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ());
|
target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ());
|
||||||
if (sServerFacade->GetDistance2d(bot, teamFC) < 33.0f)
|
if (ServerFacade::instance().GetDistance2d(bot, teamFC) < 33.0f)
|
||||||
Follow(teamFC);
|
Follow(teamFC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2284,7 +2284,7 @@ bool BGTactics::selectObjective(bool reset)
|
|||||||
{
|
{
|
||||||
// Assist own FC if not pursuing enemy FC
|
// Assist own FC if not pursuing enemy FC
|
||||||
target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ());
|
target.Relocate(teamFC->GetPositionX(), teamFC->GetPositionY(), teamFC->GetPositionZ());
|
||||||
if (sServerFacade->GetDistance2d(bot, teamFC) < 33.0f)
|
if (ServerFacade::instance().GetDistance2d(bot, teamFC) < 33.0f)
|
||||||
Follow(teamFC);
|
Follow(teamFC);
|
||||||
}
|
}
|
||||||
else if (urand(0, 99) < 5)
|
else if (urand(0, 99) < 5)
|
||||||
@@ -3197,11 +3197,11 @@ bool BGTactics::moveToObjective(bool ignoreDist)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ignoreDist && sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, pos.x, pos.y), 100.0f))
|
if (!ignoreDist && ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, pos.x, pos.y), 100.0f))
|
||||||
{
|
{
|
||||||
// std::ostringstream out;
|
// std::ostringstream out;
|
||||||
// out << "It is too far away! " << pos.x << ", " << pos.y << ", Distance: " <<
|
// out << "It is too far away! " << pos.x << ", " << pos.y << ", Distance: " <<
|
||||||
// sServerFacade->GetDistance2d(bot, pos.x, pos.y); bot->Say(out.str(), LANG_UNIVERSAL);
|
// ServerFacade::instance().GetDistance2d(bot, pos.x, pos.y); bot->Say(out.str(), LANG_UNIVERSAL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3213,7 +3213,7 @@ bool BGTactics::moveToObjective(bool ignoreDist)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// std::ostringstream out; out << "Moving to objective " << pos.x << ", " << pos.y << ", Distance: " <<
|
// std::ostringstream out; out << "Moving to objective " << pos.x << ", " << pos.y << ", Distance: " <<
|
||||||
// sServerFacade->GetDistance2d(bot, pos.x, pos.y); bot->Say(out.str(), LANG_UNIVERSAL);
|
// ServerFacade::instance().GetDistance2d(bot, pos.x, pos.y); bot->Say(out.str(), LANG_UNIVERSAL);
|
||||||
|
|
||||||
// dont increase from 1.5 will cause bugs with horde capping AV towers
|
// dont increase from 1.5 will cause bugs with horde capping AV towers
|
||||||
return MoveNear(bot->GetMapId(), pos.x, pos.y, pos.z, 1.5f);
|
return MoveNear(bot->GetMapId(), pos.x, pos.y, pos.z, 1.5f);
|
||||||
@@ -3433,7 +3433,7 @@ bool BGTactics::moveToObjectiveWp(BattleBotPath* const& currentPath, uint32 curr
|
|||||||
// out << "WP: ";
|
// out << "WP: ";
|
||||||
// reverse ? out << currPoint << " <<< -> " << nPoint : out << currPoint << ">>> ->" << nPoint;
|
// reverse ? out << currPoint << " <<< -> " << nPoint : out << currPoint << ">>> ->" << nPoint;
|
||||||
// out << ", " << nextPoint.x << ", " << nextPoint.y << " Path Size: " << currentPath->size() << ", Dist: " <<
|
// out << ", " << nextPoint.x << ", " << nextPoint.y << " Path Size: " << currentPath->size() << ", Dist: " <<
|
||||||
// sServerFacade->GetDistance2d(bot, nextPoint.x, nextPoint.y); bot->Say(out.str(), LANG_UNIVERSAL);
|
// ServerFacade::instance().GetDistance2d(bot, nextPoint.x, nextPoint.y); bot->Say(out.str(), LANG_UNIVERSAL);
|
||||||
|
|
||||||
return MoveTo(bot->GetMapId(), nextPoint.x + frand(-2, 2), nextPoint.y + frand(-2, 2), nextPoint.z);
|
return MoveTo(bot->GetMapId(), nextPoint.x + frand(-2, 2), nextPoint.y + frand(-2, 2), nextPoint.z);
|
||||||
}
|
}
|
||||||
@@ -4039,9 +4039,9 @@ bool BGTactics::useBuff()
|
|||||||
if (closeObjects.empty())
|
if (closeObjects.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool needRegen = bot->GetHealthPct() < sPlayerbotAIConfig->mediumHealth ||
|
bool needRegen = bot->GetHealthPct() < sPlayerbotAIConfig.mediumHealth ||
|
||||||
(AI_VALUE2(bool, "has mana", "self target") &&
|
(AI_VALUE2(bool, "has mana", "self target") &&
|
||||||
AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->mediumMana);
|
AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.mediumMana);
|
||||||
bool needSpeed = (bgType != BATTLEGROUND_WS || bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) ||
|
bool needSpeed = (bgType != BATTLEGROUND_WS || bot->HasAura(BG_WS_SPELL_WARSONG_FLAG) ||
|
||||||
bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL)) ||
|
bot->HasAura(BG_WS_SPELL_SILVERWING_FLAG) || bot->HasAura(BG_EY_NETHERSTORM_FLAG_SPELL)) ||
|
||||||
!(teamFlagTaken() || flagTaken());
|
!(teamFlagTaken() || flagTaken());
|
||||||
@@ -4057,7 +4057,7 @@ bool BGTactics::useBuff()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// use speed buff only if close
|
// use speed buff only if close
|
||||||
if (sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, go),
|
if (ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, go),
|
||||||
go->GetEntry() == Buff_Entries[0] ? 20.0f : 50.0f))
|
go->GetEntry() == Buff_Entries[0] ? 20.0f : 50.0f))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -4107,7 +4107,7 @@ uint32 BGTactics::getPlayersInArea(TeamId teamId, Position point, float range, b
|
|||||||
if (!combat && player->IsInCombat())
|
if (!combat && player->IsInCombat())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sServerFacade->GetDistance2d(player, point.GetPositionX(), point.GetPositionY()) < range)
|
if (ServerFacade::instance().GetDistance2d(player, point.GetPositionX(), point.GetPositionY()) < range)
|
||||||
++defCount;
|
++defCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4191,9 +4191,9 @@ bool BGTactics::IsLockedInsideKeep()
|
|||||||
// get closest portal
|
// get closest portal
|
||||||
if (bot->GetTeamId() == TEAM_ALLIANCE && go->GetEntry() == GO_TELEPORTER_4)
|
if (bot->GetTeamId() == TEAM_ALLIANCE && go->GetEntry() == GO_TELEPORTER_4)
|
||||||
{
|
{
|
||||||
float tempDist = sServerFacade->GetDistance2d(bot, go->GetPositionX(), go->GetPositionY());
|
float tempDist = ServerFacade::instance().GetDistance2d(bot, go->GetPositionX(), go->GetPositionY());
|
||||||
|
|
||||||
if (sServerFacade->IsDistanceLessThan(tempDist, closestDistance))
|
if (ServerFacade::instance().IsDistanceLessThan(tempDist, closestDistance))
|
||||||
{
|
{
|
||||||
closestDistance = tempDist;
|
closestDistance = tempDist;
|
||||||
closestPortal = go;
|
closestPortal = go;
|
||||||
@@ -4204,9 +4204,9 @@ bool BGTactics::IsLockedInsideKeep()
|
|||||||
// get closest portal
|
// get closest portal
|
||||||
if (bot->GetTeamId() == TEAM_HORDE && go->GetEntry() == GO_TELEPORTER_2)
|
if (bot->GetTeamId() == TEAM_HORDE && go->GetEntry() == GO_TELEPORTER_2)
|
||||||
{
|
{
|
||||||
float tempDist = sServerFacade->GetDistance2d(bot, go->GetPositionX(), go->GetPositionY());
|
float tempDist = ServerFacade::instance().GetDistance2d(bot, go->GetPositionX(), go->GetPositionY());
|
||||||
|
|
||||||
if (sServerFacade->IsDistanceLessThan(tempDist, closestDistance))
|
if (ServerFacade::instance().IsDistanceLessThan(tempDist, closestDistance))
|
||||||
{
|
{
|
||||||
closestDistance = tempDist;
|
closestDistance = tempDist;
|
||||||
closestPortal = go;
|
closestPortal = go;
|
||||||
@@ -4253,7 +4253,7 @@ bool ArenaTactics::Execute(Event event)
|
|||||||
{
|
{
|
||||||
if (!bot->InBattleground())
|
if (!bot->InBattleground())
|
||||||
{
|
{
|
||||||
bool IsRandomBot = sRandomPlayerbotMgr->IsRandomBot(bot->GetGUID().GetCounter());
|
bool IsRandomBot = sRandomPlayerbotMgr.IsRandomBot(bot->GetGUID().GetCounter());
|
||||||
botAI->ChangeStrategy("-arena", BOT_STATE_COMBAT);
|
botAI->ChangeStrategy("-arena", BOT_STATE_COMBAT);
|
||||||
botAI->ChangeStrategy("-arena", BOT_STATE_NON_COMBAT);
|
botAI->ChangeStrategy("-arena", BOT_STATE_NON_COMBAT);
|
||||||
botAI->ResetStrategies(!IsRandomBot);
|
botAI->ResetStrategies(!IsRandomBot);
|
||||||
@@ -224,42 +224,36 @@ bool BuyAction::Execute(Event event)
|
|||||||
|
|
||||||
bool BuyAction::BuyItem(VendorItemData const* tItems, ObjectGuid vendorguid, ItemTemplate const* proto)
|
bool BuyAction::BuyItem(VendorItemData const* tItems, ObjectGuid vendorguid, ItemTemplate const* proto)
|
||||||
{
|
{
|
||||||
uint32 oldCount = AI_VALUE2(uint32, "item count", proto->Name1);
|
if (!tItems || !proto)
|
||||||
|
|
||||||
if (!tItems)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint32 itemId = proto->ItemId;
|
uint32 itemId = proto->ItemId;
|
||||||
for (uint32 slot = 0; slot < tItems->GetItemCount(); slot++)
|
uint32 oldCount = bot->GetItemCount(itemId, false);
|
||||||
|
|
||||||
|
for (uint32 slot = 0; slot < tItems->GetItemCount(); ++slot)
|
||||||
{
|
{
|
||||||
if (tItems->GetItem(slot)->item == itemId)
|
if (tItems->GetItem(slot)->item != itemId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32 botMoney = bot->GetMoney();
|
||||||
|
if (botAI->HasCheat(BotCheatMask::gold))
|
||||||
|
bot->SetMoney(10000000);
|
||||||
|
|
||||||
|
bot->BuyItemFromVendorSlot(vendorguid, slot, itemId, 1, NULL_BAG, NULL_SLOT);
|
||||||
|
|
||||||
|
if (botAI->HasCheat(BotCheatMask::gold))
|
||||||
|
bot->SetMoney(botMoney);
|
||||||
|
|
||||||
|
uint32 newCount = bot->GetItemCount(itemId, false);
|
||||||
|
if (newCount > oldCount)
|
||||||
{
|
{
|
||||||
uint32 botMoney = bot->GetMoney();
|
std::ostringstream out;
|
||||||
if (botAI->HasCheat(BotCheatMask::gold))
|
out << "Buying " << ChatHelper::FormatItem(proto);
|
||||||
{
|
botAI->TellMaster(out.str());
|
||||||
bot->SetMoney(10000000);
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
bot->BuyItemFromVendorSlot(vendorguid, slot, itemId, 1, NULL_BAG, NULL_SLOT);
|
|
||||||
|
|
||||||
if (botAI->HasCheat(BotCheatMask::gold))
|
|
||||||
{
|
|
||||||
bot->SetMoney(botMoney);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldCount <
|
|
||||||
AI_VALUE2(
|
|
||||||
uint32, "item count",
|
|
||||||
proto->Name1)) // BuyItem Always returns false (unless unique) so we have to check the item counts.
|
|
||||||
{
|
|
||||||
std::ostringstream out;
|
|
||||||
out << "Buying " << ChatHelper::FormatItem(proto);
|
|
||||||
botAI->TellMaster(out.str());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -130,10 +130,10 @@ bool CastCustomSpellAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target != bot && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target, sPlayerbotAIConfig->sightDistance))
|
if (target != bot && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target, sPlayerbotAIConfig.sightDistance))
|
||||||
{
|
{
|
||||||
sServerFacade->SetFacingTo(bot, target);
|
ServerFacade::instance().SetFacingTo(bot, target);
|
||||||
botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay);
|
botAI->SetNextCheckDelay(sPlayerbotAIConfig.reactDelay);
|
||||||
|
|
||||||
msg << "cast " << text;
|
msg << "cast " << text;
|
||||||
botAI->HandleCommand(CHAT_MSG_WHISPER, msg.str(), master);
|
botAI->HandleCommand(CHAT_MSG_WHISPER, msg.str(), master);
|
||||||
@@ -286,7 +286,7 @@ bool CastRandomSpellAction::Execute(Event event)
|
|||||||
|
|
||||||
if (isCast)
|
if (isCast)
|
||||||
{
|
{
|
||||||
if (MultiCast && ((wo && bot->HasInArc(CAST_ANGLE_IN_FRONT, wo, sPlayerbotAIConfig->sightDistance))))
|
if (MultiCast && ((wo && bot->HasInArc(CAST_ANGLE_IN_FRONT, wo, sPlayerbotAIConfig.sightDistance))))
|
||||||
{
|
{
|
||||||
std::ostringstream cmd;
|
std::ostringstream cmd;
|
||||||
cmd << "castnc " << chat->FormatWorldobject(wo) + " " << spellId << " " << 19;
|
cmd << "castnc " << chat->FormatWorldobject(wo) + " " << spellId << " " << 19;
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "ChangeStrategyAction.h"
|
#include "ChangeStrategyAction.h"
|
||||||
|
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "PlayerbotDbStore.h"
|
#include "PlayerbotRepository.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
|
||||||
bool ChangeCombatStrategyAction::Execute(Event event)
|
bool ChangeCombatStrategyAction::Execute(Event event)
|
||||||
@@ -24,7 +24,7 @@ bool ChangeCombatStrategyAction::Execute(Event event)
|
|||||||
case '+':
|
case '+':
|
||||||
case '-':
|
case '-':
|
||||||
case '~':
|
case '~':
|
||||||
sPlayerbotDbStore->Save(botAI);
|
PlayerbotRepository::instance().Save(botAI);
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
break;
|
break;
|
||||||
@@ -40,7 +40,7 @@ bool ChangeNonCombatStrategyAction::Execute(Event event)
|
|||||||
std::string const text = event.getParam();
|
std::string const text = event.getParam();
|
||||||
|
|
||||||
uint32 account = bot->GetSession()->GetAccountId();
|
uint32 account = bot->GetSession()->GetAccountId();
|
||||||
if (sPlayerbotAIConfig->IsInRandomAccountList(account) && botAI->GetMaster() &&
|
if (sPlayerbotAIConfig.IsInRandomAccountList(account) && botAI->GetMaster() &&
|
||||||
botAI->GetMaster()->GetSession()->GetSecurity() < SEC_GAMEMASTER)
|
botAI->GetMaster()->GetSession()->GetSecurity() < SEC_GAMEMASTER)
|
||||||
{
|
{
|
||||||
if (text.find("loot") != std::string::npos || text.find("gather") != std::string::npos)
|
if (text.find("loot") != std::string::npos || text.find("gather") != std::string::npos)
|
||||||
@@ -62,7 +62,7 @@ bool ChangeNonCombatStrategyAction::Execute(Event event)
|
|||||||
case '+':
|
case '+':
|
||||||
case '-':
|
case '-':
|
||||||
case '~':
|
case '~':
|
||||||
sPlayerbotDbStore->Save(botAI);
|
PlayerbotRepository::instance().Save(botAI);
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
break;
|
break;
|
||||||
@@ -110,20 +110,20 @@ std::string ChangeTalentsAction::SpecList()
|
|||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
for (int specNo = 0; specNo < MAX_SPECNO; ++specNo)
|
for (int specNo = 0; specNo < MAX_SPECNO; ++specNo)
|
||||||
{
|
{
|
||||||
if (sPlayerbotAIConfig->premadeSpecName[cls][specNo].size() == 0)
|
if (sPlayerbotAIConfig.premadeSpecName[cls][specNo].size() == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
specFound++;
|
specFound++;
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
std::vector<std::vector<uint32>> parsed = sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][80];
|
std::vector<std::vector<uint32>> parsed = sPlayerbotAIConfig.parsedSpecLinkOrder[cls][specNo][80];
|
||||||
std::unordered_map<int, int> tabCount;
|
std::unordered_map<int, int> tabCount;
|
||||||
tabCount[0] = tabCount[1] = tabCount[2] = 0;
|
tabCount[0] = tabCount[1] = tabCount[2] = 0;
|
||||||
for (auto& item : parsed)
|
for (auto& item : parsed)
|
||||||
{
|
{
|
||||||
tabCount[item[0]] += item[3];
|
tabCount[item[0]] += item[3];
|
||||||
}
|
}
|
||||||
out << specFound << ". " << sPlayerbotAIConfig->premadeSpecName[cls][specNo] << " (";
|
out << specFound << ". " << sPlayerbotAIConfig.premadeSpecName[cls][specNo] << " (";
|
||||||
out << tabCount[0] << "-" << tabCount[1] << "-" << tabCount[2] << ")";
|
out << tabCount[0] << "-" << tabCount[1] << "-" << tabCount[2] << ")";
|
||||||
botAI->TellMasterNoFacing(out.str());
|
botAI->TellMasterNoFacing(out.str());
|
||||||
}
|
}
|
||||||
@@ -137,11 +137,11 @@ std::string ChangeTalentsAction::SpecPick(std::string param)
|
|||||||
// int specFound = 0; //not used, line marked for removal.
|
// int specFound = 0; //not used, line marked for removal.
|
||||||
for (int specNo = 0; specNo < MAX_SPECNO; ++specNo)
|
for (int specNo = 0; specNo < MAX_SPECNO; ++specNo)
|
||||||
{
|
{
|
||||||
if (sPlayerbotAIConfig->premadeSpecName[cls][specNo].size() == 0)
|
if (sPlayerbotAIConfig.premadeSpecName[cls][specNo].size() == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sPlayerbotAIConfig->premadeSpecName[cls][specNo] == param)
|
if (sPlayerbotAIConfig.premadeSpecName[cls][specNo] == param)
|
||||||
{
|
{
|
||||||
PlayerbotFactory::InitTalentsBySpecNo(bot, specNo, true);
|
PlayerbotFactory::InitTalentsBySpecNo(bot, specNo, true);
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ std::string ChangeTalentsAction::SpecPick(std::string param)
|
|||||||
factory.InitGlyphs(false);
|
factory.InitGlyphs(false);
|
||||||
|
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "Picking " << sPlayerbotAIConfig->premadeSpecName[cls][specNo];
|
out << "Picking " << sPlayerbotAIConfig.premadeSpecName[cls][specNo];
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
|
|||||||
// std::vector<TalentPath*> ChangeTalentsAction::getPremadePaths(std::string const findName)
|
// std::vector<TalentPath*> ChangeTalentsAction::getPremadePaths(std::string const findName)
|
||||||
// {
|
// {
|
||||||
// std::vector<TalentPath*> ret;
|
// std::vector<TalentPath*> ret;
|
||||||
// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath)
|
// // for (auto& path : sPlayerbotAIConfig.classSpecs[bot->getClass()].talentPath)
|
||||||
// // {
|
// // {
|
||||||
// // if (findName.empty() || path.name.find(findName) != std::string::npos)
|
// // if (findName.empty() || path.name.find(findName) != std::string::npos)
|
||||||
// // {
|
// // {
|
||||||
@@ -191,7 +191,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
|
|||||||
// {
|
// {
|
||||||
// std::vector<TalentPath*> ret;
|
// std::vector<TalentPath*> ret;
|
||||||
|
|
||||||
// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath)
|
// // for (auto& path : sPlayerbotAIConfig.classSpecs[bot->getClass()].talentPath)
|
||||||
// // {
|
// // {
|
||||||
// // TalentSpec newSpec = *GetBestPremadeSpec(path.id);
|
// // TalentSpec newSpec = *GetBestPremadeSpec(path.id);
|
||||||
// // newSpec.CropTalents(bot->GetLevel());
|
// // newSpec.CropTalents(bot->GetLevel());
|
||||||
@@ -206,7 +206,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
|
|||||||
|
|
||||||
// TalentPath* ChangeTalentsAction::getPremadePath(uint32 id)
|
// TalentPath* ChangeTalentsAction::getPremadePath(uint32 id)
|
||||||
// {
|
// {
|
||||||
// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath)
|
// // for (auto& path : sPlayerbotAIConfig.classSpecs[bot->getClass()].talentPath)
|
||||||
// // {
|
// // {
|
||||||
// // if (id == path.id)
|
// // if (id == path.id)
|
||||||
// // {
|
// // {
|
||||||
@@ -214,7 +214,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
|
|||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
|
|
||||||
// // return &sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath[0];
|
// // return &sPlayerbotAIConfig.classSpecs[bot->getClass()].talentPath[0];
|
||||||
// return nullptr;
|
// return nullptr;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -270,9 +270,9 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
|
|||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// uint32 specNo = sRandomPlayerbotMgr->GetValue(bot->GetGUID().GetCounter(), "specNo");
|
// uint32 specNo = sRandomPlayerbotMgr.GetValue(bot->GetGUID().GetCounter(), "specNo");
|
||||||
// uint32 specId = specNo - 1;
|
// uint32 specId = specNo - 1;
|
||||||
// std::string specLink = sRandomPlayerbotMgr->GetData(bot->GetGUID().GetCounter(), "specLink");
|
// std::string specLink = sRandomPlayerbotMgr.GetData(bot->GetGUID().GetCounter(), "specLink");
|
||||||
|
|
||||||
// //Continue the current spec
|
// //Continue the current spec
|
||||||
// if (specNo > 0)
|
// if (specNo > 0)
|
||||||
@@ -319,15 +319,15 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
|
|||||||
// specId = -1;
|
// specId = -1;
|
||||||
// // specLink = "";
|
// // specLink = "";
|
||||||
// }
|
// }
|
||||||
// else if (paths.size() > 1 && false/*!sPlayerbotAIConfig->autoPickTalents*/ &&
|
// else if (paths.size() > 1 && false/*!sPlayerbotAIConfig.autoPickTalents*/ &&
|
||||||
// !sRandomPlayerbotMgr->IsRandomBot(bot))
|
// !sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
// {
|
// {
|
||||||
// *out << "Found multiple specs: ";
|
// *out << "Found multiple specs: ";
|
||||||
// listPremadePaths(paths, out);
|
// listPremadePaths(paths, out);
|
||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
// {
|
// {
|
||||||
// specId = PickPremadePath(paths, sRandomPlayerbotMgr->IsRandomBot(bot))->id;
|
// specId = PickPremadePath(paths, sRandomPlayerbotMgr.IsRandomBot(bot))->id;
|
||||||
// TalentSpec newSpec = *GetBestPremadeSpec(specId);
|
// TalentSpec newSpec = *GetBestPremadeSpec(specId);
|
||||||
// specLink = newSpec.GetTalentLink();
|
// specLink = newSpec.GetTalentLink();
|
||||||
// newSpec.CropTalents(bot->GetLevel());
|
// newSpec.CropTalents(bot->GetLevel());
|
||||||
@@ -341,12 +341,12 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", specId + 1);
|
// sRandomPlayerbotMgr.SetValue(bot->GetGUID().GetCounter(), "specNo", specId + 1);
|
||||||
|
|
||||||
// if (!specLink.empty() && specId == -1)
|
// if (!specLink.empty() && specId == -1)
|
||||||
// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 1, specLink);
|
// sRandomPlayerbotMgr.SetValue(bot->GetGUID().GetCounter(), "specLink", 1, specLink);
|
||||||
// else
|
// else
|
||||||
// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 0);
|
// sRandomPlayerbotMgr.SetValue(bot->GetGUID().GetCounter(), "specLink", 0);
|
||||||
|
|
||||||
// return (specNo == 0) ? false : true;
|
// return (specNo == 0) ? false : true;
|
||||||
// }
|
// }
|
||||||
@@ -364,7 +364,7 @@ std::string ChangeTalentsAction::SpecApply(std::string param)
|
|||||||
// if (path->talentSpec.size())
|
// if (path->talentSpec.size())
|
||||||
// return &path->talentSpec.back();
|
// return &path->talentSpec.back();
|
||||||
|
|
||||||
// // return &sPlayerbotAIConfig->classSpecs[bot->getClassMask()].baseSpec;
|
// // return &sPlayerbotAIConfig.classSpecs[bot->getClassMask()].baseSpec;
|
||||||
// return nullptr;
|
// return nullptr;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ bool AutoSetTalentsAction::Execute(Event event)
|
|||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
|
|
||||||
if (!sPlayerbotAIConfig->autoPickTalents || !sRandomPlayerbotMgr->IsRandomBot(bot))
|
if (!sPlayerbotAIConfig.autoPickTalents || !sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (bot->GetFreeTalentPoints() <= 0)
|
if (bot->GetFreeTalentPoints() <= 0)
|
||||||
@@ -96,7 +96,7 @@ bool FollowChatShortcutAction::Execute(Event event)
|
|||||||
|
|
||||||
/* Default mechanics takes care of this now.
|
/* Default mechanics takes care of this now.
|
||||||
if (bot->GetMapId() != master->GetMapId() || (master && bot->GetDistance(master) >
|
if (bot->GetMapId() != master->GetMapId() || (master && bot->GetDistance(master) >
|
||||||
sPlayerbotAIConfig->sightDistance))
|
sPlayerbotAIConfig.sightDistance))
|
||||||
{
|
{
|
||||||
if (bot->isDead())
|
if (bot->isDead())
|
||||||
{
|
{
|
||||||
@@ -161,7 +161,7 @@ bool FleeChatShortcutAction::Execute(Event event)
|
|||||||
ResetReturnPosition();
|
ResetReturnPosition();
|
||||||
ResetStayPosition();
|
ResetStayPosition();
|
||||||
|
|
||||||
if (bot->GetMapId() != master->GetMapId() || bot->GetDistance(master) > sPlayerbotAIConfig->sightDistance)
|
if (bot->GetMapId() != master->GetMapId() || bot->GetDistance(master) > sPlayerbotAIConfig.sightDistance)
|
||||||
{
|
{
|
||||||
botAI->TellError("I will not flee with you - too far away");
|
botAI->TellError("I will not flee with you - too far away");
|
||||||
return true;
|
return true;
|
||||||
@@ -241,20 +241,6 @@ bool MaxDpsChatShortcutAction::Execute(Event event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NaxxChatShortcutAction::Execute(Event event)
|
|
||||||
{
|
|
||||||
Player* master = GetMaster();
|
|
||||||
if (!master)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
botAI->Reset();
|
|
||||||
botAI->ChangeStrategy("+naxx", BOT_STATE_NON_COMBAT);
|
|
||||||
botAI->ChangeStrategy("+naxx", BOT_STATE_COMBAT);
|
|
||||||
botAI->TellMasterNoFacing("Add Naxx Strategies!");
|
|
||||||
// bot->Say("Add Naxx Strategies!", LANG_UNIVERSAL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BwlChatShortcutAction::Execute(Event event)
|
bool BwlChatShortcutAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
Player* master = GetMaster();
|
Player* master = GetMaster();
|
||||||
@@ -85,13 +85,6 @@ public:
|
|||||||
bool Execute(Event event) override;
|
bool Execute(Event event) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NaxxChatShortcutAction : public Action
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NaxxChatShortcutAction(PlayerbotAI* ai) : Action(ai, "naxx chat shortcut") {}
|
|
||||||
virtual bool Execute(Event event);
|
|
||||||
};
|
|
||||||
|
|
||||||
class BwlChatShortcutAction : public Action
|
class BwlChatShortcutAction : public Action
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -86,7 +86,7 @@ void CheatAction::ListCheats()
|
|||||||
for (int i = 0; i < log2((uint32)BotCheatMask::maxMask); i++)
|
for (int i = 0; i < log2((uint32)BotCheatMask::maxMask); i++)
|
||||||
{
|
{
|
||||||
BotCheatMask cheatMask = BotCheatMask(1 << i);
|
BotCheatMask cheatMask = BotCheatMask(1 << i);
|
||||||
if ((uint32)cheatMask & (uint32)sPlayerbotAIConfig->botCheatMask)
|
if ((uint32)cheatMask & (uint32)sPlayerbotAIConfig.botCheatMask)
|
||||||
out << "[conf:" << GetCheatName(BotCheatMask(cheatMask)) << "]";
|
out << "[conf:" << GetCheatName(BotCheatMask(cheatMask)) << "]";
|
||||||
else if (botAI->HasCheat(cheatMask))
|
else if (botAI->HasCheat(cheatMask))
|
||||||
out << "[" << GetCheatName(BotCheatMask(cheatMask)) << "]";
|
out << "[" << GetCheatName(BotCheatMask(cheatMask)) << "]";
|
||||||
@@ -28,7 +28,7 @@ bool CheckMailAction::Execute(Event event)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint32 account = owner->GetSession()->GetAccountId();
|
uint32 account = owner->GetSession()->GetAccountId();
|
||||||
if (sPlayerbotAIConfig->IsInRandomAccountList(account))
|
if (sPlayerbotAIConfig.IsInRandomAccountList(account))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ProcessMail(mail, owner, trans);
|
ProcessMail(mail, owner, trans);
|
||||||
@@ -80,7 +80,7 @@ void CheckMailAction::ProcessMail(Mail* mail, Player* owner, CharacterDatabaseTr
|
|||||||
if (!item)
|
if (!item)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!sGuildTaskMgr->CheckItemTask(i->item_template, item->GetCount(), owner, bot, true))
|
if (!GuildTaskMgr::instance().CheckItemTask(i->item_template, item->GetCount(), owner, bot, true))
|
||||||
{
|
{
|
||||||
std::ostringstream body;
|
std::ostringstream body;
|
||||||
body << "Hello, " << owner->GetName() << ",\n";
|
body << "Hello, " << owner->GetName() << ",\n";
|
||||||
@@ -89,7 +89,7 @@ bool CheckMountStateAction::isUseful()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Not useful when level lower than minimum required
|
// Not useful when level lower than minimum required
|
||||||
if (bot->GetLevel() < sPlayerbotAIConfig->useGroundMountAtMinLevel)
|
if (bot->GetLevel() < sPlayerbotAIConfig.useGroundMountAtMinLevel)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Allow mounting while transformed only if the form allows it
|
// Allow mounting while transformed only if the form allows it
|
||||||
@@ -402,7 +402,7 @@ float CheckMountStateAction::CalculateDismountDistance() const
|
|||||||
// Warrior bots should dismount far enough to charge (because it's important for generating some initial rage),
|
// Warrior bots should dismount far enough to charge (because it's important for generating some initial rage),
|
||||||
// a real player would be riding toward enemy mashing the charge key but the bots won't cast charge while mounted.
|
// a real player would be riding toward enemy mashing the charge key but the bots won't cast charge while mounted.
|
||||||
bool isMelee = PlayerbotAI::IsMelee(bot);
|
bool isMelee = PlayerbotAI::IsMelee(bot);
|
||||||
float dismountDistance = isMelee ? sPlayerbotAIConfig->meleeDistance + 2.0f : sPlayerbotAIConfig->spellDistance + 2.0f;
|
float dismountDistance = isMelee ? sPlayerbotAIConfig.meleeDistance + 2.0f : sPlayerbotAIConfig.spellDistance + 2.0f;
|
||||||
return bot->getClass() == CLASS_WARRIOR ? std::max(18.0f, dismountDistance) : dismountDistance;
|
return bot->getClass() == CLASS_WARRIOR ? std::max(18.0f, dismountDistance) : dismountDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,7 +413,7 @@ float CheckMountStateAction::CalculateMountDistance() const
|
|||||||
// seconds:
|
// seconds:
|
||||||
// 21 / 7 = 21 / 14 + 1.5 = 3 (7 = dismounted speed 14 = epic-mount speed 1.5 = mount-spell cast time)
|
// 21 / 7 = 21 / 14 + 1.5 = 3 (7 = dismounted speed 14 = epic-mount speed 1.5 = mount-spell cast time)
|
||||||
bool isMelee = PlayerbotAI::IsMelee(bot);
|
bool isMelee = PlayerbotAI::IsMelee(bot);
|
||||||
float baseDistance = isMelee ? sPlayerbotAIConfig->meleeDistance + 10.0f : sPlayerbotAIConfig->spellDistance + 10.0f;
|
float baseDistance = isMelee ? sPlayerbotAIConfig.meleeDistance + 10.0f : sPlayerbotAIConfig.spellDistance + 10.0f;
|
||||||
return std::max(21.0f, baseDistance);
|
return std::max(21.0f, baseDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ int32 CheckMountStateAction::CalculateMasterMountSpeed(Player* master, const Mou
|
|||||||
int32 ridingSkill = bot->GetPureSkillValue(SKILL_RIDING);
|
int32 ridingSkill = bot->GetPureSkillValue(SKILL_RIDING);
|
||||||
int32 botLevel = bot->GetLevel();
|
int32 botLevel = bot->GetLevel();
|
||||||
|
|
||||||
if (ridingSkill <= 75 && botLevel < static_cast<int32>(sPlayerbotAIConfig->useFastGroundMountAtMinLevel))
|
if (ridingSkill <= 75 && botLevel < static_cast<int32>(sPlayerbotAIConfig.useFastGroundMountAtMinLevel))
|
||||||
return 59;
|
return 59;
|
||||||
|
|
||||||
// If there is a master and bot not in BG, use master's aura effects.
|
// If there is a master and bot not in BG, use master's aura effects.
|
||||||
@@ -20,7 +20,7 @@ bool CheckValuesAction::Execute(Event event)
|
|||||||
|
|
||||||
if (botAI->HasStrategy("map", BOT_STATE_NON_COMBAT) || botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT))
|
if (botAI->HasStrategy("map", BOT_STATE_NON_COMBAT) || botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT))
|
||||||
{
|
{
|
||||||
sTravelNodeMap->manageNodes(bot, botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT));
|
TravelNodeMap::instance().manageNodes(bot, botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT));
|
||||||
}
|
}
|
||||||
|
|
||||||
GuidVector possible_targets = *context->GetValue<GuidVector>("possible targets");
|
GuidVector possible_targets = *context->GetValue<GuidVector>("possible targets");
|
||||||
@@ -78,20 +78,17 @@ float ChooseRpgTargetAction::getMaxRelevance(GuidPosition guidP)
|
|||||||
if (!trigger->IsActive())
|
if (!trigger->IsActive())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
NextAction** nextActions = triggerNode->getHandlers();
|
std::vector<NextAction> nextActions = triggerNode->getHandlers();
|
||||||
|
|
||||||
bool isRpg = false;
|
bool isRpg = false;
|
||||||
|
|
||||||
for (int32 i = 0; i < NextAction::size(nextActions); i++)
|
for (NextAction nextAction : nextActions)
|
||||||
{
|
{
|
||||||
NextAction* nextAction = nextActions[i];
|
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction.getName());
|
||||||
|
|
||||||
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction->getName());
|
|
||||||
|
|
||||||
if (dynamic_cast<RpgEnabled*>(action))
|
if (dynamic_cast<RpgEnabled*>(action))
|
||||||
isRpg = true;
|
isRpg = true;
|
||||||
}
|
}
|
||||||
NextAction::destroy(nextActions);
|
|
||||||
|
|
||||||
if (isRpg)
|
if (isRpg)
|
||||||
{
|
{
|
||||||
@@ -251,7 +248,7 @@ bool ChooseRpgTargetAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::mt19937 gen(time(0));
|
std::mt19937 gen(time(0));
|
||||||
sTravelMgr->weighted_shuffle(guidps.begin(), guidps.end(), relevances.begin(), relevances.end(), gen);
|
TravelMgr::instance().weighted_shuffle(guidps.begin(), guidps.end(), relevances.begin(), relevances.end(), gen);
|
||||||
|
|
||||||
GuidPosition guidP(guidps.front());
|
GuidPosition guidP(guidps.front());
|
||||||
if (!guidP)
|
if (!guidP)
|
||||||
@@ -282,7 +279,7 @@ bool ChooseRpgTargetAction::isUseful()
|
|||||||
|
|
||||||
GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target");
|
GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target");
|
||||||
|
|
||||||
if (guidP && guidP.distance(bot) < sPlayerbotAIConfig->reactDistance * 2)
|
if (guidP && guidP.distance(bot) < sPlayerbotAIConfig.reactDistance * 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 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.
|
||||||
@@ -333,7 +330,7 @@ bool ChooseRpgTargetAction::isFollowValid(Player* bot, WorldPosition pos)
|
|||||||
if (!botAI->HasStrategy("follow", BOT_STATE_NON_COMBAT))
|
if (!botAI->HasStrategy("follow", BOT_STATE_NON_COMBAT))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (bot->GetDistance(groupLeader) > sPlayerbotAIConfig->rpgDistance * 2)
|
if (bot->GetDistance(groupLeader) > sPlayerbotAIConfig.rpgDistance * 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Formation* formation = AI_VALUE(Formation*, "formation");
|
Formation* formation = AI_VALUE(Formation*, "formation");
|
||||||
@@ -343,7 +340,7 @@ bool ChooseRpgTargetAction::isFollowValid(Player* bot, WorldPosition pos)
|
|||||||
{
|
{
|
||||||
Player* player = groupLeader;
|
Player* player = groupLeader;
|
||||||
if (groupLeader && !groupLeader->isMoving() ||
|
if (groupLeader && !groupLeader->isMoving() ||
|
||||||
PAI_VALUE(WorldPosition, "last long move").distance(pos) < sPlayerbotAIConfig->reactDistance)
|
PAI_VALUE(WorldPosition, "last long move").distance(pos) < sPlayerbotAIConfig.reactDistance)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "LootObjectStack.h"
|
#include "LootObjectStack.h"
|
||||||
#include "NewRpgStrategy.h"
|
#include "NewRpgStrategy.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
#include "RtiTargetValue.h"
|
||||||
#include "PossibleRpgTargetsValue.h"
|
#include "PossibleRpgTargetsValue.h"
|
||||||
#include "PvpTriggers.h"
|
#include "PvpTriggers.h"
|
||||||
#include "ServerFacade.h"
|
#include "ServerFacade.h"
|
||||||
@@ -19,13 +20,13 @@ bool AttackEnemyPlayerAction::isUseful()
|
|||||||
if (PlayerHasFlag::IsCapturingFlag(bot))
|
if (PlayerHasFlag::IsCapturingFlag(bot))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return !sPlayerbotAIConfig->IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId());
|
return !sPlayerbotAIConfig.IsPvpProhibited(bot->GetZoneId(), bot->GetAreaId());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AttackEnemyFlagCarrierAction::isUseful()
|
bool AttackEnemyFlagCarrierAction::isUseful()
|
||||||
{
|
{
|
||||||
Unit* target = context->GetValue<Unit*>("enemy flag carrier")->Get();
|
Unit* target = context->GetValue<Unit*>("enemy flag carrier")->Get();
|
||||||
return target && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, target), 100.0f) &&
|
return target && ServerFacade::instance().IsDistanceLessOrEqualThan(ServerFacade::instance().GetDistance2d(bot, target), 100.0f) &&
|
||||||
PlayerHasFlag::IsCapturingFlag(bot);
|
PlayerHasFlag::IsCapturingFlag(bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,9 +88,7 @@ bool DropTargetAction::Execute(Event event)
|
|||||||
{
|
{
|
||||||
Spell const* spell = bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL); // Get the current spell being cast by the bot
|
Spell const* spell = bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL); // Get the current spell being cast by the bot
|
||||||
if (spell && spell->m_spellInfo->Id == 75) //Check spell is not nullptr before accessing m_spellInfo
|
if (spell && spell->m_spellInfo->Id == 75) //Check spell is not nullptr before accessing m_spellInfo
|
||||||
{
|
|
||||||
bot->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); // Interrupt Auto Shot
|
bot->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); // Interrupt Auto Shot
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bot->AttackStop();
|
bot->AttackStop();
|
||||||
|
|
||||||
@@ -142,6 +141,23 @@ bool AttackRtiTargetAction::Execute(Event event)
|
|||||||
{
|
{
|
||||||
Unit* rtiTarget = AI_VALUE(Unit*, "rti target");
|
Unit* rtiTarget = AI_VALUE(Unit*, "rti target");
|
||||||
|
|
||||||
|
// Fallback: if the "rti target" value did not resolve a valid unit yet,
|
||||||
|
// try to resolve the raid icon directly from the group.
|
||||||
|
if (!rtiTarget)
|
||||||
|
{
|
||||||
|
if (Group* group = bot->GetGroup())
|
||||||
|
{
|
||||||
|
std::string const rti = AI_VALUE(std::string, "rti");
|
||||||
|
int32 const index = RtiTargetValue::GetRtiIndex(rti);
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
ObjectGuid const guid = group->GetTargetIcon(index);
|
||||||
|
if (!guid.IsEmpty())
|
||||||
|
rtiTarget = botAI->GetUnit(guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rtiTarget && rtiTarget->IsInWorld() && rtiTarget->GetMapId() == bot->GetMapId())
|
if (rtiTarget && rtiTarget->IsInWorld() && rtiTarget->GetMapId() == bot->GetMapId())
|
||||||
{
|
{
|
||||||
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Set({rtiTarget->GetGUID()});
|
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Set({rtiTarget->GetGUID()});
|
||||||
@@ -153,9 +169,7 @@ bool AttackRtiTargetAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
botAI->TellError("I dont see my rti attack target");
|
botAI->TellError("I dont see my rti attack target");
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -366,7 +366,7 @@ bool ChooseTravelTargetAction::getBestDestination(std::vector<TravelDestination*
|
|||||||
|
|
||||||
WorldPosition botLocation(bot);
|
WorldPosition botLocation(bot);
|
||||||
std::vector<WorldPosition*> availablePoints =
|
std::vector<WorldPosition*> availablePoints =
|
||||||
sTravelMgr->getNextPoint(&botLocation, *activePoints); // Pick a good point.
|
TravelMgr::instance().getNextPoint(&botLocation, *activePoints); // Pick a good point.
|
||||||
|
|
||||||
if (availablePoints.empty()) // No points available.
|
if (availablePoints.empty()) // No points available.
|
||||||
return false;
|
return false;
|
||||||
@@ -488,7 +488,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCom
|
|||||||
if (newQuests)
|
if (newQuests)
|
||||||
{
|
{
|
||||||
// Prefer new quests near the player at lower levels.
|
// Prefer new quests near the player at lower levels.
|
||||||
activeDestinations = sTravelMgr->getQuestTravelDestinations(bot, -1, true, false, 400 + bot->GetLevel() * 10);
|
activeDestinations = TravelMgr::instance().getQuestTravelDestinations(bot, -1, true, false, 400 + bot->GetLevel() * 10);
|
||||||
}
|
}
|
||||||
if (activeQuests || completedQuests)
|
if (activeQuests || completedQuests)
|
||||||
{
|
{
|
||||||
@@ -510,7 +510,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCom
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
//Find quest takers or objectives
|
//Find quest takers or objectives
|
||||||
std::vector<TravelDestination*> questDestinations = sTravelMgr->getQuestTravelDestinations(bot, questId, true, false, 0);
|
std::vector<TravelDestination*> questDestinations = TravelMgr::instance().getQuestTravelDestinations(bot, questId, true, false, 0);
|
||||||
|
|
||||||
if (onlyClassQuest && activeDestinations.size() && questDestinations.size()) //Only do class quests if we have any.
|
if (onlyClassQuest && activeDestinations.size() && questDestinations.size()) //Only do class quests if we have any.
|
||||||
{
|
{
|
||||||
@@ -525,7 +525,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newQuests && activeDestinations.empty())
|
if (newQuests && activeDestinations.empty())
|
||||||
activeDestinations = sTravelMgr->getQuestTravelDestinations(bot, -1, true, false); //If we really don't find any new quests look futher away.
|
activeDestinations = TravelMgr::instance().getQuestTravelDestinations(bot, -1, true, false); //If we really don't find any new quests look futher away.
|
||||||
|
|
||||||
if (botAI->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT))
|
if (botAI->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT))
|
||||||
botAI->TellMasterNoFacing(std::to_string(activeDestinations.size()) + " quest destinations found.");
|
botAI->TellMasterNoFacing(std::to_string(activeDestinations.size()) + " quest destinations found.");
|
||||||
@@ -547,7 +547,7 @@ bool ChooseTravelTargetAction::SetNewQuestTarget(TravelTarget* target)
|
|||||||
|
|
||||||
// Find quest givers.
|
// Find quest givers.
|
||||||
std::vector<TravelDestination*> TravelDestinations =
|
std::vector<TravelDestination*> TravelDestinations =
|
||||||
sTravelMgr->getQuestTravelDestinations(bot, -1, botAI->HasRealPlayerMaster());
|
TravelMgr::instance().getQuestTravelDestinations(bot, -1, botAI->HasRealPlayerMaster());
|
||||||
|
|
||||||
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
||||||
|
|
||||||
@@ -576,7 +576,7 @@ bool ChooseTravelTargetAction::SetRpgTarget(TravelTarget* target)
|
|||||||
|
|
||||||
// Find rpg npcs
|
// Find rpg npcs
|
||||||
std::vector<TravelDestination*> TravelDestinations =
|
std::vector<TravelDestination*> TravelDestinations =
|
||||||
sTravelMgr->getRpgTravelDestinations(bot, botAI->HasRealPlayerMaster());
|
TravelMgr::instance().getRpgTravelDestinations(bot, botAI->HasRealPlayerMaster());
|
||||||
|
|
||||||
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
||||||
|
|
||||||
@@ -605,7 +605,7 @@ bool ChooseTravelTargetAction::SetGrindTarget(TravelTarget* target)
|
|||||||
|
|
||||||
// Find grind mobs.
|
// Find grind mobs.
|
||||||
std::vector<TravelDestination*> TravelDestinations =
|
std::vector<TravelDestination*> TravelDestinations =
|
||||||
sTravelMgr->getGrindTravelDestinations(bot, botAI->HasRealPlayerMaster());
|
TravelMgr::instance().getGrindTravelDestinations(bot, botAI->HasRealPlayerMaster());
|
||||||
|
|
||||||
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
||||||
|
|
||||||
@@ -634,7 +634,7 @@ bool ChooseTravelTargetAction::SetBossTarget(TravelTarget* target)
|
|||||||
|
|
||||||
// Find boss mobs.
|
// Find boss mobs.
|
||||||
std::vector<TravelDestination*> TravelDestinations =
|
std::vector<TravelDestination*> TravelDestinations =
|
||||||
sTravelMgr->getBossTravelDestinations(bot, botAI->HasRealPlayerMaster());
|
TravelMgr::instance().getBossTravelDestinations(bot, botAI->HasRealPlayerMaster());
|
||||||
|
|
||||||
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
||||||
|
|
||||||
@@ -662,7 +662,7 @@ bool ChooseTravelTargetAction::SetExploreTarget(TravelTarget* target)
|
|||||||
WorldPosition botLocation(bot);
|
WorldPosition botLocation(bot);
|
||||||
|
|
||||||
// Find quest givers.
|
// Find quest givers.
|
||||||
std::vector<TravelDestination*> TravelDestinations = sTravelMgr->getExploreTravelDestinations(bot, true, true);
|
std::vector<TravelDestination*> TravelDestinations = TravelMgr::instance().getExploreTravelDestinations(bot, true, true);
|
||||||
|
|
||||||
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
activeDestinations.insert(activeDestinations.end(), TravelDestinations.begin(), TravelDestinations.end());
|
||||||
/*
|
/*
|
||||||
@@ -681,7 +681,7 @@ bool ChooseTravelTargetAction::SetExploreTarget(TravelTarget* target)
|
|||||||
|
|
||||||
if (activePoints.empty())
|
if (activePoints.empty())
|
||||||
{
|
{
|
||||||
TravelDestinations = sTravelMgr->getExploreTravelDestinations(bot, botAI->HasRealPlayerMaster());
|
TravelDestinations = TravelMgr::instance().getExploreTravelDestinations(bot, botAI->HasRealPlayerMaster());
|
||||||
|
|
||||||
for (auto& activeTarget : activeDestinations)
|
for (auto& activeTarget : activeDestinations)
|
||||||
{
|
{
|
||||||
@@ -710,7 +710,7 @@ bool ChooseTravelTargetAction::SetNpcFlagTarget(TravelTarget* target, std::vecto
|
|||||||
|
|
||||||
std::vector<TravelDestination*> dests;
|
std::vector<TravelDestination*> dests;
|
||||||
|
|
||||||
for (auto& d : sTravelMgr->getRpgTravelDestinations(bot, true, true))
|
for (auto& d : TravelMgr::instance().getRpgTravelDestinations(bot, true, true))
|
||||||
{
|
{
|
||||||
if (!d->getEntry())
|
if (!d->getEntry())
|
||||||
continue;
|
continue;
|
||||||
@@ -813,7 +813,7 @@ std::vector<TravelDestination*> TravelMgr::getBossTravelDestinations(Player* bot
|
|||||||
|
|
||||||
bool ChooseTravelTargetAction::SetNullTarget(TravelTarget* target)
|
bool ChooseTravelTargetAction::SetNullTarget(TravelTarget* target)
|
||||||
{
|
{
|
||||||
target->setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition, true);
|
target->setTarget(TravelMgr::instance().nullTravelDestination, TravelMgr::instance().nullWorldPosition, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -832,7 +832,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s
|
|||||||
//Quests
|
//Quests
|
||||||
if (quests)
|
if (quests)
|
||||||
{
|
{
|
||||||
for (auto& d : sTravelMgr->getQuestTravelDestinations(bot, 0, true, true))
|
for (auto& d : TravelMgr::instance().getQuestTravelDestinations(bot, 0, true, true))
|
||||||
{
|
{
|
||||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||||
dests.push_back(d);
|
dests.push_back(d);
|
||||||
@@ -842,7 +842,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s
|
|||||||
//Zones
|
//Zones
|
||||||
if (zones)
|
if (zones)
|
||||||
{
|
{
|
||||||
for (auto& d : sTravelMgr->getExploreTravelDestinations(bot, true, true))
|
for (auto& d : TravelMgr::instance().getExploreTravelDestinations(bot, true, true))
|
||||||
{
|
{
|
||||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||||
dests.push_back(d);
|
dests.push_back(d);
|
||||||
@@ -852,7 +852,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s
|
|||||||
//Npcs
|
//Npcs
|
||||||
if (npcs)
|
if (npcs)
|
||||||
{
|
{
|
||||||
for (auto& d : sTravelMgr->getRpgTravelDestinations(bot, true, true))
|
for (auto& d : TravelMgr::instance().getRpgTravelDestinations(bot, true, true))
|
||||||
{
|
{
|
||||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||||
dests.push_back(d);
|
dests.push_back(d);
|
||||||
@@ -862,7 +862,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s
|
|||||||
//Mobs
|
//Mobs
|
||||||
if (mobs)
|
if (mobs)
|
||||||
{
|
{
|
||||||
for (auto& d : sTravelMgr->getGrindTravelDestinations(bot, true, true, 5000.0f))
|
for (auto& d : TravelMgr::instance().getGrindTravelDestinations(bot, true, true, 5000.0f))
|
||||||
{
|
{
|
||||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||||
dests.push_back(d);
|
dests.push_back(d);
|
||||||
@@ -872,7 +872,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s
|
|||||||
//Bosses
|
//Bosses
|
||||||
if (bosses)
|
if (bosses)
|
||||||
{
|
{
|
||||||
for (auto& d : sTravelMgr->getBossTravelDestinations(bot, true, true))
|
for (auto& d : TravelMgr::instance().getBossTravelDestinations(bot, true, true))
|
||||||
{
|
{
|
||||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||||
dests.push_back(d);
|
dests.push_back(d);
|
||||||
@@ -25,7 +25,7 @@ bool SwitchToMeleeAction::isUseful()
|
|||||||
return botAI->HasStrategy("ranged", BOT_STATE_COMBAT) &&
|
return botAI->HasStrategy("ranged", BOT_STATE_COMBAT) &&
|
||||||
((bot->IsInCombat() && target &&
|
((bot->IsInCombat() && target &&
|
||||||
(target->GetVictim() == bot && (!bot->GetGroup() || lastFlee) &&
|
(target->GetVictim() == bot && (!bot->GetGroup() || lastFlee) &&
|
||||||
sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), 8.0f))) ||
|
ServerFacade::instance().IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), 8.0f))) ||
|
||||||
(!bot->IsInCombat()));
|
(!bot->IsInCombat()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ bool SwitchToRangedAction::isUseful()
|
|||||||
return botAI->HasStrategy("close", BOT_STATE_COMBAT) && hasAmmo &&
|
return botAI->HasStrategy("close", BOT_STATE_COMBAT) && hasAmmo &&
|
||||||
((bot->IsInCombat() && target &&
|
((bot->IsInCombat() && target &&
|
||||||
((target->GetVictim() != bot || target->GetTarget() != bot->GetGUID()) ||
|
((target->GetVictim() != bot || target->GetTarget() != bot->GetGUID()) ||
|
||||||
sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"), 8.0f))) ||
|
ServerFacade::instance().IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"), 8.0f))) ||
|
||||||
(!bot->IsInCombat()));
|
(!bot->IsInCombat()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ bool DebugAction::Execute(Event event)
|
|||||||
|
|
||||||
if (text == "scan")
|
if (text == "scan")
|
||||||
{
|
{
|
||||||
sPlayerbotAIConfig->openLog("scan.csv", "w");
|
sPlayerbotAIConfig.openLog("scan.csv", "w");
|
||||||
|
|
||||||
uint32 i = 0;
|
uint32 i = 0;
|
||||||
for (auto p : WorldPosition().getCreaturesNear())
|
for (auto p : WorldPosition().getCreaturesNear())
|
||||||
@@ -36,15 +36,15 @@ bool DebugAction::Execute(Event event)
|
|||||||
|
|
||||||
pos.printWKT(out);
|
pos.printWKT(out);
|
||||||
|
|
||||||
sPlayerbotAIConfig->log("scan.csv", out.str().c_str());
|
sPlayerbotAIConfig.log("scan.csv", out.str().c_str());
|
||||||
|
|
||||||
if (zoneId == 0 && areaId == 0)
|
if (zoneId == 0 && areaId == 0)
|
||||||
{
|
{
|
||||||
sPlayerbotAIConfig->log("x", out.str().c_str());
|
sPlayerbotAIConfig.log("x", out.str().c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sPlayerbotAIConfig->log("y", out.str().c_str());
|
sPlayerbotAIConfig.log("y", out.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
i = zoneId;
|
i = zoneId;
|
||||||
@@ -53,8 +53,8 @@ bool DebugAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
else if (text.find("printmap") != std::string::npos)
|
else if (text.find("printmap") != std::string::npos)
|
||||||
{
|
{
|
||||||
sTravelNodeMap->printMap();
|
TravelNodeMap::instance().printMap();
|
||||||
sTravelNodeMap->printNodeStore();
|
TravelNodeMap::instance().printNodeStore();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (text.find("travel ") != std::string::npos)
|
else if (text.find("travel ") != std::string::npos)
|
||||||
@@ -72,7 +72,7 @@ bool DebugAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::vector<WorldPosition> beginPath, endPath;
|
std::vector<WorldPosition> beginPath, endPath;
|
||||||
TravelNodeRoute route = sTravelNodeMap->getRoute(botPos, *points.front(), beginPath, bot);
|
TravelNodeRoute route = TravelNodeMap::instance().getRoute(botPos, *points.front(), beginPath, bot);
|
||||||
|
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "Traveling to " << dest->getTitle() << ": ";
|
out << "Traveling to " << dest->getTitle() << ": ";
|
||||||
@@ -108,7 +108,7 @@ bool DebugAction::Execute(Event event)
|
|||||||
|
|
||||||
out << quest->GetTitle() << ": ";
|
out << quest->GetTitle() << ": ";
|
||||||
|
|
||||||
QuestContainer* cont = sTravelMgr->quests[questId];
|
QuestContainer* cont = TravelMgr::instance().quests[questId];
|
||||||
|
|
||||||
for (auto g : cont->questGivers)
|
for (auto g : cont->questGivers)
|
||||||
{
|
{
|
||||||
@@ -135,11 +135,11 @@ bool DebugAction::Execute(Event event)
|
|||||||
else if (text.find("quest") != std::string::npos)
|
else if (text.find("quest") != std::string::npos)
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << sTravelMgr->quests.size() << " quests ";
|
out << TravelMgr::instance().quests.size() << " quests ";
|
||||||
|
|
||||||
uint32 noT = 0, noG = 0, noO = 0;
|
uint32 noT = 0, noG = 0, noO = 0;
|
||||||
|
|
||||||
for (auto q : sTravelMgr->quests)
|
for (auto q : TravelMgr::instance().quests)
|
||||||
{
|
{
|
||||||
if (q.second->questGivers.empty())
|
if (q.second->questGivers.empty())
|
||||||
noG++;
|
noG++;
|
||||||
@@ -164,7 +164,7 @@ bool DebugAction::Execute(Event event)
|
|||||||
|
|
||||||
// uint32 noT = 0, noG = 0, noO = 0; //not used, line marked for removal.
|
// uint32 noT = 0, noG = 0, noO = 0; //not used, line marked for removal.
|
||||||
|
|
||||||
for (auto q : sTravelMgr->quests)
|
for (auto q : TravelMgr::instance().quests)
|
||||||
{
|
{
|
||||||
Quest const* quest = sObjectMgr->GetQuestTemplate(q.first);
|
Quest const* quest = sObjectMgr->GetQuestTemplate(q.first);
|
||||||
|
|
||||||
@@ -194,16 +194,16 @@ bool DebugAction::Execute(Event event)
|
|||||||
|
|
||||||
std::string const name = "USER:" + text.substr(9);
|
std::string const name = "USER:" + text.substr(9);
|
||||||
|
|
||||||
/* TravelNode* startNode = */ sTravelNodeMap->addNode(pos, name, false, false); // startNode not used, but addNode as side effect, fragment marked for removal.
|
/* TravelNode* startNode = */ TravelNodeMap::instance().addNode(pos, name, false, false); // startNode not used, but addNode as side effect, fragment marked for removal.
|
||||||
|
|
||||||
for (auto& endNode : sTravelNodeMap->getNodes(pos, 2000))
|
for (auto& endNode : TravelNodeMap::instance().getNodes(pos, 2000))
|
||||||
{
|
{
|
||||||
endNode->setLinked(false);
|
endNode->setLinked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
botAI->TellMasterNoFacing("Node " + name + " created.");
|
botAI->TellMasterNoFacing("Node " + name + " created.");
|
||||||
|
|
||||||
sTravelNodeMap->setHasToGen();
|
TravelNodeMap::instance().setHasToGen();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ bool DebugAction::Execute(Event event)
|
|||||||
{
|
{
|
||||||
WorldPosition pos(bot);
|
WorldPosition pos(bot);
|
||||||
|
|
||||||
TravelNode* startNode = sTravelNodeMap->getNode(pos, nullptr, 50);
|
TravelNode* startNode = TravelNodeMap::instance().getNode(pos, nullptr, 50);
|
||||||
|
|
||||||
if (!startNode)
|
if (!startNode)
|
||||||
return false;
|
return false;
|
||||||
@@ -221,24 +221,24 @@ bool DebugAction::Execute(Event event)
|
|||||||
botAI->TellMasterNoFacing("Node can not be removed.");
|
botAI->TellMasterNoFacing("Node can not be removed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
sTravelNodeMap->m_nMapMtx.lock();
|
TravelNodeMap::instance().m_nMapMtx.lock();
|
||||||
sTravelNodeMap->removeNode(startNode);
|
TravelNodeMap::instance().removeNode(startNode);
|
||||||
botAI->TellMasterNoFacing("Node removed.");
|
botAI->TellMasterNoFacing("Node removed.");
|
||||||
sTravelNodeMap->m_nMapMtx.unlock();
|
TravelNodeMap::instance().m_nMapMtx.unlock();
|
||||||
|
|
||||||
sTravelNodeMap->setHasToGen();
|
TravelNodeMap::instance().setHasToGen();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (text.find("reset node") != std::string::npos)
|
else if (text.find("reset node") != std::string::npos)
|
||||||
{
|
{
|
||||||
for (auto& node : sTravelNodeMap->getNodes())
|
for (auto& node : TravelNodeMap::instance().getNodes())
|
||||||
node->setLinked(false);
|
node->setLinked(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (text.find("reset path") != std::string::npos)
|
else if (text.find("reset path") != std::string::npos)
|
||||||
{
|
{
|
||||||
for (auto& node : sTravelNodeMap->getNodes())
|
for (auto& node : TravelNodeMap::instance().getNodes())
|
||||||
for (auto& path : *node->getLinks())
|
for (auto& path : *node->getLinks())
|
||||||
node->removeLinkTo(path.first, true);
|
node->removeLinkTo(path.first, true);
|
||||||
return true;
|
return true;
|
||||||
@@ -246,23 +246,23 @@ bool DebugAction::Execute(Event event)
|
|||||||
else if (text.find("gen node") != std::string::npos)
|
else if (text.find("gen node") != std::string::npos)
|
||||||
{
|
{
|
||||||
// Pathfinder
|
// Pathfinder
|
||||||
sTravelNodeMap->generateNodes();
|
TravelNodeMap::instance().generateNodes();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (text.find("gen path") != std::string::npos)
|
else if (text.find("gen path") != std::string::npos)
|
||||||
{
|
{
|
||||||
sTravelNodeMap->generatePaths();
|
TravelNodeMap::instance().generatePaths();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (text.find("crop path") != std::string::npos)
|
else if (text.find("crop path") != std::string::npos)
|
||||||
{
|
{
|
||||||
sTravelNodeMap->removeUselessPaths();
|
TravelNodeMap::instance().removeUselessPaths();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (text.find("save node") != std::string::npos)
|
else if (text.find("save node") != std::string::npos)
|
||||||
{
|
{
|
||||||
sTravelNodeMap->printNodeStore();
|
TravelNodeMap::instance().printNodeStore();
|
||||||
sTravelNodeMap->saveNodeStore();
|
TravelNodeMap::instance().saveNodeStore();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (text.find("load node") != std::string::npos)
|
else if (text.find("load node") != std::string::npos)
|
||||||
@@ -270,8 +270,8 @@ bool DebugAction::Execute(Event event)
|
|||||||
std::thread t(
|
std::thread t(
|
||||||
[]
|
[]
|
||||||
{
|
{
|
||||||
sTravelNodeMap->removeNodes();
|
TravelNodeMap::instance().removeNodes();
|
||||||
sTravelNodeMap->loadNodeStore();
|
TravelNodeMap::instance().loadNodeStore();
|
||||||
});
|
});
|
||||||
|
|
||||||
t.detach();
|
t.detach();
|
||||||
@@ -282,7 +282,7 @@ bool DebugAction::Execute(Event event)
|
|||||||
{
|
{
|
||||||
WorldPosition pos(bot);
|
WorldPosition pos(bot);
|
||||||
|
|
||||||
std::vector<TravelNode*> nodes = sTravelNodeMap->getNodes(pos, 500);
|
std::vector<TravelNode*> nodes = TravelNodeMap::instance().getNodes(pos, 500);
|
||||||
|
|
||||||
for (auto& node : nodes)
|
for (auto& node : nodes)
|
||||||
{
|
{
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
bool DelayAction::Execute(Event event)
|
bool DelayAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
uint32 delay = sPlayerbotAIConfig->passiveDelay + sPlayerbotAIConfig->globalCoolDown;
|
uint32 delay = sPlayerbotAIConfig.passiveDelay + sPlayerbotAIConfig.globalCoolDown;
|
||||||
|
|
||||||
botAI->SetNextCheckDelay(delay);
|
botAI->SetNextCheckDelay(delay);
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ bool CleanQuestLogAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sPlayerbotAIConfig->dropObsoleteQuests)
|
if (!sPlayerbotAIConfig.dropObsoleteQuests)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ void EmoteActionBase::InitEmotes()
|
|||||||
|
|
||||||
bool EmoteActionBase::Emote(Unit* target, uint32 type, bool textEmote)
|
bool EmoteActionBase::Emote(Unit* target, uint32 type, bool textEmote)
|
||||||
{
|
{
|
||||||
if (target && !bot->HasInArc(static_cast<float>(M_PI), target, sPlayerbotAIConfig->sightDistance))
|
if (target && !bot->HasInArc(static_cast<float>(M_PI), target, sPlayerbotAIConfig.sightDistance))
|
||||||
bot->SetFacingToObject(target);
|
bot->SetFacingToObject(target);
|
||||||
|
|
||||||
ObjectGuid oldSelection = bot->GetTarget();
|
ObjectGuid oldSelection = bot->GetTarget();
|
||||||
@@ -100,7 +100,7 @@ bool EmoteActionBase::Emote(Unit* target, uint32 type, bool textEmote)
|
|||||||
if (player)
|
if (player)
|
||||||
{
|
{
|
||||||
PlayerbotAI* playerBotAI = GET_PLAYERBOT_AI(player);
|
PlayerbotAI* playerBotAI = GET_PLAYERBOT_AI(player);
|
||||||
if (playerBotAI && !player->HasInArc(static_cast<float>(M_PI), bot, sPlayerbotAIConfig->sightDistance))
|
if (playerBotAI && !player->HasInArc(static_cast<float>(M_PI), bot, sPlayerbotAIConfig.sightDistance))
|
||||||
{
|
{
|
||||||
player->SetFacingToObject(bot);
|
player->SetFacingToObject(bot);
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ Unit* EmoteActionBase::GetTarget()
|
|||||||
for (GuidVector::iterator i = nfp.begin(); i != nfp.end(); ++i)
|
for (GuidVector::iterator i = nfp.begin(); i != nfp.end(); ++i)
|
||||||
{
|
{
|
||||||
Unit* unit = botAI->GetUnit(*i);
|
Unit* unit = botAI->GetUnit(*i);
|
||||||
if (unit && sServerFacade->GetDistance2d(bot, unit) < sPlayerbotAIConfig->tooCloseDistance)
|
if (unit && ServerFacade::instance().GetDistance2d(bot, unit) < sPlayerbotAIConfig.tooCloseDistance)
|
||||||
targets.push_back(unit);
|
targets.push_back(unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,8 +618,8 @@ bool EmoteActionBase::ReceiveEmote(Player* source, uint32 emote, bool verbal)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source && !bot->isMoving() && !bot->HasInArc(static_cast<float>(M_PI), source, sPlayerbotAIConfig->farDistance))
|
if (source && !bot->isMoving() && !bot->HasInArc(static_cast<float>(M_PI), source, sPlayerbotAIConfig.farDistance))
|
||||||
sServerFacade->SetFacingTo(bot, source);
|
ServerFacade::instance().SetFacingTo(bot, source);
|
||||||
|
|
||||||
if (verbal)
|
if (verbal)
|
||||||
{
|
{
|
||||||
@@ -689,7 +689,7 @@ bool EmoteAction::Execute(Event event)
|
|||||||
p >> emoteId >> source;
|
p >> emoteId >> source;
|
||||||
|
|
||||||
pSource = ObjectAccessor::FindPlayer(source);
|
pSource = ObjectAccessor::FindPlayer(source);
|
||||||
if (pSource && pSource != bot && sServerFacade->GetDistance2d(bot, pSource) < sPlayerbotAIConfig->farDistance &&
|
if (pSource && pSource != bot && ServerFacade::instance().GetDistance2d(bot, pSource) < sPlayerbotAIConfig.farDistance &&
|
||||||
emoteId != EMOTE_ONESHOT_NONE)
|
emoteId != EMOTE_ONESHOT_NONE)
|
||||||
{
|
{
|
||||||
if ((pSource->GetGUID() != bot->GetGUID()) &&
|
if ((pSource->GetGUID() != bot->GetGUID()) &&
|
||||||
@@ -737,7 +737,7 @@ bool EmoteAction::Execute(Event event)
|
|||||||
// time_t lastEmote = AI_VALUE2(time_t, "last emote", qualifier); //not used, line marked for removal.
|
// time_t lastEmote = AI_VALUE2(time_t, "last emote", qualifier); //not used, line marked for removal.
|
||||||
botAI->GetAiObjectContext()
|
botAI->GetAiObjectContext()
|
||||||
->GetValue<time_t>("last emote", qualifier)
|
->GetValue<time_t>("last emote", qualifier)
|
||||||
->Set(time(nullptr) + urand(1000, sPlayerbotAIConfig->repeatDelay) / 1000);
|
->Set(time(nullptr) + urand(1000, sPlayerbotAIConfig.repeatDelay) / 1000);
|
||||||
param = qualifier;
|
param = qualifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ void EquipAction::EquipItem(Item* item)
|
|||||||
|
|
||||||
bool EquipUpgradesAction::Execute(Event event)
|
bool EquipUpgradesAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
if (!sPlayerbotAIConfig->autoEquipUpgradeLoot && !sRandomPlayerbotMgr->IsRandomBot(bot))
|
if (!sPlayerbotAIConfig.autoEquipUpgradeLoot && !sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (event.GetSource() == "trade status")
|
if (event.GetSource() == "trade status")
|
||||||
@@ -344,6 +344,27 @@ bool EquipUpgradesAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.GetSource() == "item push result")
|
||||||
|
{
|
||||||
|
WorldPacket p(event.getPacket());
|
||||||
|
p.rpos(0);
|
||||||
|
ObjectGuid playerGuid;
|
||||||
|
uint32 received, created, sendChatMessage, itemSlot, itemId;
|
||||||
|
uint8 bagSlot;
|
||||||
|
|
||||||
|
p >> playerGuid;
|
||||||
|
p >> received;
|
||||||
|
p >> created;
|
||||||
|
p >> sendChatMessage;
|
||||||
|
p >> bagSlot;
|
||||||
|
p >> itemSlot;
|
||||||
|
p >> itemId;
|
||||||
|
|
||||||
|
ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
|
||||||
|
if (item->Class == ITEM_CLASS_TRADE_GOODS && item->SubClass == ITEM_SUBCLASS_MEAT)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CollectItemsVisitor visitor;
|
CollectItemsVisitor visitor;
|
||||||
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
|
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
|
||||||
|
|
||||||
510
src/Ai/Base/Actions/FishingAction.cpp
Normal file
510
src/Ai/Base/Actions/FishingAction.cpp
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
/*
|
||||||
|
* 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 "FishingAction.h"
|
||||||
|
#include "FishValues.h"
|
||||||
|
#include "Event.h"
|
||||||
|
|
||||||
|
#include "GridNotifiers.h"
|
||||||
|
#include "GridNotifiersImpl.h"
|
||||||
|
#include "ItemPackets.h"
|
||||||
|
#include "LastMovementValue.h"
|
||||||
|
#include "Map.h"
|
||||||
|
#include "MovementActions.h"
|
||||||
|
#include "Object.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "PlayerbotTextMgr.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
#include "Position.h"
|
||||||
|
|
||||||
|
uint32 const FISHING_SPELL = 7620;
|
||||||
|
uint32 const FISHING_POLE = 6256;
|
||||||
|
uint32 const FISHING_BOBBER = 35591;
|
||||||
|
float const MIN_DISTANCE_TO_WATER = 10.0f; // Minimum spell distance
|
||||||
|
float const MAX_DISTANCE_TO_WATER = 20.0f; // Maximum spell distance
|
||||||
|
float const HEIGHT_ABOVE_WATER_TOLERANCE = 1.0f; // Can stand in up to 1 unit of water and still fish.
|
||||||
|
float const SEARCH_INCREMENT = 2.5f;
|
||||||
|
float const HEIGHT_SEARCH_BUFFER = 10.0f; // Height buffer to prevent potentially missing the model the bot is standing on.
|
||||||
|
float const SEARCH_LAND_BUFFER = 0.5f;
|
||||||
|
uint32 const FISHING_LOCATION_TIMEOUT = 180000; //Three minutes
|
||||||
|
|
||||||
|
static bool IsFishingPole(Item* const item)
|
||||||
|
{
|
||||||
|
if (!item)
|
||||||
|
return false;
|
||||||
|
const ItemTemplate* proto = item->GetTemplate();
|
||||||
|
return proto && proto->Class == ITEM_CLASS_WEAPON &&
|
||||||
|
proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
float HasFishableWaterOrLand(float x, float y, float z, Map* map, uint32 phaseMask, bool checkForLand=false)
|
||||||
|
{
|
||||||
|
if (!map)
|
||||||
|
return INVALID_HEIGHT;
|
||||||
|
|
||||||
|
LiquidData const& liq = map->GetLiquidData(phaseMask, x, y, z+HEIGHT_ABOVE_WATER_TOLERANCE, DEFAULT_COLLISION_HEIGHT, MAP_ALL_LIQUIDS);
|
||||||
|
float ground = map->GetHeight(phaseMask, x, y, z + HEIGHT_SEARCH_BUFFER, true);
|
||||||
|
if (liq.Entry == MAP_LIQUID_TYPE_NO_WATER)
|
||||||
|
{
|
||||||
|
if (checkForLand)
|
||||||
|
return ground;
|
||||||
|
return INVALID_HEIGHT;
|
||||||
|
}
|
||||||
|
if (checkForLand)
|
||||||
|
{
|
||||||
|
if (ground > liq.Level - HEIGHT_ABOVE_WATER_TOLERANCE)
|
||||||
|
return ground;
|
||||||
|
return INVALID_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (liq.Level + HEIGHT_ABOVE_WATER_TOLERANCE > ground)
|
||||||
|
{
|
||||||
|
if (abs(liq.DepthLevel) < 0.5f) // too shallow to fish in.
|
||||||
|
return INVALID_HEIGHT;
|
||||||
|
return liq.Level;
|
||||||
|
}
|
||||||
|
return INVALID_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasLosToWater(Player* bot, float wx, float wy, float waterZ)
|
||||||
|
{
|
||||||
|
float z = bot->GetCollisionHeight() + bot->GetPositionZ();
|
||||||
|
return bot->GetMap()->isInLineOfSight(
|
||||||
|
bot->GetPositionX(), bot->GetPositionY(), z,
|
||||||
|
wx, wy, waterZ,
|
||||||
|
bot->GetPhaseMask(),
|
||||||
|
LINEOFSIGHT_ALL_CHECKS,
|
||||||
|
VMAP::ModelIgnoreFlags::Nothing);
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPosition FindLandFromPosition(PlayerbotAI* botAI, float startDistance, float endDistance, float increment, float orientation, WorldPosition targetPos, float fishingSearchWindow, bool checkLOS = true)
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
Map* map = bot->GetMap();
|
||||||
|
uint32 phaseMask = bot->GetPhaseMask();
|
||||||
|
Player* master = botAI->GetMaster();
|
||||||
|
|
||||||
|
float targetX = targetPos.GetPositionX();
|
||||||
|
float targetY = targetPos.GetPositionY();
|
||||||
|
float targetZ = targetPos.GetPositionZ();
|
||||||
|
|
||||||
|
for (float dist = startDistance; dist <= endDistance; dist += increment)
|
||||||
|
{
|
||||||
|
//step backwards from position to bot to find edge of shore.
|
||||||
|
float checkX = targetX - dist * cos(orientation);
|
||||||
|
float checkY = targetY - dist * sin(orientation);
|
||||||
|
|
||||||
|
float groundZ = map->GetHeight(phaseMask, checkX, checkY, targetZ + HEIGHT_SEARCH_BUFFER, true);
|
||||||
|
|
||||||
|
if (groundZ == INVALID_HEIGHT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LiquidData const& liq = map->GetLiquidData(phaseMask, checkX, checkY, targetZ, DEFAULT_COLLISION_HEIGHT, MAP_ALL_LIQUIDS);
|
||||||
|
if (liq.Entry == MAP_LIQUID_TYPE_NO_WATER || groundZ > liq.DepthLevel + HEIGHT_ABOVE_WATER_TOLERANCE)
|
||||||
|
{
|
||||||
|
if (checkLOS)
|
||||||
|
{
|
||||||
|
bool hasLOS = map->isInLineOfSight(checkX, checkY, groundZ, targetX, targetY, targetZ, phaseMask, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing);
|
||||||
|
if (!hasLOS)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Add a distance check for the position to prevent the bot from moving out of range to the master.
|
||||||
|
if (master && botAI->HasStrategy("follow", BOT_STATE_NON_COMBAT) && master->GetDistance(checkX, checkY, groundZ) > fishingSearchWindow - SEARCH_LAND_BUFFER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return WorldPosition(bot->GetMapId(), checkX, checkY, groundZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return WorldPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPosition FindLandRadialFromPosition (PlayerbotAI* botAI, WorldPosition targetPos, float startDistance, float endDistance, float increment, float fishingSearchWindow, int angles = 16)
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
const int numDirections = angles;
|
||||||
|
std::vector<WorldPosition> boundaryPoints;
|
||||||
|
Player* master = botAI->GetMaster();
|
||||||
|
if (!master)
|
||||||
|
return WorldPosition();
|
||||||
|
|
||||||
|
Map* map = bot->GetMap();
|
||||||
|
uint32 phaseMask = bot->GetPhaseMask();
|
||||||
|
|
||||||
|
float targetX = targetPos.GetPositionX();
|
||||||
|
float targetY = targetPos.GetPositionY();
|
||||||
|
float targetZ = targetPos.GetPositionZ();
|
||||||
|
|
||||||
|
for (float dist = startDistance; dist <= endDistance; dist += increment)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numDirections; ++i)
|
||||||
|
{
|
||||||
|
float angle = (2.0f * M_PI * i) / numDirections;
|
||||||
|
float checkX = targetX - cos(angle) * dist;
|
||||||
|
float checkY = targetY - sin(angle) * dist;
|
||||||
|
|
||||||
|
float groundZ = HasFishableWaterOrLand(checkX, checkY, targetZ, map, phaseMask, true);
|
||||||
|
|
||||||
|
if (groundZ == INVALID_HEIGHT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (map->isInLineOfSight(checkX, checkY, groundZ, targetX, targetY, targetZ, phaseMask, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing) && master->GetDistance(checkX, checkY, groundZ) > fishingSearchWindow - SEARCH_LAND_BUFFER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
boundaryPoints.emplace_back(WorldPosition(bot->GetMapId(), checkX, checkY, groundZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boundaryPoints.empty())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boundaryPoints.empty())
|
||||||
|
return WorldPosition();
|
||||||
|
|
||||||
|
if (boundaryPoints.size() == 1)
|
||||||
|
return boundaryPoints[0];
|
||||||
|
|
||||||
|
float minDistance = FLT_MAX;
|
||||||
|
WorldLocation closestPoint = WorldPosition();
|
||||||
|
for (auto const& pos : boundaryPoints)
|
||||||
|
{
|
||||||
|
float distance = bot->GetExactDist2d(&pos);
|
||||||
|
if (distance < minDistance)
|
||||||
|
{
|
||||||
|
minDistance = distance;
|
||||||
|
closestPoint = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closestPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPosition FindWaterRadial(Player* bot, float x, float y, float z, Map* map, uint32 phaseMask, float minDistance, float maxDistance, float increment, bool checkLOS, int numDirections)
|
||||||
|
{
|
||||||
|
std::vector<WorldPosition> boundaryPoints;
|
||||||
|
|
||||||
|
float dist = minDistance;
|
||||||
|
while (dist <= maxDistance)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numDirections; ++i)
|
||||||
|
{
|
||||||
|
float angle = (2.0f * M_PI * i) / numDirections;
|
||||||
|
float checkX = x + cos(angle) * dist;
|
||||||
|
float checkY = y + sin(angle) * dist;
|
||||||
|
|
||||||
|
float waterZ = HasFishableWaterOrLand(checkX, checkY, z, map, phaseMask);
|
||||||
|
|
||||||
|
if (waterZ == INVALID_HEIGHT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (checkLOS && !HasLosToWater(bot, checkX, checkY, waterZ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
boundaryPoints.emplace_back(WorldPosition(bot->GetMapId(), checkX, checkY, waterZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boundaryPoints.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
dist += increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boundaryPoints.empty())
|
||||||
|
return WorldPosition();
|
||||||
|
|
||||||
|
if (boundaryPoints.size() == 1)
|
||||||
|
return boundaryPoints[0];
|
||||||
|
// return the central point in the identified positions in to try to be perpendicular to the shore.
|
||||||
|
return boundaryPoints[boundaryPoints.size() / 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPosition FindFishingHole(PlayerbotAI* botAI)
|
||||||
|
{
|
||||||
|
Player* player = botAI->GetBot();
|
||||||
|
GuidVector gos = PAI_VALUE(GuidVector, "nearest game objects no los");
|
||||||
|
GameObject* nearestFishingHole = nullptr;
|
||||||
|
float minDist = std::numeric_limits<float>::max();
|
||||||
|
for (auto const& guid : gos)
|
||||||
|
{
|
||||||
|
GameObject* go = botAI->GetGameObject(guid);
|
||||||
|
if (!go)
|
||||||
|
continue;
|
||||||
|
if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE)
|
||||||
|
{
|
||||||
|
float dist = player->GetDistance2d(go);
|
||||||
|
if (dist < minDist)
|
||||||
|
{
|
||||||
|
minDist = dist;
|
||||||
|
nearestFishingHole = go;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nearestFishingHole)
|
||||||
|
return WorldPosition(nearestFishingHole->GetMapId(), nearestFishingHole->GetPositionX(), nearestFishingHole->GetPositionY(), nearestFishingHole->GetPositionZ());
|
||||||
|
|
||||||
|
return WorldPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MoveNearWaterAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
WorldPosition landSpot = AI_VALUE(WorldPosition, "fishing spot");
|
||||||
|
if (landSpot.IsValid())
|
||||||
|
return MoveTo(landSpot.GetMapId(), landSpot.GetPositionX(), landSpot.GetPositionY(), landSpot.GetPositionZ());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MoveNearWaterAction::isUseful()
|
||||||
|
{
|
||||||
|
if (!AI_VALUE(bool, "can fish"))
|
||||||
|
return false;
|
||||||
|
FishingSpotValue* fishingSpotValueObject = (FishingSpotValue*)context->GetValue<WorldPosition>("fishing spot");
|
||||||
|
WorldPosition pos = fishingSpotValueObject->Get();
|
||||||
|
return !pos.IsValid() || fishingSpotValueObject->IsStale(FISHING_LOCATION_TIMEOUT) ||
|
||||||
|
bot->GetExactDist(&pos) < 0.1f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MoveNearWaterAction::isPossible()
|
||||||
|
{
|
||||||
|
Player* master = botAI->GetMaster();
|
||||||
|
float fishingSearchWindow;
|
||||||
|
|
||||||
|
if (master)
|
||||||
|
fishingSearchWindow = sPlayerbotAIConfig.fishingDistanceFromMaster;
|
||||||
|
else
|
||||||
|
fishingSearchWindow = sPlayerbotAIConfig.fishingDistance;
|
||||||
|
|
||||||
|
WorldPosition fishingHole = FindFishingHole(botAI);
|
||||||
|
|
||||||
|
if (fishingHole.IsValid())
|
||||||
|
{
|
||||||
|
float distance = bot->GetExactDist2d(&fishingHole);
|
||||||
|
bool hasLOS = bot->IsWithinLOS(fishingHole.GetPositionX(), fishingHole.GetPositionY(), fishingHole.GetPositionZ());
|
||||||
|
// Water spot is in range, and we have LOS to it. Set bot position to fishing spot and do not move
|
||||||
|
if (distance >= MIN_DISTANCE_TO_WATER &&
|
||||||
|
distance <= MAX_DISTANCE_TO_WATER && hasLOS)
|
||||||
|
{
|
||||||
|
SET_AI_VALUE(WorldPosition, "fishing spot", WorldPosition(WorldPosition(bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Water spot is out of range, lets look for a spot to move to for the fishing hole.
|
||||||
|
if (distance > MAX_DISTANCE_TO_WATER || distance < MIN_DISTANCE_TO_WATER)
|
||||||
|
{
|
||||||
|
float angle = bot->GetAngle(fishingHole.GetPositionX(), fishingHole.GetPositionY());
|
||||||
|
WorldPosition landSpot = FindLandRadialFromPosition(botAI, fishingHole, MIN_DISTANCE_TO_WATER, MAX_DISTANCE_TO_WATER, SEARCH_INCREMENT, fishingSearchWindow, 32);
|
||||||
|
if (landSpot.IsValid())
|
||||||
|
{
|
||||||
|
SET_AI_VALUE(WorldPosition, "fishing spot", landSpot);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Can the bot fish from current position?
|
||||||
|
WorldPosition waterAtCurrentPos =
|
||||||
|
FindWaterRadial(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMap(),
|
||||||
|
bot->GetPhaseMask(), MIN_DISTANCE_TO_WATER, MAX_DISTANCE_TO_WATER, SEARCH_INCREMENT, true);
|
||||||
|
if (waterAtCurrentPos.IsValid())
|
||||||
|
{
|
||||||
|
SET_AI_VALUE(WorldPosition, "fishing spot",
|
||||||
|
WorldPosition(WorldPosition(bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(),
|
||||||
|
bot->GetPositionZ())));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Lets find some water where we can fish.
|
||||||
|
WorldPosition water = FindWaterRadial(
|
||||||
|
bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||||
|
bot->GetMap(), bot->GetPhaseMask(),
|
||||||
|
MIN_DISTANCE_TO_WATER,
|
||||||
|
fishingSearchWindow + MAX_DISTANCE_TO_WATER,
|
||||||
|
SEARCH_INCREMENT, false);
|
||||||
|
|
||||||
|
if (!water.IsValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool hasLOS = bot->IsWithinLOS(water.GetPositionX(), water.GetPositionY(), water.GetPositionZ());
|
||||||
|
float angle = bot->GetAngle(water.GetPositionX(), water.GetPositionY());
|
||||||
|
WorldPosition landSpot =
|
||||||
|
FindLandFromPosition(botAI, 0.0f, MAX_DISTANCE_TO_WATER, 1.0f, angle, water, fishingSearchWindow, false);
|
||||||
|
|
||||||
|
if (landSpot.IsValid())
|
||||||
|
{
|
||||||
|
SET_AI_VALUE(WorldPosition, "fishing spot", landSpot);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EquipFishingPoleAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
if (!_pole)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WorldPacket eqPacket(CMSG_AUTOEQUIP_ITEM_SLOT, 2);
|
||||||
|
eqPacket << _pole->GetGUID() << uint8(EQUIPMENT_SLOT_MAINHAND);
|
||||||
|
WorldPackets::Item::AutoEquipItemSlot nicePacket(std::move(eqPacket));
|
||||||
|
nicePacket.Read();
|
||||||
|
bot->GetSession()->HandleAutoEquipItemSlotOpcode(nicePacket);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EquipFishingPoleAction::isUseful()
|
||||||
|
{
|
||||||
|
Item* mainHand = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
|
||||||
|
if (IsFishingPole(mainHand))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; ++slot)
|
||||||
|
{
|
||||||
|
if (Item* item = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
|
||||||
|
{
|
||||||
|
if (IsFishingPole(item))
|
||||||
|
{
|
||||||
|
_pole = item;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag)
|
||||||
|
{
|
||||||
|
if (Bag* pBag = bot->GetBagByPos(bag))
|
||||||
|
{
|
||||||
|
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||||
|
{
|
||||||
|
if (Item* item = pBag->GetItemByPos(j))
|
||||||
|
{
|
||||||
|
if (IsFishingPole(item))
|
||||||
|
{
|
||||||
|
_pole = item;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sRandomPlayerbotMgr.IsRandomBot(bot))
|
||||||
|
{
|
||||||
|
bot->StoreNewItemInBestSlots(FISHING_POLE, 1); // Try to get a fishing pole
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player* master = botAI->GetMaster();
|
||||||
|
if (!master)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string masterName = master->GetName();
|
||||||
|
std::string text = PlayerbotTextMgr::instance().GetBotTextOrDefault(
|
||||||
|
"no_fishing_pole_error", "I don't have a Fishing Pole",{});
|
||||||
|
botAI->Whisper(text, masterName);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FishingAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
WorldPosition target = WorldPosition();
|
||||||
|
WorldPosition fishingHole = FindFishingHole(botAI);
|
||||||
|
if (fishingHole.IsValid())
|
||||||
|
{
|
||||||
|
Position pos = fishingHole;
|
||||||
|
float distance = bot->GetExactDist2d(&pos);
|
||||||
|
bool hasLOS = bot->IsWithinLOS(fishingHole.GetPositionX(), fishingHole.GetPositionY(), fishingHole.GetPositionZ());
|
||||||
|
if (distance < MAX_DISTANCE_TO_WATER &&
|
||||||
|
distance > MIN_DISTANCE_TO_WATER && hasLOS)
|
||||||
|
target = fishingHole;
|
||||||
|
}
|
||||||
|
if (!target.IsValid())
|
||||||
|
{
|
||||||
|
target = FindWaterRadial(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||||
|
bot->GetPositionZ(), bot->GetMap(), bot->GetPhaseMask(),
|
||||||
|
MIN_DISTANCE_TO_WATER, MAX_DISTANCE_TO_WATER, SEARCH_INCREMENT, true, 32);
|
||||||
|
if (!target.IsValid())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Position pos = target;
|
||||||
|
|
||||||
|
if (!bot->HasInArc(1.0, &pos, 1.0))
|
||||||
|
{
|
||||||
|
float angle = bot->GetAngle(pos.GetPositionX(), pos.GetPositionY());
|
||||||
|
bot->SetOrientation(angle);
|
||||||
|
if (!bot->IsRooted())
|
||||||
|
bot->SendMovementFlagUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
EquipFishingPoleAction equipAction(botAI);
|
||||||
|
if (equipAction.isUseful())
|
||||||
|
return equipAction.Execute(event);
|
||||||
|
|
||||||
|
botAI->CastSpell(FISHING_SPELL, bot);
|
||||||
|
botAI->ChangeStrategy("+use bobber", BOT_STATE_NON_COMBAT);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FishingAction::isUseful()
|
||||||
|
{
|
||||||
|
if (!AI_VALUE(bool, "can fish"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FishingSpotValue* fishingSpotValueObject = (FishingSpotValue*)context->GetValue<WorldPosition>("fishing spot");
|
||||||
|
WorldPosition pos = fishingSpotValueObject->Get();
|
||||||
|
|
||||||
|
if (!pos.IsValid() || fishingSpotValueObject->IsStale(FISHING_LOCATION_TIMEOUT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return bot->GetExactDist(&pos) < 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UseBobberAction::isUseful()
|
||||||
|
{
|
||||||
|
return AI_VALUE(bool, "can use fishing bobber");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UseBobberAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
GuidVector gos = AI_VALUE(GuidVector, "nearest game objects no los");
|
||||||
|
for (auto const& guid : gos)
|
||||||
|
{
|
||||||
|
if (GameObject* go = botAI->GetGameObject(guid))
|
||||||
|
{
|
||||||
|
if (go->GetEntry() != FISHING_BOBBER)
|
||||||
|
continue;
|
||||||
|
if (go->GetOwnerGUID() != bot->GetGUID())
|
||||||
|
continue;
|
||||||
|
if (go->getLootState() == GO_READY)
|
||||||
|
{
|
||||||
|
go->Use(bot);
|
||||||
|
botAI->ChangeStrategy("-use bobber", BOT_STATE_NON_COMBAT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EndMasterFishingAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
botAI->ChangeStrategy("-master fishing", BOT_STATE_NON_COMBAT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EndMasterFishingAction::isUseful()
|
||||||
|
{
|
||||||
|
FishingSpotValue* fishingSpotValueObject = (FishingSpotValue*)context->GetValue<WorldPosition>("fishing spot");
|
||||||
|
WorldPosition pos = fishingSpotValueObject->Get();
|
||||||
|
if (pos.IsValid() && !fishingSpotValueObject->IsStale(FISHING_LOCATION_TIMEOUT) && pos == bot->GetPosition())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WorldPosition nearWater = FindWaterRadial(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||||
|
bot->GetMap(), bot->GetPhaseMask(), MIN_DISTANCE_TO_WATER, sPlayerbotAIConfig.endFishingWithMaster, 10.0f);
|
||||||
|
return !nearWater.IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoveBobberStrategyAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
botAI->ChangeStrategy("-use bobber", BOT_STATE_NON_COMBAT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
71
src/Ai/Base/Actions/FishingAction.h
Normal file
71
src/Ai/Base/Actions/FishingAction.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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_FISHINGACTION_H
|
||||||
|
#define _PLAYERBOT_FISHINGACTION_H
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
#include "MovementActions.h"
|
||||||
|
#include "Event.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
|
||||||
|
extern const uint32 FISHING_SPELL;
|
||||||
|
extern const uint32 FISHING_POLE;
|
||||||
|
extern const uint32 FISHING_BOBBER;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
class PlayerbotAI;
|
||||||
|
|
||||||
|
class FishingAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FishingAction(PlayerbotAI* botAI) : Action(botAI, "go fishing"){}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EquipFishingPoleAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EquipFishingPoleAction(PlayerbotAI* botAI) : Action(botAI, "equip fishing pole") {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
private:
|
||||||
|
Item* _pole = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MoveNearWaterAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MoveNearWaterAction(PlayerbotAI* botAI): MovementAction(botAI, "move near water") {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
bool isPossible() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UseBobberAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UseBobberAction(PlayerbotAI* botAI) : Action(botAI, "use fishing bobber") {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EndMasterFishingAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EndMasterFishingAction(PlayerbotAI* botAI) : Action(botAI, "end master fishing") {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RemoveBobberStrategyAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RemoveBobberStrategyAction(PlayerbotAI* botAI) : Action(botAI, "remove bobber strategy") {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
@@ -44,7 +44,7 @@ bool FollowAction::Execute(Event event)
|
|||||||
// botAI->PetFollow();
|
// botAI->PetFollow();
|
||||||
// }
|
// }
|
||||||
// if (moved)
|
// if (moved)
|
||||||
// botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay);
|
// botAI->SetNextCheckDelay(sPlayerbotAIConfig.reactDelay);
|
||||||
|
|
||||||
return moved;
|
return moved;
|
||||||
}
|
}
|
||||||
@@ -97,8 +97,10 @@ bool FollowAction::isUseful()
|
|||||||
|
|
||||||
distance = bot->GetDistance(loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ());
|
distance = bot->GetDistance(loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ());
|
||||||
}
|
}
|
||||||
|
if (botAI->HasStrategy("master fishing", BOT_STATE_NON_COMBAT))
|
||||||
|
return ServerFacade::instance().IsDistanceGreaterThan(distance, sPlayerbotAIConfig.fishingDistanceFromMaster);
|
||||||
|
|
||||||
return sServerFacade->IsDistanceGreaterThan(distance, formation->GetMaxDistance());
|
return ServerFacade::instance().IsDistanceGreaterThan(distance, formation->GetMaxDistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FollowAction::CanDeadFollow(Unit* target)
|
bool FollowAction::CanDeadFollow(Unit* target)
|
||||||
@@ -128,7 +130,7 @@ bool FleeToGroupLeaderAction::Execute(Event event)
|
|||||||
WorldPosition bosPos(bot);
|
WorldPosition bosPos(bot);
|
||||||
float distance = bosPos.fDist(targetPos);
|
float distance = bosPos.fDist(targetPos);
|
||||||
|
|
||||||
if (distance < sPlayerbotAIConfig->reactDistance * 3)
|
if (distance < sPlayerbotAIConfig.reactDistance * 3)
|
||||||
{
|
{
|
||||||
if (!urand(0, 3))
|
if (!urand(0, 3))
|
||||||
botAI->TellMaster("I am close, wait for me!");
|
botAI->TellMaster("I am close, wait for me!");
|
||||||
@@ -113,7 +113,7 @@ bool TogglePetSpellAutoCastAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Debug message if pet spells have been toggled and debug is enabled
|
// Debug message if pet spells have been toggled and debug is enabled
|
||||||
if (toggled && sPlayerbotAIConfig->petChatCommandDebug == 1)
|
if (toggled && sPlayerbotAIConfig.petChatCommandDebug == 1)
|
||||||
botAI->TellMaster("Pet autocast spells have been toggled.");
|
botAI->TellMaster("Pet autocast spells have been toggled.");
|
||||||
|
|
||||||
return toggled;
|
return toggled;
|
||||||
@@ -185,7 +185,7 @@ bool SetPetStanceAction::Execute(Event /*event*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the default pet stance from the configuration
|
// Get the default pet stance from the configuration
|
||||||
int32 stance = sPlayerbotAIConfig->defaultPetStance;
|
int32 stance = sPlayerbotAIConfig.defaultPetStance;
|
||||||
ReactStates react = REACT_DEFENSIVE;
|
ReactStates react = REACT_DEFENSIVE;
|
||||||
std::string stanceText = "defensive (from config, fallback)";
|
std::string stanceText = "defensive (from config, fallback)";
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ bool SetPetStanceAction::Execute(Event /*event*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If debug is enabled in config, inform the master of the new stance
|
// If debug is enabled in config, inform the master of the new stance
|
||||||
if (sPlayerbotAIConfig->petChatCommandDebug == 1)
|
if (sPlayerbotAIConfig.petChatCommandDebug == 1)
|
||||||
botAI->TellMaster("Pet stance set to " + stanceText + " (applied to all pets/guardians).");
|
botAI->TellMaster("Pet stance set to " + stanceText + " (applied to all pets/guardians).");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -87,7 +87,7 @@ namespace ai::buff
|
|||||||
{
|
{
|
||||||
std::string castName = baseName;
|
std::string castName = baseName;
|
||||||
Group* g = bot->GetGroup();
|
Group* g = bot->GetGroup();
|
||||||
if (!g || g->GetMembersCount() < static_cast<uint32>(sPlayerbotAIConfig->minBotsForGreaterBuff))
|
if (!g || g->GetMembersCount() < static_cast<uint32>(sPlayerbotAIConfig.minBotsForGreaterBuff))
|
||||||
return castName; // Group too small: stay in solo mode
|
return castName; // Group too small: stay in solo mode
|
||||||
|
|
||||||
if (std::string const groupName = GroupVariantFor(baseName); !groupName.empty())
|
if (std::string const groupName = GroupVariantFor(baseName); !groupName.empty())
|
||||||
@@ -114,7 +114,7 @@ namespace ai::buff
|
|||||||
time_t now = std::time(nullptr);
|
time_t now = std::time(nullptr);
|
||||||
uint32 botLow = static_cast<uint32>(bot->GetGUID().GetCounter());
|
uint32 botLow = static_cast<uint32>(bot->GetGUID().GetCounter());
|
||||||
time_t& last = s_lastWarn[ std::make_pair(botLow, groupName) ];
|
time_t& last = s_lastWarn[ std::make_pair(botLow, groupName) ];
|
||||||
if (!last || now - last >= sPlayerbotAIConfig->rpWarningCooldown) // Configurable anti-spam
|
if (!last || now - last >= sPlayerbotAIConfig.rpWarningCooldown) // Configurable anti-spam
|
||||||
{
|
{
|
||||||
// DB Key choice in regard of the buff
|
// DB Key choice in regard of the buff
|
||||||
std::string key;
|
std::string key;
|
||||||
@@ -132,7 +132,7 @@ namespace ai::buff
|
|||||||
placeholders["%group_spell"] = groupName;
|
placeholders["%group_spell"] = groupName;
|
||||||
placeholders["%base_spell"] = baseName;
|
placeholders["%base_spell"] = baseName;
|
||||||
|
|
||||||
std::string announceText = sPlayerbotTextMgr->GetBotTextOrDefault(key,
|
std::string announceText = PlayerbotTextMgr::instance().GetBotTextOrDefault(key,
|
||||||
"Out of components for %group_spell. Using %base_spell!", placeholders);
|
"Out of components for %group_spell. Using %base_spell!", placeholders);
|
||||||
|
|
||||||
announce(announceText);
|
announce(announceText);
|
||||||
@@ -82,7 +82,7 @@ bool CastSpellAction::isPossible()
|
|||||||
{
|
{
|
||||||
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true))
|
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true))
|
||||||
{
|
{
|
||||||
if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster()))
|
if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster()))
|
||||||
{
|
{
|
||||||
LOG_DEBUG("playerbots", "Can cast spell failed. Vehicle. - bot name: {}", bot->GetName());
|
LOG_DEBUG("playerbots", "Can cast spell failed. Vehicle. - bot name: {}", bot->GetName());
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ bool CastSpellAction::isPossible()
|
|||||||
|
|
||||||
if (spell == "mount" && bot->IsInCombat())
|
if (spell == "mount" && bot->IsInCombat())
|
||||||
{
|
{
|
||||||
if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster()))
|
if (!sPlayerbotAIConfig.logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster()))
|
||||||
{
|
{
|
||||||
LOG_DEBUG("playerbots", "Can cast spell failed. Mount. - bot name: {}", bot->GetName());
|
LOG_DEBUG("playerbots", "Can cast spell failed. Mount. - bot name: {}", bot->GetName());
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ bool CastSpellAction::isUseful()
|
|||||||
|
|
||||||
return spellTarget &&
|
return spellTarget &&
|
||||||
AI_VALUE2(bool, "spell cast useful",
|
AI_VALUE2(bool, "spell cast useful",
|
||||||
spell); // && sServerFacade->GetDistance2d(bot, spellTarget) <= (range + combatReach);
|
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)
|
||||||
@@ -265,11 +265,6 @@ CastShootAction::CastShootAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NextAction** CastSpellAction::getPrerequisites()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value<Unit*>* CastDebuffSpellOnAttackerAction::GetTargetValue()
|
Value<Unit*>* CastDebuffSpellOnAttackerAction::GetTargetValue()
|
||||||
{
|
{
|
||||||
return context->GetValue<Unit*>("attacker without aura", spell);
|
return context->GetValue<Unit*>("attacker without aura", spell);
|
||||||
@@ -27,7 +27,11 @@ public:
|
|||||||
bool isUseful() override;
|
bool isUseful() override;
|
||||||
ActionThreatType getThreatType() override { return ActionThreatType::Single; }
|
ActionThreatType getThreatType() override { return ActionThreatType::Single; }
|
||||||
|
|
||||||
NextAction** getPrerequisites() override;
|
std::vector<NextAction> getPrerequisites() override
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::string const getSpell() { return spell; }
|
std::string const getSpell() { return spell; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -193,10 +197,12 @@ public:
|
|||||||
ResurrectPartyMemberAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) {}
|
ResurrectPartyMemberAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) {}
|
||||||
|
|
||||||
std::string const GetTargetName() override { return "party member to resurrect"; }
|
std::string const GetTargetName() override { return "party member to resurrect"; }
|
||||||
NextAction** getPrerequisites() override
|
std::vector<NextAction> getPrerequisites() override
|
||||||
{
|
{
|
||||||
return NextAction::merge(NextAction::array(0, new NextAction("reach party member to resurrect"), NULL),
|
return NextAction::merge(
|
||||||
Action::getPrerequisites());
|
{ NextAction("reach party member to resurrect") },
|
||||||
|
Action::getPrerequisites()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ Unit* GiveItemAction::GetTarget() { return AI_VALUE2(Unit*, "party member withou
|
|||||||
|
|
||||||
bool GiveItemAction::isUseful()
|
bool GiveItemAction::isUseful()
|
||||||
{
|
{
|
||||||
return GetTarget() && AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig->lowMana;
|
return GetTarget() && AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig.lowMana;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit* GiveFoodAction::GetTarget() { return AI_VALUE(Unit*, "party member without food"); }
|
Unit* GiveFoodAction::GetTarget() { return AI_VALUE(Unit*, "party member without food"); }
|
||||||
@@ -74,7 +74,7 @@ bool GiveFoodAction::isUseful()
|
|||||||
if (!GetTarget())
|
if (!GetTarget())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool isRandomBot = GetTarget()->IsPlayer() && sRandomPlayerbotMgr->IsRandomBot((Player*)GetTarget());
|
bool isRandomBot = GetTarget()->IsPlayer() && sRandomPlayerbotMgr.IsRandomBot((Player*)GetTarget());
|
||||||
|
|
||||||
return !isRandomBot || (isRandomBot && !botAI->HasCheat(BotCheatMask::food));
|
return !isRandomBot || (isRandomBot && !botAI->HasCheat(BotCheatMask::food));
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ bool GiveWaterAction::isUseful()
|
|||||||
if (!GetTarget())
|
if (!GetTarget())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool isRandomBot = GetTarget()->IsPlayer() && sRandomPlayerbotMgr->IsRandomBot((Player*)GetTarget());
|
bool isRandomBot = GetTarget()->IsPlayer() && sRandomPlayerbotMgr.IsRandomBot((Player*)GetTarget());
|
||||||
|
|
||||||
return !isRandomBot || (isRandomBot && !botAI->HasCheat(BotCheatMask::food));
|
return !isRandomBot || (isRandomBot && !botAI->HasCheat(BotCheatMask::food));
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ bool GoAction::Execute(Event event)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
botAI->TellMasterNoFacing("Clearing travel target");
|
botAI->TellMasterNoFacing("Clearing travel target");
|
||||||
target->setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition);
|
target->setTarget(TravelMgr::instance().nullTravelDestination, TravelMgr::instance().nullWorldPosition);
|
||||||
target->setForced(false);
|
target->setForced(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -75,8 +75,8 @@ bool GoAction::Execute(Event event)
|
|||||||
if (GameObject* go = botAI->GetGameObject(guid))
|
if (GameObject* go = botAI->GetGameObject(guid))
|
||||||
if (go->isSpawned())
|
if (go->isSpawned())
|
||||||
{
|
{
|
||||||
if (sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, go),
|
if (ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, go),
|
||||||
sPlayerbotAIConfig->reactDistance))
|
sPlayerbotAIConfig.reactDistance))
|
||||||
{
|
{
|
||||||
botAI->TellError("It is too far away");
|
botAI->TellError("It is too far away");
|
||||||
return false;
|
return false;
|
||||||
@@ -86,7 +86,7 @@ bool GoAction::Execute(Event event)
|
|||||||
out << "Moving to " << ChatHelper::FormatGameobject(go);
|
out << "Moving to " << ChatHelper::FormatGameobject(go);
|
||||||
botAI->TellMasterNoFacing(out.str());
|
botAI->TellMasterNoFacing(out.str());
|
||||||
return MoveNear(bot->GetMapId(), go->GetPositionX(), go->GetPositionY(), go->GetPositionZ() + 0.5f,
|
return MoveNear(bot->GetMapId(), go->GetPositionX(), go->GetPositionY(), go->GetPositionZ() + 0.5f,
|
||||||
sPlayerbotAIConfig->followDistance);
|
sPlayerbotAIConfig.followDistance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -106,7 +106,7 @@ bool GoAction::Execute(Event event)
|
|||||||
out << "Moving to " << unit->GetName();
|
out << "Moving to " << unit->GetName();
|
||||||
botAI->TellMasterNoFacing(out.str());
|
botAI->TellMasterNoFacing(out.str());
|
||||||
return MoveNear(bot->GetMapId(), unit->GetPositionX(), unit->GetPositionY(),
|
return MoveNear(bot->GetMapId(), unit->GetPositionX(), unit->GetPositionY(),
|
||||||
unit->GetPositionZ() + 0.5f, sPlayerbotAIConfig->followDistance);
|
unit->GetPositionZ() + 0.5f, sPlayerbotAIConfig.followDistance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,8 +176,8 @@ bool GoAction::Execute(Event event)
|
|||||||
float z = bot->GetPositionZ();
|
float z = bot->GetPositionZ();
|
||||||
bot->UpdateAllowedPositionZ(x, y, z);
|
bot->UpdateAllowedPositionZ(x, y, z);
|
||||||
|
|
||||||
if (sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, x, y),
|
if (ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, x, y),
|
||||||
sPlayerbotAIConfig->reactDistance))
|
sPlayerbotAIConfig.reactDistance))
|
||||||
{
|
{
|
||||||
botAI->TellMaster("It is too far away");
|
botAI->TellMaster("It is too far away");
|
||||||
return false;
|
return false;
|
||||||
@@ -203,14 +203,14 @@ bool GoAction::Execute(Event event)
|
|||||||
out << "Moving to " << x1 << "," << y1;
|
out << "Moving to " << x1 << "," << y1;
|
||||||
botAI->TellMasterNoFacing(out.str());
|
botAI->TellMasterNoFacing(out.str());
|
||||||
|
|
||||||
return MoveNear(bot->GetMapId(), x, y, z + 0.5f, sPlayerbotAIConfig->followDistance);
|
return MoveNear(bot->GetMapId(), x, y, z + 0.5f, sPlayerbotAIConfig.followDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionInfo pos = context->GetValue<PositionMap&>("position")->Get()[param];
|
PositionInfo pos = context->GetValue<PositionMap&>("position")->Get()[param];
|
||||||
if (pos.isSet())
|
if (pos.isSet())
|
||||||
{
|
{
|
||||||
if (sServerFacade->IsDistanceGreaterThan(sServerFacade->GetDistance2d(bot, pos.x, pos.y),
|
if (ServerFacade::instance().IsDistanceGreaterThan(ServerFacade::instance().GetDistance2d(bot, pos.x, pos.y),
|
||||||
sPlayerbotAIConfig->reactDistance))
|
sPlayerbotAIConfig.reactDistance))
|
||||||
{
|
{
|
||||||
botAI->TellError("It is too far away");
|
botAI->TellError("It is too far away");
|
||||||
return false;
|
return false;
|
||||||
@@ -219,7 +219,7 @@ bool GoAction::Execute(Event event)
|
|||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "Moving to position " << param;
|
out << "Moving to position " << param;
|
||||||
botAI->TellMasterNoFacing(out.str());
|
botAI->TellMasterNoFacing(out.str());
|
||||||
return MoveNear(bot->GetMapId(), pos.x, pos.y, pos.z + 0.5f, sPlayerbotAIConfig->followDistance);
|
return MoveNear(bot->GetMapId(), pos.x, pos.y, pos.z + 0.5f, sPlayerbotAIConfig.followDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
botAI->TellMaster("Whisper 'go x,y', 'go [game object]', 'go unit' or 'go position' and I will go there");
|
botAI->TellMaster("Whisper 'go x,y', 'go [game object]', 'go unit' or 'go position' and I will go there");
|
||||||
@@ -20,7 +20,7 @@ bool GreetAction::Execute(Event event)
|
|||||||
if (!player)
|
if (!player)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, player, sPlayerbotAIConfig->sightDistance))
|
if (!bot->HasInArc(CAST_ANGLE_IN_FRONT, player, sPlayerbotAIConfig.sightDistance))
|
||||||
bot->SetFacingToObject(player);
|
bot->SetFacingToObject(player);
|
||||||
|
|
||||||
ObjectGuid oldSel = bot->GetTarget();
|
ObjectGuid oldSel = bot->GetTarget();
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user