mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-02-20 10:00:02 +01:00
Big update.
This commit is contained in:
parent
b3d00ccb26
commit
b952636f0d
2
.github/workflows/core-build.yml
vendored
2
.github/workflows/core-build.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
path: 'modules/skeleton-module'
|
||||
path: 'modules/mod_playerbots'
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
||||
@ -6,27 +6,27 @@
|
||||
## BASE SQL
|
||||
|
||||
DB_AUTH_CUSTOM_PATHS+=(
|
||||
"$MOD_SKELETON_ROOT/sql/auth/base/"
|
||||
$MOD_PLAYERBOTS_ROOT"/sql/auth/base/"
|
||||
)
|
||||
|
||||
DB_CHARACTERS_CUSTOM_PATHS+=(
|
||||
"$MOD_SKELETON_ROOT/sql/characters/base/"
|
||||
$MOD_PLAYERBOTS_ROOT"/sql/characters/base/"
|
||||
)
|
||||
|
||||
DB_WORLD_CUSTOM_PATHS+=(
|
||||
"$MOD_SKELETON_ROOT/sql/world/base/"
|
||||
$MOD_PLAYERBOTS_ROOT"/sql/world/base/"
|
||||
)
|
||||
|
||||
## UPDATES
|
||||
|
||||
DB_AUTH_UPDATES_PATHS+=(
|
||||
"$MOD_SKELETON_ROOT/sql/auth/updates/"
|
||||
DB_AUTH_UPDATE_PATHS+=(
|
||||
$MOD_PLAYERBOTS_ROOT"/sql/auth/updates/"
|
||||
)
|
||||
|
||||
DB_CHARACTERS_UPDATES_PATHS+=(
|
||||
"$MOD_SKELETON_ROOT/sql/characters/updates/"
|
||||
DB_CHARACTERS_UPDATE_PATHS+=(
|
||||
$MOD_PLAYERBOTS_ROOT"/sql/characters/updates/"
|
||||
)
|
||||
|
||||
DB_WORLD_UPDATES_PATHS+=(
|
||||
"$MOD_SKELETON_ROOT/sql/world/updates/"
|
||||
DB_WORLD_UPDATE_PATHS+=(
|
||||
$MOD_PLAYERBOTS_ROOT"/sql/world/updates/"
|
||||
)
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
#
|
||||
|
||||
[worldserver]
|
||||
|
||||
########################################
|
||||
# My module configuration
|
||||
########################################
|
||||
#
|
||||
# MyModule.Enable
|
||||
# Description: Enable my module and print "Hello World" message at server start
|
||||
# Default: 0 - Disabled
|
||||
# 1 - Enabled
|
||||
#
|
||||
|
||||
MyModule.Enable = 0
|
||||
644
conf/playerbots.conf.dist
Normal file
644
conf/playerbots.conf.dist
Normal file
@ -0,0 +1,644 @@
|
||||
##########################################
|
||||
# Playerbot Configuration file #
|
||||
##########################################
|
||||
|
||||
# Enable or disable AI Playerbot
|
||||
AiPlayerbot.Enabled = 1
|
||||
|
||||
# Enable random bot system
|
||||
AiPlayerbot.RandomBotAutologin = 1
|
||||
|
||||
# Log on all random bots on start
|
||||
AiPlayerbot.RandomBotLoginAtStartup = 1
|
||||
|
||||
# Delete all random bot accounts (reset randombots)
|
||||
AiPlayerbot.DeleteRandomBotAccounts = 0
|
||||
|
||||
# auto-login all player alts as bots on player login
|
||||
AiPlayerbot.BotAutologin = 0
|
||||
|
||||
# Guild Task system
|
||||
AiPlayerbot.EnableGuildTasks = 1
|
||||
|
||||
# Enable LFG for random bots
|
||||
AiPlayerbot.RandomBotJoinLfg = 1
|
||||
|
||||
# Enable BG/Arena for random Bots
|
||||
AiPlayerbot.RandomBotJoinBG = 1
|
||||
|
||||
# Mark many quests <= Bot level as complete (slows down bot creation)
|
||||
AiPlayerbot.PreQuests = 1
|
||||
|
||||
# Random bot count
|
||||
AiPlayerbot.MinRandomBots = 50
|
||||
AiPlayerbot.MaxRandomBots = 200
|
||||
AiPlayerbot.RandomBotMinLevel = 1
|
||||
AiPlayerbot.RandomBotMaxLevel = 80
|
||||
|
||||
# Accounts to create for random bots
|
||||
AiPlayerbot.RandomBotAccountPrefix = "rndbot"
|
||||
AiPlayerbot.RandomBotAccountCount = 200
|
||||
|
||||
# Random bot guild count
|
||||
AiPlayerbot.RandomBotGuildCount = 20
|
||||
|
||||
# Delete all random bot guilds
|
||||
AiPlayerbot.DeleteRandomBotGuilds = 0
|
||||
|
||||
# Random bot arena team count
|
||||
AiPlayerbot.RandomBotArenaTeamCount = 20
|
||||
|
||||
# Delete all random bot arena teams
|
||||
AiPlayerbot.DeleteRandomBotArenaTeams = 0
|
||||
|
||||
# Change random bot has lower gear
|
||||
AiPlayerbot.RandomGearLoweringChance = 0.15
|
||||
|
||||
# Chance random bot has max level on first randomize (default 0.15)
|
||||
AiPlayerbot.RandomBotMaxLevelChance = 0.15
|
||||
|
||||
# Chance bot chooses RPG (Teleport to random camp for their level) instead of grinding
|
||||
AiPlayerbot.RandomBotRpgChance = 0.20
|
||||
|
||||
# Set randombots movement speed to walking anywhere
|
||||
AiPlayerbot.RandombotsWalkingRPG = 0
|
||||
|
||||
# Set randombots movement speed to walking only inside buildings
|
||||
AiPlayerbot.RandombotsWalkingRPG.InDoors = 0
|
||||
|
||||
# Bots greet to the players
|
||||
AiPlayerbot.EnableGreet = 1
|
||||
|
||||
# Show helmet and cloak on randombots (reset required)
|
||||
AiPlayerbot.RandomBotShowHelmet = 1
|
||||
AiPlayerbot.RandomBotShowCloak = 1
|
||||
|
||||
# Disable random levels for randombots
|
||||
# Every bots started on the specified level and level up by killing mobs.
|
||||
AiPlayerbot.DisableRandomLevels = 0
|
||||
|
||||
# Set randombots starting level here if "AiPlayerbot.DisableRandomLevels" enabled
|
||||
# Recommended: 5+
|
||||
AiPlayerbot.RandombotStartingLevel = 5
|
||||
|
||||
# Set kill XP rate for bots (default: 1)
|
||||
# Server XP Rate * AiPlayerbot.KillXPRate
|
||||
AiPlayerbot.KillXPRate = 1
|
||||
|
||||
# Specify percent of active bots
|
||||
# The default is 10. With 10% of all bots going active or inactive each minute.
|
||||
AiPlayerbot.BotActiveAlone = 10
|
||||
|
||||
# Set minimum level of randombots where gets enchants on items (Maxlevel + 1 to disable)
|
||||
# Default: 60
|
||||
AiPlayerbot.MinEnchantingBotLevel = 60
|
||||
|
||||
# Randombots checking players gear score level and deny the group invite if it's too low
|
||||
# Default: 1 (enabled)
|
||||
AiPlayerbot.GearScoreCheck = 0
|
||||
|
||||
# Quest that will be completed and rewarded to all random bots
|
||||
AiPlayerbot.RandomBotQuestIds = "7848,3802,5505,6502,7761"
|
||||
|
||||
# Randombots will group with nearby bots to do shared quests
|
||||
AiPlayerbot.RandomBotGroupNearby = 1
|
||||
|
||||
# Bots without a master will say their lines
|
||||
AiPlayerbot.RandomBotSayWithoutMaster = 0
|
||||
|
||||
# Automation
|
||||
|
||||
# Bots pick their quest reward (yes = picks first useful item, no = list all rewards, ask = pick useful item and lists if multiple)
|
||||
AiPlayerbot.AutoPickReward = yes
|
||||
|
||||
# Bots equip upgrades (Bots will equip any item obtained from looting or a quest if they are upgrades)
|
||||
# Default: 0 (disabled)
|
||||
AiPlayerbot.AutoEquipUpgradeLoot = 1
|
||||
|
||||
# Sync quests with player (Bots will complete quests the moment you hand them in. Bots will ignore looting quest items.)
|
||||
# Default: 0 (disabled)
|
||||
AiPlayerbot.SyncQuestWithPlayer = 0
|
||||
|
||||
# Bots will auto-complete quests for the player when handing in
|
||||
# Default: 0 (disabled)
|
||||
AiPlayerbot.SyncQuestForPlayer = 0
|
||||
|
||||
# Sync max random bot level with max level of online players
|
||||
# Default: 0 (disabled)
|
||||
AiPlayerbot.SyncLevelWithPlayers = 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)
|
||||
AiPlayerbot.AutoTrainSpells = yes
|
||||
|
||||
# Bot automatically picks talent points based on current spec (full = pick spec based on probability if multiple are like current spec, semi = only apply points if 1 spec looks like current spec, no = no auto talent points)
|
||||
AiPlayerbot.AutoPickTalents = full
|
||||
|
||||
# Bots automatically learn trainable spells on levelup
|
||||
# Default: 0 (disabled)
|
||||
AiPlayerbot.AutoLearnTrainerSpells = 0
|
||||
|
||||
# Bots automatically learn classquest reward spells on levelup
|
||||
# Default: 0 (disabled)
|
||||
AiPlayerbot.AutoLearnQuestSpells = 0
|
||||
|
||||
# Random Bots will pick quests on their own and try to complete
|
||||
# Default: 0 (disabled)
|
||||
AiPlayerbot.AutoDoQuests = 0
|
||||
|
||||
##################################################################################
|
||||
# #
|
||||
# All other parameters are optional but can be changed by uncommenting them here #
|
||||
# #
|
||||
##################################################################################
|
||||
|
||||
##################################################################################
|
||||
# #
|
||||
# Premade builds #
|
||||
# #
|
||||
##################################################################################
|
||||
#
|
||||
# AiPlayerbot.PremadeSpecName.<class>.<specno> = <name> #Name of the talent specialisation
|
||||
# AiPlayerbot.PremadeSpecProb.<class>.<specno> = <number> #Probability Randombots will pick this spec. (default 100)
|
||||
# AiPlayerbot.PremadeSpecLink.<class>.<specno>.<level> = <link> #Wowhead style link the bot should work towards at given level.
|
||||
|
||||
# Preset talents supplied by Lidocain. Do you have more/improved specs? Let us know!
|
||||
# Warrior
|
||||
AiPlayerbot.PremadeSpecName.1.0 = pve arms
|
||||
AiPlayerbot.PremadeSpecLink.1.0.80 = 3022032123335100202012013031251-32505010002
|
||||
AiPlayerbot.PremadeSpecName.1.1 = pve fury
|
||||
AiPlayerbot.PremadeSpecLink.1.1.80 = 30202300233-305053000500310153120511351
|
||||
AiPlayerbot.PremadeSpecName.1.2 = pve prot
|
||||
AiPlayerbot.PremadeSpecLink.1.2.80 = 05-3025-053351225000210521030113321
|
||||
|
||||
AiPlayerbot.PremadeSpecName.1.3 = pvp arms
|
||||
AiPlayerbot.PremadeSpecLink.1.3.80 = 3020232023335100222212013221251-32500013
|
||||
AiPlayerbot.PremadeSpecName.1.4 = pvp fury
|
||||
AiPlayerbot.PremadeSpecLink.1.4.80 = 32003200233-325000131504012050122511351
|
||||
AiPlayerbot.PremadeSpecName.1.5 = pvp prot
|
||||
AiPlayerbot.PremadeSpecLink.1.5.80 = 32003200233-325000131504012050122511351
|
||||
|
||||
|
||||
# Paladin
|
||||
AiPlayerbot.PremadeSpecName.2.1 = Ret Pvp
|
||||
AiPlayerbot.PremadeSpecProb.2.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.2.1.80 = 05002-053201-05222150203331322133201331
|
||||
|
||||
AiPlayerbot.PremadeSpecName.2.2 = Prot Pvp
|
||||
AiPlayerbot.PremadeSpecProb.2.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.2.2.80 = -15320130223122321333312321052300500002
|
||||
|
||||
AiPlayerbot.PremadeSpecName.2.3 = Holy Pvp
|
||||
AiPlayerbot.PremadeSpecProb.2.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.2.3.80 = 503521503000131501034142215032013122
|
||||
|
||||
AiPlayerbot.PremadeSpecName.2.4 = Ret Pve
|
||||
AiPlayerbot.PremadeSpecProb.2.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.2.4.80 = 050501-05-05232051203331302133231331
|
||||
|
||||
AiPlayerbot.PremadeSpecName.2.5 = Prot Pve
|
||||
AiPlayerbot.PremadeSpecProb.2.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.2.5.80 = -050051352031323113333123215023005
|
||||
|
||||
AiPlayerbot.PremadeSpecName.2.6 = Holy Pve
|
||||
AiPlayerbot.PremadeSpecProb.2.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.2.6.80 = 503501510200130531005152215-503205
|
||||
|
||||
|
||||
# Hunter
|
||||
AiPlayerbot.PremadeSpecName.3.1 = BM Pvp
|
||||
AiPlayerbot.PremadeSpecProb.3.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.3.1.80 = 05203001505212233100531351005305131
|
||||
|
||||
AiPlayerbot.PremadeSpecName.3.2 = MM Pvp
|
||||
AiPlayerbot.PremadeSpecProb.3.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.3.2.80 = 052-025305101030213233115031051530020201
|
||||
|
||||
AiPlayerbot.PremadeSpecName.3.3 = Surv Pvp
|
||||
AiPlayerbot.PremadeSpecProb.3.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.3.3.80 = -005305101-3300132510233330532135001031
|
||||
|
||||
AiPlayerbot.PremadeSpecName.3.4 = BM Pve
|
||||
AiPlayerbot.PremadeSpecProb.3.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.3.4.80 = 51200201505112253100531351015305021
|
||||
|
||||
AiPlayerbot.PremadeSpecName.3.5 = MM Pve
|
||||
AiPlayerbot.PremadeSpecProb.3.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.3.5.80 = 502-0353051012300132331350313515000002
|
||||
|
||||
AiPlayerbot.PremadeSpecName.3.6 = Surv Pve
|
||||
AiPlayerbot.PremadeSpecProb.3.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.3.6.80 = -0053041-5000032500033330523134321331
|
||||
|
||||
|
||||
# Rogue
|
||||
AiPlayerbot.PremadeSpecName.4.1 = Assassination Pvp
|
||||
AiPlayerbot.PremadeSpecProb.4.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.4.1.80 = 005303103342102522103031000004-532023203000012
|
||||
|
||||
AiPlayerbot.PremadeSpecName.4.2 = Combat Pvp
|
||||
AiPlayerbot.PremadeSpecProb.4.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.4.2.80 = 005-3250302102205015023122021251230023013
|
||||
|
||||
AiPlayerbot.PremadeSpecName.4.3 = Subtlety Pvp
|
||||
AiPlayerbot.PremadeSpecProb.4.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.4.3.80 = 0053031-1-5020232033322121350105131251
|
||||
|
||||
AiPlayerbot.PremadeSpecName.4.4 = Assassination Pve
|
||||
AiPlayerbot.PremadeSpecProb.4.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.4.4.80 = 005323005350100520103331051005005003-502
|
||||
|
||||
AiPlayerbot.PremadeSpecName.4.5 = Combat Pve
|
||||
AiPlayerbot.PremadeSpecProb.4.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.4.5.80 = 30530000522-0252051000035015223100501251
|
||||
|
||||
AiPlayerbot.PremadeSpecName.4.6 = Subtlety Pve
|
||||
AiPlayerbot.PremadeSpecProb.4.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.4.6.80 = 0053231-2-5120222030321121050135231251
|
||||
|
||||
|
||||
# Priest
|
||||
AiPlayerbot.PremadeSpecName.5.1 = Shadow PvE
|
||||
AiPlayerbot.PremadeSpecProb.5.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.5.1.80 = 0503203--325023051223010323152301351
|
||||
|
||||
AiPlayerbot.PremadeSpecName.5.2 = Shadow PvP
|
||||
AiPlayerbot.PremadeSpecProb.5.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.5.2.80 = 502320013--005023251023112123152311351
|
||||
|
||||
AiPlayerbot.PremadeSpecName.5.3 = Disc PvE
|
||||
AiPlayerbot.PremadeSpecProb.5.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.5.3.80 = 050320313030051233132323125100550103
|
||||
|
||||
AiPlayerbot.PremadeSpecName.5.4 = Disc PvE renew build
|
||||
AiPlayerbot.PremadeSpecProb.5.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.5.4.80 = 050320313030051233132323125103530003
|
||||
|
||||
AiPlayerbot.PremadeSpecName.5.5 = Holy PvE
|
||||
AiPlayerbot.PremadeSpecProb.5.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.5.5.80 = 05032031-235050032302152530000331351
|
||||
|
||||
AiPlayerbot.PremadeSpecName.5.6 = Holy PvP
|
||||
AiPlayerbot.PremadeSpecProb.5.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.5.6.80 = 500320313030251233102323115120350123
|
||||
|
||||
|
||||
# Death Knight
|
||||
AiPlayerbot.PremadeSpecName.6.1 = Blood Pvp
|
||||
AiPlayerbot.PremadeSpecProb.6.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.6.1.80 = 20450215333033132002231313513232
|
||||
|
||||
AiPlayerbot.PremadeSpecName.6.2 = Unholy Pvp
|
||||
AiPlayerbot.PremadeSpecProb.6.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.6.2.80 = -320050410002-2301323301002152233101203103151
|
||||
|
||||
AiPlayerbot.PremadeSpecName.6.3 = Frost Pvp
|
||||
AiPlayerbot.PremadeSpecProb.6.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.6.3.80 = 0325101303-32025351052203012001033101341
|
||||
|
||||
AiPlayerbot.PremadeSpecName.6.4 = Blood Pve
|
||||
AiPlayerbot.PremadeSpecProb.6.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.6.4.80 = 0355220530003313221020131351305-0052
|
||||
|
||||
AiPlayerbot.PremadeSpecName.6.5 = Unholy Pve
|
||||
AiPlayerbot.PremadeSpecProb.6.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.6.5.80 = 23050202--2302003350032152003150003133151
|
||||
|
||||
AiPlayerbot.PremadeSpecName.6.6 = Frost Pve
|
||||
AiPlayerbot.PremadeSpecProb.6.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.6.6.80 = 03-32002350352203012300033101351230200305
|
||||
|
||||
|
||||
# Shaman
|
||||
AiPlayerbot.PremadeSpecName.7.1 = Enh Pvp
|
||||
AiPlayerbot.PremadeSpecProb.7.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.7.1.80 = 05032005-02305233105001333201131231251
|
||||
|
||||
AiPlayerbot.PremadeSpecName.7.2 = Ele Pvp
|
||||
AiPlayerbot.PremadeSpecProb.7.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.7.2.80 = 0533001503213051322331351-024252001
|
||||
|
||||
AiPlayerbot.PremadeSpecName.7.3 = Resto Pvp
|
||||
AiPlayerbot.PremadeSpecProb.7.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.7.3.80 = -023202301-50032331330313551120321251
|
||||
|
||||
AiPlayerbot.PremadeSpecName.7.4 = Enh Pve
|
||||
AiPlayerbot.PremadeSpecProb.7.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.7.4.80 = 053030052-30205033005021333031131131051
|
||||
|
||||
AiPlayerbot.PremadeSpecName.7.5 = Ele Pve
|
||||
AiPlayerbot.PremadeSpecProb.7.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.7.5.80 = 3530001523213351322301351005050031
|
||||
|
||||
AiPlayerbot.PremadeSpecName.7.6 = Resto Pve
|
||||
AiPlayerbot.PremadeSpecProb.7.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.7.6.80 = -00505031-50005331335310501022331251
|
||||
|
||||
|
||||
# Mage
|
||||
AiPlayerbot.PremadeSpecName.8.1 = Arcane Pvp
|
||||
AiPlayerbot.PremadeSpecProb.8.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.8.1.80 = 205025220122032103323102515321--203023001
|
||||
|
||||
AiPlayerbot.PremadeSpecName.8.2 = Fire Pvp
|
||||
AiPlayerbot.PremadeSpecProb.8.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.8.2.80 = 230320220122-2305022310220031243122201351
|
||||
|
||||
AiPlayerbot.PremadeSpecName.8.3 = Frost Pvp
|
||||
AiPlayerbot.PremadeSpecProb.8.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.8.3.80 = 23002322010203--3533103310203100232102231151
|
||||
|
||||
AiPlayerbot.PremadeSpecName.8.4 = Arcane Pve
|
||||
AiPlayerbot.PremadeSpecProb.8.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.8.4.80 = 23500503010023015032310250532103-203023001
|
||||
|
||||
AiPlayerbot.PremadeSpecName.8.5 = Fire Pve
|
||||
AiPlayerbot.PremadeSpecProb.8.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.8.5.80 = 23000503310003-0055030012303330053120300351
|
||||
|
||||
AiPlayerbot.PremadeSpecName.8.6 = Frost Arcane Pve
|
||||
AiPlayerbot.PremadeSpecProb.8.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.8.6.80 = 23500503110023015032310250532003-203023001
|
||||
|
||||
|
||||
# Warlock
|
||||
AiPlayerbot.PremadeSpecName.9.1 = Affli CoE Pvp
|
||||
AiPlayerbot.PremadeSpecProb.9.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.9.1.80 = 03500022312233110535023011510032203011302
|
||||
|
||||
AiPlayerbot.PremadeSpecName.9.2 = Affli CoA Pvp
|
||||
AiPlayerbot.PremadeSpecProb.9.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.9.2.80 = 23500022312231110535023011510032203011302
|
||||
|
||||
AiPlayerbot.PremadeSpecName.9.3 = Destro Pvp
|
||||
AiPlayerbot.PremadeSpecProb.9.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.9.3.80 = 03-0032203011302-05230015220331351005031051
|
||||
|
||||
AiPlayerbot.PremadeSpecName.9.4 = Demo Pve
|
||||
AiPlayerbot.PremadeSpecProb.9.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.9.4.80 = -00320330113520253013523134155000005
|
||||
|
||||
AiPlayerbot.PremadeSpecName.9.5 = Affli Pve
|
||||
AiPlayerbot.PremadeSpecProb.9.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.9.5.80 = 2350002030023510253500331151--550000051
|
||||
|
||||
AiPlayerbot.PremadeSpecName.9.6 = Destro Pve
|
||||
AiPlayerbot.PremadeSpecProb.9.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.9.6.80 = -03310030003-05203205210331051335230351
|
||||
|
||||
AiPlayerbot.PremadeSpecName.9.7 = Demo Pve
|
||||
AiPlayerbot.PremadeSpecProb.9.7 = 100
|
||||
AiPlayerbot.PremadeSpecLink.9.7.80 = -00320330113520253013523134155-5
|
||||
|
||||
|
||||
# Druid
|
||||
AiPlayerbot.PremadeSpecName.11.1 = Feral shred Pvp
|
||||
AiPlayerbot.PremadeSpecProb.11.1 = 100
|
||||
AiPlayerbot.PremadeSpecLink.11.1.80 = -55020213232021205312301331051100550101
|
||||
|
||||
AiPlayerbot.PremadeSpecName.11.2 = Feral 1v1 Pvp
|
||||
AiPlayerbot.PremadeSpecProb.11.2 = 100
|
||||
AiPlayerbot.PremadeSpecLink.11.2.80 = -53020213032021205312303331351100550001
|
||||
|
||||
AiPlayerbot.PremadeSpecName.11.3 = Balance Pvp
|
||||
AiPlayerbot.PremadeSpecProb.11.3 = 100
|
||||
AiPlayerbot.PremadeSpecLink.11.3.80 = 5022203125331003213035311231--230033012
|
||||
|
||||
AiPlayerbot.PremadeSpecName.11.4 = Resto Pvp
|
||||
AiPlayerbot.PremadeSpecProb.11.4 = 100
|
||||
AiPlayerbot.PremadeSpecLink.11.4.80 = 5532000120321--230033312031502221350013200
|
||||
|
||||
AiPlayerbot.PremadeSpecName.11.5 = Feral dps Pve
|
||||
AiPlayerbot.PremadeSpecProb.11.5 = 100
|
||||
AiPlayerbot.PremadeSpecLink.11.5.80 = -550202132322010053120030312511005503012
|
||||
|
||||
AiPlayerbot.PremadeSpecName.11.6 = Feral Tank Pve
|
||||
AiPlayerbot.PremadeSpecProb.11.6 = 100
|
||||
AiPlayerbot.PremadeSpecLink.11.6.80 = -50123213032211035312030331351120350001
|
||||
|
||||
AiPlayerbot.PremadeSpecName.11.7 = Balance Pve
|
||||
AiPlayerbot.PremadeSpecProb.11.7 = 100
|
||||
AiPlayerbot.PremadeSpecLink.11.7.80 = 5012203125331103213305301231--205003212
|
||||
|
||||
AiPlayerbot.PremadeSpecName.11.8 = Restro Pve
|
||||
AiPlayerbot.PremadeSpecProb.11.8 = 100
|
||||
AiPlayerbot.PremadeSpecLink.11.8.80 = 05320001--230033312031512531153313051
|
||||
|
||||
|
||||
# Prefix for bot chat commands (e.g. follow, stay)
|
||||
AiPlayerbot.CommandPrefix = ""
|
||||
|
||||
# Separator for bot chat commands
|
||||
AiPlayerbot.CommandSeparator = "\\\\"
|
||||
|
||||
# Max AI iterations per tick
|
||||
AiPlayerbot.IterationsPerTick = 100
|
||||
|
||||
# Allow/deny bots from your guild
|
||||
AiPlayerbot.AllowGuildBots = 1
|
||||
|
||||
# Delay between two short-time spells cast
|
||||
AiPlayerbot.GlobalCooldown = 1500
|
||||
|
||||
# Max wait time when moving
|
||||
AiPlayerbot.MaxWaitForMove = 5000
|
||||
|
||||
# Action expiration time
|
||||
AiPlayerbot.ExpireActionTime = 5000
|
||||
|
||||
# Max dispel auras duration
|
||||
AiPlayerbot.DispelAuraDuration = 7000
|
||||
|
||||
# Delay between two bot actions
|
||||
AiPlayerbot.ReactDelay = 500
|
||||
|
||||
# Inactivity delay
|
||||
AiPlayerbot.PassiveDelay = 10000
|
||||
|
||||
# Minimum delay between repeating actions (chat messages, emotes etc)
|
||||
AiPlayerbot.RepeatDelay = 5000
|
||||
|
||||
# Delay timers
|
||||
AiPlayerbot.ErrorDelay = 5000
|
||||
AiPlayerbot.RpgDelay = 10000
|
||||
AiPlayerbot.SitDelay = 30000
|
||||
AiPlayerbot.ReturnDelay = 7000
|
||||
AiPlayerbot.LootDelay = 1000
|
||||
|
||||
# Distances
|
||||
AiPlayerbot.FarDistance = 20.0
|
||||
AiPlayerbot.SightDistance = 75.0
|
||||
AiPlayerbot.SpellDistance = 22.0
|
||||
AiPlayerbot.ShootDistance = 25.0
|
||||
AiPlayerbot.ReactDistance = 150.0
|
||||
AiPlayerbot.GrindDistance = 75.0
|
||||
AiPlayerbot.HealDistance = 20.0
|
||||
AiPlayerbot.LootDistance = 15.0
|
||||
AiPlayerbot.FleeDistance = 7.5
|
||||
AiPlayerbot.TooCloseDistance = 5.0
|
||||
AiPlayerbot.MeleeDistance = 1.5
|
||||
AiPlayerbot.FollowDistance = 1.5
|
||||
AiPlayerbot.WhisperDistance = 6000.0
|
||||
AiPlayerbot.ContactDistance = 0.5
|
||||
AiPlayerbot.AoeRadius = 5
|
||||
AiPlayerbot.RpgDistance = 200
|
||||
AiPlayerbot.AggroDistance = 22
|
||||
|
||||
# Bot can flee for enemy
|
||||
AiPlayerbot.FleeingEnabled = 1
|
||||
|
||||
# Health/Mana levels
|
||||
AiPlayerbot.CriticalHealth = 20
|
||||
AiPlayerbot.LowHealth = 45
|
||||
AiPlayerbot.MediumHealth = 65
|
||||
AiPlayerbot.AlmostFullHealth = 85
|
||||
AiPlayerbot.LowMana = 15
|
||||
AiPlayerbot.MediumMana = 40
|
||||
|
||||
# Random bot default strategies (applied after defaults)
|
||||
AiPlayerbot.RandomBotCombatStrategies = "-threat"
|
||||
AiPlayerbot.RandomBotNonCombatStrategies = ""
|
||||
AiPlayerbot.CombatStrategies = "+custom::say"
|
||||
AiPlayerbot.NonCombatStrategies = "+custom::say,+return"
|
||||
|
||||
# How often tasks are changed
|
||||
AiPlayerbot.MinGuildTaskChangeTime = 172800
|
||||
AiPlayerbot.MaxGuildTaskChangeTime = 432000
|
||||
|
||||
# Mail spam interval
|
||||
AiPlayerbot.MinGuildTaskAdvertisementTime = 300
|
||||
AiPlayerbot.MaxGuildTaskAdvertisementTime = 43200
|
||||
|
||||
# Delay before reward is sent
|
||||
AiPlayerbot.MinGuildTaskRewardTime = 300
|
||||
AiPlayerbot.MaxGuildTaskRewardTime = 3600
|
||||
|
||||
# Cleanup of guild tasks interval
|
||||
AiPlayerbot.GuildTaskAdvertCleanupTime = 300
|
||||
|
||||
# Specify max distance between victim and bot when creating guild kill task
|
||||
AiPlayerbot.GuildTaskKillTaskDistance = 2000
|
||||
|
||||
# Distance margin for facade calculations
|
||||
AiPlayerbot.TargetPosRecalcDistance = 0.1
|
||||
|
||||
# Maps where bots can be teleported to
|
||||
AiPlayerbot.RandomBotMaps = 0,1,530,571
|
||||
|
||||
# Quest items to leave (do not destroy)
|
||||
AiPlayerbot.RandomBotQuestItems = "6948,5175,5176,5177,5178,16309,12382,13704,11000""
|
||||
|
||||
# PvP Restricted Zones (bots don't pvp)
|
||||
AiPlayerbot.PvpProhibitedZoneIds = "2255,656,2361,2362,2363,976,35,2268,3425,392,541,1446,3828,3712,3738,3565,3539,3623,4152,3988,4658,4284,4418,4436,4275,4323""
|
||||
|
||||
# Spells every random bot will learn on randomize (54197 - cold weather flying)
|
||||
AiPlayerbot.RandomBotSpellIds = "1""
|
||||
|
||||
# Level diff between random bots and nearby creatures for random teleports
|
||||
AiPlayerbot.RandomBotTeleLevel = 5
|
||||
|
||||
# ID of spell to open lootable chests
|
||||
AiPlayerbot.OpenGoSpell = 6477
|
||||
|
||||
# Intervals
|
||||
AiPlayerbot.RandomBotUpdateInterval = 60
|
||||
AiPlayerbot.RandomBotCountChangeMinInterval = 1800
|
||||
AiPlayerbot.RandomBotCountChangeMaxInterval = 7200
|
||||
AiPlayerbot.MinRandomBotInWorldTime = 7200
|
||||
AiPlayerbot.MaxRandomBotInWorldTime = 43200
|
||||
AiPlayerbot.MinRandomBotRandomizeTime = 7200
|
||||
AiPlayerbot.MaxRandomRandomizeTime = 1209600
|
||||
AiPlayerbot.RandomBotsPerInterval = 60
|
||||
AiPlayerbot.MinRandomBotsPriceChangeInterval = 7200
|
||||
AiPlayerbot.MaxRandomBotsPriceChangeInterval = 172800
|
||||
AiPlayerbot.MinRandomBotChangeStrategyTime = 1800
|
||||
AiPlayerbot.MaxRandomBotChangeStrategyTime = 7200
|
||||
AiPlayerbot.MinRandomBotReviveTime = 60
|
||||
AiPlayerbot.MaxRandomBotReviveTime = 300
|
||||
|
||||
# How far random bots are teleported after death
|
||||
AiPlayerbot.RandomBotTeleportDistance = 100
|
||||
|
||||
# Debug switches
|
||||
AiPlayerbot.SpellDump = 0
|
||||
AiPlayerbot.LogInGroupOnly = 1
|
||||
AiPlayerbot.LogValuesPerTick = 0
|
||||
AiPlayerbot.RandomChangeMultiplier = 1
|
||||
|
||||
# Command server port, 0 - disabled
|
||||
AiPlayerbot.CommandServerPort = 8888
|
||||
|
||||
# Enables/Disables performance monitor
|
||||
AiPlayerbot.PerfMonEnabled = 0
|
||||
|
||||
# Allow bots to be summoned near innkeepers
|
||||
AiPlayerbot.SummonAtInnkeepersEnabled = 1
|
||||
|
||||
# Custom config to allow logfiles to be created.
|
||||
# Example: AiPlayerbot.AllowedLogFiles = travelNodes.csv,travelPaths.csv,TravelNodeStore.h,bot_movement.csv,bot_location.csv
|
||||
AiPlayerbot.AllowedLogFiles = ""
|
||||
|
||||
# Applies a permanent buff to all bots.
|
||||
# WorldBuff.Faction.Class.MinLevel.MaxLevel
|
||||
|
||||
# Added following config
|
||||
# Selfbot permission level (0 = disabled, 1 = gm only (default), 2 = all players, 3 = activate on login) # AiPlayerbot.SelfBotLevel = 1
|
||||
AiPlayerbot.SelfBotLevel = 1
|
||||
|
||||
# Enables/Disables bot cheating
|
||||
AiPlayerbot.BotCheats = "taxi"
|
||||
|
||||
# Enables/Disables password to bot account
|
||||
AiPlayerbot.RandomBotRandomPassword = 1
|
||||
|
||||
##################################################################################
|
||||
# #
|
||||
# Database Stuff #
|
||||
# #
|
||||
##################################################################################
|
||||
|
||||
#
|
||||
# PlayerbotsDatabaseInfo
|
||||
# Description: Database connection settings for the playerbots server.
|
||||
# Example: "hostname;port;username;password;database"
|
||||
# ".;somenumber;username;password;database" - (Use named pipes on Windows
|
||||
# "enable-named-pipe" to [mysqld]
|
||||
# section my.ini)
|
||||
# ".;/path/to/unix_socket;username;password;database" - (use Unix sockets on
|
||||
# Unix/Linux)
|
||||
# Default: "127.0.0.1;3306;acore;acore;acore_playerbots" - (PlayerbotDatabaseInfo)
|
||||
|
||||
PlayerbotsDatabaseInfo = "127.0.0.1;3306;acore;acore;acore_playerbots"
|
||||
|
||||
#
|
||||
# PlayerbotsDatabase.WorkerThreads
|
||||
# Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL
|
||||
# statements. Each worker thread is mirrored with its own connection to the
|
||||
# MySQL server and their own thread on the MySQL server.
|
||||
# Default: 1 - (PlayerbotsDatabase.WorkerThreads)
|
||||
|
||||
PlayerbotsDatabase.WorkerThreads = 1
|
||||
|
||||
#
|
||||
# PlayerbotsDatabase.SynchThreads
|
||||
# Description: The amount of MySQL connections spawned to handle.
|
||||
# Default: 1 - (PlayerbotDatabase.WorkerThreads)
|
||||
|
||||
PlayerbotsDatabase.SynchThreads = 1
|
||||
|
||||
# Playerbot.Updates.EnableDatabases
|
||||
# Description: Determined if updates system work with playerbot database.
|
||||
#
|
||||
# Default: 1 - (Enabled)
|
||||
# 0 - (Disabled)
|
||||
|
||||
Playerbots.Updates.EnableDatabases = 1
|
||||
#
|
||||
|
||||
##################################################################################
|
||||
# #
|
||||
# Logging Stuff #
|
||||
# #
|
||||
##################################################################################
|
||||
|
||||
Appender.Playerbots=2,5,0,Playerbots.log,w
|
||||
Logger.playerbots=5,Playerbots
|
||||
@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
## GETS THE CURRENT MODULE ROOT DIRECTORY
|
||||
MOD_SKELETON_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/" && pwd )"
|
||||
MOD_PLAYERBOTS_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/" && pwd )"
|
||||
|
||||
source $MOD_SKELETON_ROOT"/conf/conf.sh.dist"
|
||||
source $MOD_PLAYERBOTS_ROOT"/conf/conf.sh.dist"
|
||||
|
||||
if [ -f $MOD_SKELETON_ROOT"/conf/conf.sh" ]; then
|
||||
source $MOD_SKELETON_ROOT"/conf/conf.sh"
|
||||
if [ -f $MOD_PLAYERBOTS_ROOT"/conf/conf.sh" ]; then
|
||||
source $MOD_PLAYERBOTS_ROOT"/conf/conf.sh"
|
||||
fi
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
-- Put only sql data in this file (insert, update, replace into, delete etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
-- If no data, just delete this file.
|
||||
@ -1,3 +0,0 @@
|
||||
-- Put only sql data in this file (insert, update, replace into, delete etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
-- If no data, just delete this file.
|
||||
@ -1,2 +0,0 @@
|
||||
-- Put only sql structure in this file (create table if exists, delete table, alter table etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
@ -1,3 +0,0 @@
|
||||
-- Put only sql data in this file (insert, update, replace into, delete etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
-- If no data, just delete this file.
|
||||
@ -1,3 +0,0 @@
|
||||
-- Put only sql data in this file (insert, update, replace into, delete etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
-- If no data, just delete this file.
|
||||
@ -1,2 +0,0 @@
|
||||
-- Put only sql structure in this file (create table if exists, delete table, alter table etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
626
sql/characters/playerbots_arena_team_names.sql
Normal file
626
sql/characters/playerbots_arena_team_names.sql
Normal file
@ -0,0 +1,626 @@
|
||||
DROP TABLE IF EXISTS `playerbot_arena_team_names`;
|
||||
CREATE TABLE `playerbot_arena_team_names` (
|
||||
`name_id` mediumint(8) NOT NULL AUTO_INCREMENT UNIQUE,
|
||||
`name` varchar(24) NOT NULL UNIQUE,
|
||||
`type` TINYINT(3) NOT NULL,
|
||||
PRIMARY KEY (`name_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Playerbot arena team names';
|
||||
|
||||
|
||||
DELETE FROM `playerbot_arena_team_names`;
|
||||
INSERT INTO `playerbot_arena_team_names` (`name_id`,`name`, `type`) VALUES
|
||||
(NULL, 'out of coverage',2),
|
||||
(NULL, 'Dead or Alive',2),
|
||||
(NULL, 'Noßrain',2),
|
||||
(NULL, 'Истребление',2),
|
||||
(NULL, 'Pieces',2),
|
||||
(NULL, 'ßurst',2),
|
||||
(NULL, 'hey im actually not mvp',2),
|
||||
(NULL, 'Group Therapy',2),
|
||||
(NULL, 'Outland Elite',2),
|
||||
(NULL, 'Исчадье Тьмы',2),
|
||||
(NULL, 'Dun Spetsnaz',2),
|
||||
(NULL, 'ЧСВ РБГ',2),
|
||||
(NULL, 'ShameReborn',2),
|
||||
(NULL, 'TEAM VÉSUVE',2),
|
||||
(NULL, 'Battle for Apes',2),
|
||||
(NULL, 'Can You Feel It',2),
|
||||
(NULL, 'Zero to Hero',2),
|
||||
(NULL, 'Link Curve',2),
|
||||
(NULL, 'Project',2),
|
||||
(NULL, 'Security',2),
|
||||
(NULL, 'Skill Loading',2),
|
||||
(NULL, 'Cya Bro',2),
|
||||
(NULL, 'out of rage',2),
|
||||
(NULL, 'Improve',2),
|
||||
(NULL, 'WORST GENERATION',2),
|
||||
(NULL, 'KFC Fitness Club',2),
|
||||
(NULL, 'unlucky',2),
|
||||
(NULL, 'OldStyle',2),
|
||||
(NULL, 'Walkthrough',2),
|
||||
(NULL, 'Лё Резистанс',2),
|
||||
(NULL, 'League of Gladiators',2),
|
||||
(NULL, 'Practice',2),
|
||||
(NULL, 'Rofl So Bad',2),
|
||||
(NULL, 'Synergy',2),
|
||||
(NULL, 'Que la famille',2),
|
||||
(NULL, 'Древние баги',2),
|
||||
(NULL, 'Echo',2),
|
||||
(NULL, 'KARMA',2),
|
||||
(NULL, 'Exodus',2),
|
||||
(NULL, 'Felsenfest',2),
|
||||
(NULL, 'LifeIsPain',2),
|
||||
(NULL, 'The Eternal',2),
|
||||
(NULL, 'Raid Trap',2),
|
||||
(NULL, 'The Dambusters',2),
|
||||
(NULL, 'Станция Токсичных',2),
|
||||
(NULL, 'Cykla Blöt',2),
|
||||
(NULL, 'Ethics',2),
|
||||
(NULL, 'Human ZOO',2),
|
||||
(NULL, 'Mausoleum',2),
|
||||
(NULL, 'Nashwan GoDs',2),
|
||||
(NULL, 'PASTIS PETANQUE ARENE',2),
|
||||
(NULL, 'tweet holinka',2),
|
||||
(NULL, 'Пять Бутылок Водки',2),
|
||||
(NULL, 'РЕТРИК РУКИ ПОЛТОРАШКИ',2),
|
||||
(NULL, 'У беляша',2),
|
||||
(NULL, 'A M K',2),
|
||||
(NULL, 'Against The WorId',2),
|
||||
(NULL, 'Dilemma',2),
|
||||
(NULL, 'Efficiency',2),
|
||||
(NULL, 'Halcyon',2),
|
||||
(NULL, 'I SoliD I',2),
|
||||
(NULL, 'Impact',2),
|
||||
(NULL, 'Melk Trupp',2),
|
||||
(NULL, 'Tatortreiniger',2),
|
||||
(NULL, 'TG Gaming',2),
|
||||
(NULL, 'Without a Trace',2),
|
||||
(NULL, 'Fysikbasserne',3),
|
||||
(NULL, 'Helion',3),
|
||||
(NULL, 'Twix',3),
|
||||
(NULL, 'Unethical',3),
|
||||
(NULL, 'Advance',3),
|
||||
(NULL, 'Arctic Avengers',3),
|
||||
(NULL, 'E V O L U T I O N',3),
|
||||
(NULL, 'FOR THE ALLÎANCE',3),
|
||||
(NULL, 'Insanity',3),
|
||||
(NULL, 'Integrity',3),
|
||||
(NULL, 'Oderant',3),
|
||||
(NULL, 'P G',3),
|
||||
(NULL, 'PMA',3),
|
||||
(NULL, 'Revoke',3),
|
||||
(NULL, 'stay hydrated',3),
|
||||
(NULL, 'Sum optime',3),
|
||||
(NULL, 'Team Sweden',3),
|
||||
(NULL, 'Two Ghouls One Cup',3),
|
||||
(NULL, 'Vous ne passerez pas',3),
|
||||
(NULL, 'Øgma Tuatha',3),
|
||||
(NULL, 'Адская Орда',3),
|
||||
(NULL, 'Селфлесс',3),
|
||||
(NULL, 'Чёрный Лотос',3),
|
||||
(NULL, 'Crown',3),
|
||||
(NULL, 'Distopia',3),
|
||||
(NULL, 'FatSharkYes',3),
|
||||
(NULL, 'Feed',3),
|
||||
(NULL, 'Myst',3),
|
||||
(NULL, 'Slack',3),
|
||||
(NULL, 'Team Fight',3),
|
||||
(NULL, 'The Haunted',3),
|
||||
(NULL, 'Unicornz',3),
|
||||
(NULL, 'В КОЛХОЗ ЗА ПЕТУХАМИ',3),
|
||||
(NULL, 'THE MOVE',3),
|
||||
(NULL, 'SSEN',3),
|
||||
(NULL, 'Mørdor',3),
|
||||
(NULL, 'one lesson per day',3),
|
||||
(NULL, 'ddosed',3),
|
||||
(NULL, 'hey im mvp',3),
|
||||
(NULL, 'Still On Sargeras',3),
|
||||
(NULL, 'ddosedx',3),
|
||||
(NULL, 'Cyber Athletes',3),
|
||||
(NULL, 'Gnomeland Security',3),
|
||||
(NULL, 'ad hoc',3),
|
||||
(NULL, 'slash spit',3),
|
||||
(NULL, 'Suppy',3),
|
||||
(NULL, 'Crimson Dragon',3),
|
||||
(NULL, 'The Syndicate',3),
|
||||
(NULL, 'Blur',3),
|
||||
(NULL, 'tEh mOve',3),
|
||||
(NULL, 'Cherry Pink',3),
|
||||
(NULL, 'Honestly',3),
|
||||
(NULL, 'Disney World',3),
|
||||
(NULL, 'poptart corndoG',3),
|
||||
(NULL, 'See Again Solitary',3),
|
||||
(NULL, 'Infinity',3),
|
||||
(NULL, 'BIG DAM',3),
|
||||
(NULL, 'Ethical',3),
|
||||
(NULL, 'BloodBoùnd',3),
|
||||
(NULL, 'Show Me How',3),
|
||||
(NULL, 'dog squad',3),
|
||||
(NULL, 'Zandalari Bobsled Team',3),
|
||||
(NULL, 'Goons Goonies',3),
|
||||
(NULL, 'Legacy of the Alliance',3),
|
||||
(NULL, 'Spiral Out',3),
|
||||
(NULL, 'Melt',3),
|
||||
(NULL, 'Last Attempt',3),
|
||||
(NULL, 'Nolifer',3),
|
||||
(NULL, 'RBG Hero',5),
|
||||
(NULL, 'Medium',5),
|
||||
(NULL, 'Nascent',5),
|
||||
(NULL, 'M E R C I L E S S',5),
|
||||
(NULL, 'Team Thougs',5),
|
||||
(NULL, 'Verdict',5),
|
||||
(NULL, 'CMG',5),
|
||||
(NULL, 'Dishonorable Kill',5),
|
||||
(NULL, 'Knights Who Say Yee',5),
|
||||
(NULL, 'Restricted',5),
|
||||
(NULL, 'Vile',5),
|
||||
(NULL, 'Nemesis',5),
|
||||
(NULL, 'Oasis',5),
|
||||
(NULL, 'The Depraved',5),
|
||||
(NULL, 'didnt ask',5),
|
||||
(NULL, 'Epic Gamers',5),
|
||||
(NULL, 'Essence',5),
|
||||
(NULL, 'i love slicedbaka',5),
|
||||
(NULL, 'Lights Oath',5),
|
||||
(NULL, 'M Y T H I C C',5),
|
||||
(NULL, 'Major Pain',5),
|
||||
(NULL, 'Dads Against Vaping',5),
|
||||
(NULL, 'No Skill',5),
|
||||
(NULL, 'The Degenerates',5),
|
||||
(NULL,'Boralus Yacht Club',5),
|
||||
(NULL, 'Censored',5),
|
||||
(NULL, 'Defenestrate',5),
|
||||
(NULL, 'HATE DIVISION',5),
|
||||
(NULL, 'hi',5),
|
||||
(NULL, 'Ironsworn Regiment',5),
|
||||
(NULL, 'is kinda like god',5),
|
||||
(NULL, 'Temerity',5),
|
||||
(NULL, 'The Pantheon NB',5),
|
||||
(NULL, 'Vision',5),
|
||||
(NULL, 'Baddies',5),
|
||||
(NULL, 'Complexity Limit',5),
|
||||
(NULL, 'Dark Clan of Fenris',5),
|
||||
(NULL, 'Elite Horde',5),
|
||||
(NULL, 'Makin a Bagel',5),
|
||||
(NULL, 'Nimue',5),
|
||||
(NULL, 'Ran Thru',5),
|
||||
(NULL, 'Sin',5),
|
||||
(NULL, 'VØDKA SØCIETY',5),
|
||||
(NULL, 'Wizards and Monkeys',5),
|
||||
(NULL, 'Is cute AF',5),
|
||||
(NULL, 'Reckless Ambition',5),
|
||||
(NULL, 'Solidarity Gaming',5),
|
||||
(NULL, 'Spike Flail',5),
|
||||
(NULL, 'Vexation',5),
|
||||
(NULL, 'Hungry Wolves',5),
|
||||
(NULL, 'Peel Team Six',5),
|
||||
(NULL, 'Polaris',5),
|
||||
(NULL, 'rest easy criter',5),
|
||||
(NULL, 'Scripted',5),
|
||||
(NULL, 'TAG',5),
|
||||
(NULL, 'toXique',5),
|
||||
(NULL, 'who are you talkin to',5),
|
||||
(NULL, 'CRvillains',5),
|
||||
(NULL, 'Decapodian',5),
|
||||
(NULL, 'Fierce',5),
|
||||
(NULL, 'Glad to see you',5),
|
||||
(NULL, 'Impression',5),
|
||||
(NULL, 'Nerd Rage',5),
|
||||
(NULL, 'The Art of War',5),
|
||||
(NULL, 'Wisdom',5),
|
||||
(NULL, 'Against',2),
|
||||
(NULL, 'Dot Run Profit',2),
|
||||
(NULL, 'Fluffy Doods of Doom',2),
|
||||
(NULL, 'Dot Pillar Profit',2),
|
||||
(NULL, 'Team GG',2),
|
||||
(NULL, 'Paizuri',2),
|
||||
(NULL, 'Plz i need',2),
|
||||
(NULL, 'shadow resist last week',2),
|
||||
(NULL, 'shen diao xia lv',2),
|
||||
(NULL, 'Speechless',2),
|
||||
(NULL, 'Pandaninja Team',2),
|
||||
(NULL, 'Kettes Ninja',2),
|
||||
(NULL, 'PROXIMO',2),
|
||||
(NULL, 'System Down',2),
|
||||
(NULL, 'Hakuna matata',2),
|
||||
(NULL, 'Freshly Baked',2),
|
||||
(NULL, 'Abandon All Hope',2),
|
||||
(NULL, 'GIEF UR POINTS PLX',2),
|
||||
(NULL, 'Schobbejakken',2),
|
||||
(NULL, 'Our team got deleted',2),
|
||||
(NULL, 'Chocolate fingers',2),
|
||||
(NULL, 'Wet Dreams',2),
|
||||
(NULL, 'Vissnar er skit',2),
|
||||
(NULL, 'Holla Fo Da Top Dolla',2),
|
||||
(NULL, 'WTS Taran Icebreaker',2),
|
||||
(NULL, 'Copenhagen eSports',2),
|
||||
(NULL, 'SWE HORDE',2),
|
||||
(NULL, 'I Touch Myself',2),
|
||||
(NULL, 'Kines Jaegarna',2),
|
||||
(NULL, 'Greek SOUVLAKI',2),
|
||||
(NULL, 'Halinallet',2),
|
||||
(NULL, 'TELLME WHEN THEY TRINKE',2),
|
||||
(NULL, 'Team Obie',2),
|
||||
(NULL, 'weh',2),
|
||||
(NULL, 'Coconat Crew',2),
|
||||
(NULL, 'DISPEL DUXE',2),
|
||||
(NULL, 'Aftermath of GeekBoys',2),
|
||||
(NULL, 'RockStarz',2),
|
||||
(NULL, 'Triple Penetration',2),
|
||||
(NULL, 'Abandoned hope',2),
|
||||
(NULL, 'Againandagain',2),
|
||||
(NULL, 'WTFGON',2),
|
||||
(NULL, 'Chill',2),
|
||||
(NULL, 'SUPERPVPPOWER',2),
|
||||
(NULL, 'Funky ShEt',2),
|
||||
(NULL, 'Cyclone it and Run',2),
|
||||
(NULL, 'Mante and Alvi',2),
|
||||
(NULL, 'Toku was off',2),
|
||||
(NULL, 'BOOMHEADSHOT',2),
|
||||
(NULL, 'Beer',2),
|
||||
(NULL, 'Will you marry Me',2),
|
||||
(NULL, 'Razer was a piece of St',2),
|
||||
(NULL, 'More Dots',2),
|
||||
(NULL, 'SuirotkiV',2),
|
||||
(NULL, 'Celguar and Mostlikely',2),
|
||||
(NULL, 'You got PWNed',2),
|
||||
(NULL, 'Lido and Nonuse',2),
|
||||
(NULL, 'I Am Your Father',2),
|
||||
(NULL, 'TO XRYSO KOUFETO',2),
|
||||
(NULL, 'FourKings',2),
|
||||
(NULL, 'Dont hate the player',2),
|
||||
(NULL, 'LF akashis replacement',2),
|
||||
(NULL, 'Found Your Cookies',2),
|
||||
(NULL, 'manglecritTIOtysen',2),
|
||||
(NULL, 'For sale',2),
|
||||
(NULL, 'Pirates',2),
|
||||
(NULL, 'råttakuninkaat',2),
|
||||
(NULL, 'DotaAPgogo',2),
|
||||
(NULL, 'Has gone offline',2),
|
||||
(NULL, 'Hide your Cookies',2),
|
||||
(NULL, 'Player Hater Foundation',2),
|
||||
(NULL, 'Something new',2),
|
||||
(NULL, 'asdklfjkläasdhjkla',2),
|
||||
(NULL, 'Ignorance is Bliss',2),
|
||||
(NULL, 'Spellbook OPEN',2),
|
||||
(NULL, 'BIG SMITING MACHINE',2),
|
||||
(NULL, 'The Five Musketeers',2),
|
||||
(NULL, 'Proximity',2),
|
||||
(NULL, 'Artefakt',2),
|
||||
(NULL, 'Devastation',2),
|
||||
(NULL, 'Spawn more Overlords',2),
|
||||
(NULL, 'We only log on for arena',2),
|
||||
(NULL, 'Come Honour Face',2),
|
||||
(NULL, 'High Caliberr',2),
|
||||
(NULL, 'Wildhammer',2),
|
||||
(NULL, 'We dont like Arena',2),
|
||||
(NULL, 'No mercy for the noobs',2),
|
||||
(NULL, 'we loose because of exor',2),
|
||||
(NULL, 'Hit Me Hard',2),
|
||||
(NULL, 'Variksen Orjat',2),
|
||||
(NULL, 'Jumalauta',2),
|
||||
(NULL, 'Baqa lack skills',2),
|
||||
(NULL, 'The Crackheads',2),
|
||||
(NULL, 'Me Smash You',2),
|
||||
(NULL, 'Over the Top',2),
|
||||
(NULL, 'We like cookies',2),
|
||||
(NULL, 'Devil wears SRada',2),
|
||||
(NULL, 'Healing Misery',2),
|
||||
(NULL, 'Just gear',2),
|
||||
(NULL, 'Mystical Is Fat Dorf IRL',2),
|
||||
(NULL, 'DISPELL ME PLZ',2),
|
||||
(NULL, 'Death Note',2),
|
||||
(NULL, 'Wicked Grin',2),
|
||||
(NULL, 'Analnie Oduvanchiki',2),
|
||||
(NULL, 'eru bränd lr',2),
|
||||
(NULL, 'we lose coz schade sux',2),
|
||||
(NULL, 'forte gaming',2),
|
||||
(NULL, 'Blitzkrieg Platoon',2),
|
||||
(NULL, 'CC Inc',2),
|
||||
(NULL, 'Razerium',2),
|
||||
(NULL, 'Crusty Farmers',2),
|
||||
(NULL, 'Unrated',2),
|
||||
(NULL, 'jag grindar för guld',2),
|
||||
(NULL, 'Razor',2),
|
||||
(NULL, 'Sarahs Evil Minions',2),
|
||||
(NULL, 'Brutal Team',2),
|
||||
(NULL, 'apekatt',2),
|
||||
(NULL, 'Diekmann',2),
|
||||
(NULL, 'Balanced Combo',2),
|
||||
(NULL, 'Team of Lolroots',2),
|
||||
(NULL, 'Ajs is ubernoob',2),
|
||||
(NULL, 'Snowy gryphon',2),
|
||||
(NULL, 'steady hand',2),
|
||||
(NULL, 'Imbanuke',2),
|
||||
(NULL, 'Hello I like you',2),
|
||||
(NULL, 'Pallokala',2),
|
||||
(NULL, 'PuG And Pray',3),
|
||||
(NULL, 'DoT BoTs',3),
|
||||
(NULL, 'Italianstyle',3),
|
||||
(NULL, 'Fear Inc',3),
|
||||
(NULL, 'We survived Gnomeregan',3),
|
||||
(NULL, 'Three Mighty Mice',3),
|
||||
(NULL, 'Murlox',3),
|
||||
(NULL, 'Poon',3),
|
||||
(NULL, 'Manbearpig',3),
|
||||
(NULL, 'Yea we lift',3),
|
||||
(NULL, 'PuG KZ Fans',3),
|
||||
(NULL, 'Abandoned',3),
|
||||
(NULL, 'Rinse And Repeat',3),
|
||||
(NULL, 'WHATS GOING ON',3),
|
||||
(NULL, 'Chillside',3),
|
||||
(NULL, 'SUPERPVEPOWER',3),
|
||||
(NULL, 'Juicy Guys',3),
|
||||
(NULL, 'Cyclone and Run',3),
|
||||
(NULL, 'Check and Mate',3),
|
||||
(NULL, 'CC to Death',3),
|
||||
(NULL, 'two gimps and mighty pet',3),
|
||||
(NULL, 'Boulderfist Geeks',3),
|
||||
(NULL, 'Sap and Consecration',3),
|
||||
(NULL, 'Rusty Robocop',3),
|
||||
(NULL, 'More Dots Plx',3),
|
||||
(NULL, 'kARVAKAMUT',3),
|
||||
(NULL, 'Your face',3),
|
||||
(NULL, 'You got Stoneformed',3),
|
||||
(NULL, 'fluffy evil bunnies',3),
|
||||
(NULL, 'watrox elemental iceblox',3),
|
||||
(NULL, 'Serotonine',3),
|
||||
(NULL, 'Imbalanced',3),
|
||||
(NULL, 'inYaface',3),
|
||||
(NULL, 'lol we liek pie',3),
|
||||
(NULL, 'Pat Sharp Celebrity DJ',3),
|
||||
(NULL, 'Eighty gold WTF',3),
|
||||
(NULL, 'Righteous Rage',3),
|
||||
(NULL, 'momma said knock you out',3),
|
||||
(NULL, 'TeletabiTransformers',3),
|
||||
(NULL, 'Team Murloc',3),
|
||||
(NULL, 'GK',3),
|
||||
(NULL, 'kayfour',3),
|
||||
(NULL, 'we loose cos spraaty sux',3),
|
||||
(NULL, 'Infected Infinity',3),
|
||||
(NULL, 'Demogorgon sux',3),
|
||||
(NULL, 'My mate sux',3),
|
||||
(NULL, 'Set to Kill',3),
|
||||
(NULL, 'Team China',3),
|
||||
(NULL, 'schlag',3),
|
||||
(NULL, 'klops',3),
|
||||
(NULL, 'HAF A NAIS CUP O MANGEL',3),
|
||||
(NULL, 'Mantrain of Love',3),
|
||||
(NULL, 'The Light Embrace',3),
|
||||
(NULL, 'Team Glasmastarn',3),
|
||||
(NULL, 'Dwarf Wet Tshirt Team',3),
|
||||
(NULL, 'Tur med Vädret INC',3),
|
||||
(NULL, 'Dumb Dumber Dimtim',3),
|
||||
(NULL, 'Büdösbunkók',3),
|
||||
(NULL, 'ze germans are coming',3),
|
||||
(NULL, 'XND',3),
|
||||
(NULL, 'Hooked up by LFG chat',3),
|
||||
(NULL, 'KaplA',3),
|
||||
(NULL, 'The Perfect Storm',3),
|
||||
(NULL, 'ashwjzrwtficantmove',3),
|
||||
(NULL, 'Strawberry',3),
|
||||
(NULL, 'Three Ladies',3),
|
||||
(NULL, 'I Dont Know',3),
|
||||
(NULL, 'Our warrior cant do dmg',3),
|
||||
(NULL, 'Lockout',3),
|
||||
(NULL, 'Scrubs',3),
|
||||
(NULL, 'Tarmed',3),
|
||||
(NULL, 'Knockout',3),
|
||||
(NULL, 'Trollout',3),
|
||||
(NULL, 'Midgets and Co',3),
|
||||
(NULL, 'toy soldiers',3),
|
||||
(NULL, 'Your Nightmare',3),
|
||||
(NULL, 'lack of experience',3),
|
||||
(NULL, 'socialbidrag',3),
|
||||
(NULL, 'Sweep The Leg',3),
|
||||
(NULL, 'YourMomIsAnEpicMount',3),
|
||||
(NULL, 'Captain Birdseye',3),
|
||||
(NULL, 'Wasted Talent',3),
|
||||
(NULL, 'Hammer Time',3),
|
||||
(NULL, 'Really Powerful PvP',3),
|
||||
(NULL, 'TESTOVOIMAA',3),
|
||||
(NULL, 'Reptile in my Pants',3),
|
||||
(NULL, 'Insert Coin',3),
|
||||
(NULL, 'Vixens',3),
|
||||
(NULL, 'Keyboard Blackbelts',3),
|
||||
(NULL, 'Giggity',3),
|
||||
(NULL, 'Landoo',3),
|
||||
(NULL, 'GG MAN',3),
|
||||
(NULL, 'excrucio',3),
|
||||
(NULL, 'Recklessness',3),
|
||||
(NULL, 'envious',3),
|
||||
(NULL, 'Mordbrenner',3),
|
||||
(NULL, 'not my account',3),
|
||||
(NULL, 'Wir ausm Märchenland',3),
|
||||
(NULL, 'Erdbeerwochen',3),
|
||||
(NULL, 'Vierundzwanzig sieben',3),
|
||||
(NULL, 'PiDaBeLJueNDi',3),
|
||||
(NULL, 'Target was friendly',3),
|
||||
(NULL, 'Straight Outta Pjöngjang',3),
|
||||
(NULL, 'Y not',3),
|
||||
(NULL, 'Infamous',3),
|
||||
(NULL, 'NullachtfünfzehneR',5),
|
||||
(NULL, 'Dunkle Schar',5),
|
||||
(NULL, 'Flex',5),
|
||||
(NULL, 'Chîkara',5),
|
||||
(NULL, 'because size does matter',5),
|
||||
(NULL, 'wir ownen euch JETZT',5),
|
||||
(NULL, 'three bathing beauties',5),
|
||||
(NULL, 'Straight Outta Timbuktu',5),
|
||||
(NULL, 'Keyboard Turnerrizor',5),
|
||||
(NULL, 'dinosekz',5),
|
||||
(NULL, 'kÁ',5),
|
||||
(NULL, 'Boondock Pandas',5),
|
||||
(NULL, 'perfect',5),
|
||||
(NULL, 'Dracorex',5),
|
||||
(NULL, 'Annihilation',5),
|
||||
(NULL, 'X files',5),
|
||||
(NULL, 'Kuschlig weich',5),
|
||||
(NULL, 'Arcanum',5),
|
||||
(NULL, 'fatalis drei',5),
|
||||
(NULL, 'Psyms Team',5),
|
||||
(NULL, 'Push it to the Límit',5),
|
||||
(NULL, 'MassacreGamingDotCom',5),
|
||||
(NULL, 'need equip',5),
|
||||
(NULL, 'First Kill',5),
|
||||
(NULL, 'Sand in der Vaseline',5),
|
||||
(NULL, 'Panda',5),
|
||||
(NULL, 'Eradication Instincts',5),
|
||||
(NULL, 'eMiNeNCe',5),
|
||||
(NULL, 'O M F G ICH ZERHACK DICH',5),
|
||||
(NULL, 'foresighted',5),
|
||||
(NULL, 'heavy petting zoo',5),
|
||||
(NULL, 'Pew Pew Laser',5),
|
||||
(NULL, 'OMFG ICH ZERHACK DICH II',5),
|
||||
(NULL, 'Maustilicious',5),
|
||||
(NULL, 'FAQ',5),
|
||||
(NULL, 'Dreist',5),
|
||||
(NULL, 'Höllenflämmchen',5),
|
||||
(NULL, 'five mins no rush',5),
|
||||
(NULL, 'Sarang',5),
|
||||
(NULL, 'Die Wiederkäuer',5),
|
||||
(NULL, 'Schäfchen reloaded',5),
|
||||
(NULL, 'excellent',5),
|
||||
(NULL, 'Abyza',5),
|
||||
(NULL, 'n to the p',5),
|
||||
(NULL, 'haRdcorE baSh',5),
|
||||
(NULL, 'TeaM LoTTo',5),
|
||||
(NULL, 'Shattered Hand says hi',5),
|
||||
(NULL, 'Troll Cat',5),
|
||||
(NULL, 'Hilgrim INC',5),
|
||||
(NULL, 'Panda Assault',5),
|
||||
(NULL, 'Enter Victory',5),
|
||||
(NULL, 'Hung like a Cow',5),
|
||||
(NULL, 'Sangis Cobras',5),
|
||||
(NULL, 'Team Failure',5),
|
||||
(NULL, 'Viva Pinatas',5),
|
||||
(NULL, 'Blood Brothers',5),
|
||||
(NULL, 'Swomp Was Here',5),
|
||||
(NULL, 'ÆNima',5),
|
||||
(NULL, 'Team Poison',5),
|
||||
(NULL, 'WTB Flying Pink Elephant',5),
|
||||
(NULL, 'Thiz is a mans world',5),
|
||||
(NULL, 'Ri',5),
|
||||
(NULL, 'Poison',5),
|
||||
(NULL, 'BARE AND PLATE',5),
|
||||
(NULL, 'Skuggelaget',5),
|
||||
(NULL, 'Le Pinatas',5),
|
||||
(NULL, 'Finish Him',5),
|
||||
(NULL, 'Gentle Seduction',5),
|
||||
(NULL, 'Warrior Mage Paladin',5),
|
||||
(NULL, 'Haha',5),
|
||||
(NULL, 'NewtypE',5),
|
||||
(NULL, 'Mazinger Z',5),
|
||||
(NULL, 'Triple Impact',5),
|
||||
(NULL, 'Me lieK',5),
|
||||
(NULL, 'beep beep i am jeep',5),
|
||||
(NULL, 'Imprudent',5),
|
||||
(NULL, 'Galaxy Angel Team',5),
|
||||
(NULL, 'IceCrown',5),
|
||||
(NULL, 'Nba',5),
|
||||
(NULL, 'We fight for pie',5),
|
||||
(NULL, 'OK',5),
|
||||
(NULL, 'Randoms',5),
|
||||
(NULL, 'Wanna Be',5),
|
||||
(NULL, 'WANNA GO UBRS NVM AB LOL',5),
|
||||
(NULL, 'Deadly n Stuff',5),
|
||||
(NULL, 'Shadow Vulnerability',5),
|
||||
(NULL, 'Occult',5),
|
||||
(NULL, 'Crab People',5),
|
||||
(NULL, 'ena xeri kai ena podi',5),
|
||||
(NULL, 'OutPlayed',5),
|
||||
(NULL, 'No Life',5),
|
||||
(NULL, 'Shadows Edge',5),
|
||||
(NULL, 'Durotar Fight Club',5),
|
||||
(NULL, 'Warriors are easy',5),
|
||||
(NULL, 'Shatter',5),
|
||||
(NULL, 'Powerhouse',5),
|
||||
(NULL, 'Higitus Figitus',5),
|
||||
(NULL, 'RIP',5),
|
||||
(NULL, 'TSoG',5),
|
||||
(NULL, 'JUSTINS ENTOURAGE',5),
|
||||
(NULL, 'Guess Who',5),
|
||||
(NULL, 'Feeders Club',5),
|
||||
(NULL, 'Crab Pupils',5),
|
||||
(NULL, 'lol its a bird',5),
|
||||
(NULL, 'Deaf In Texas',5),
|
||||
(NULL, 'Millenium',5),
|
||||
(NULL, 'Les Pores',5),
|
||||
(NULL, 'No need War',5),
|
||||
(NULL, 'Overall',5),
|
||||
(NULL, 'WeLoseCozLweySux',5),
|
||||
(NULL, 'Epik Boyz de Lumière',5),
|
||||
(NULL, 'Himalaya',5),
|
||||
(NULL, 'Take it deep RETURNZ',5),
|
||||
(NULL, 'Gangrenaab',5),
|
||||
(NULL, 'Millenium Stylz',5),
|
||||
(NULL, 'Where is my umbrella',5),
|
||||
(NULL, 'Esport LOL',5),
|
||||
(NULL, 'HARDCORE UNITED',5),
|
||||
(NULL, 'Korean Wannabe',5),
|
||||
(NULL, 'Nétalïon',5),
|
||||
(NULL, 'Mega Jaunes volume Deux',5),
|
||||
(NULL, 'Impending Doom',5),
|
||||
(NULL, 'Les Poulets Fringuants',5),
|
||||
(NULL, 'Kool and teh Gank',5),
|
||||
(NULL, 'Mille Margoulins',5),
|
||||
(NULL, 'Naabz',5),
|
||||
(NULL, 'Need du stuff plz',5),
|
||||
(NULL, 'Typhoon',5),
|
||||
(NULL, 'A new Begining',5),
|
||||
(NULL, 'Est',5),
|
||||
(NULL, 'Les Rois Mages',5),
|
||||
(NULL, 'WeLooseCuzImoSux',5),
|
||||
(NULL, 'WeLozCozShamSuX',5),
|
||||
(NULL, 'WeLoseCuzNetherSux',5),
|
||||
(NULL, 'eXecut Him',5),
|
||||
(NULL, 'Økra est unstuff',5),
|
||||
(NULL, 'WeLoseCauzNetherSux',5),
|
||||
(NULL, 'WeLoseCozVixcisSux',5),
|
||||
(NULL, 'RAT',5),
|
||||
(NULL, 'a A a Arena',5),
|
||||
(NULL, 'OMG',5),
|
||||
(NULL, 'NoraJ ThX',5),
|
||||
(NULL, 'Tendresse et calin',5),
|
||||
(NULL, 'Laming is not a crime',5),
|
||||
(NULL, 'Over',5),
|
||||
(NULL, 'You love it',5),
|
||||
(NULL, 'Naturiste Dance',5),
|
||||
(NULL, 'Dead Breed',5),
|
||||
(NULL, 'To lazy',5),
|
||||
(NULL, 'CN',5),
|
||||
(NULL, 'Burn Mana',5),
|
||||
(NULL, 'A vendre',5),
|
||||
(NULL, 'We Lose Cuz Kisame Sux',5),
|
||||
(NULL, 'Pestis Atra',5),
|
||||
(NULL, 'Un vs deux',5),
|
||||
(NULL, 'Pwee Pwee BOUM',5),
|
||||
(NULL, 'Gnomette Team',5),
|
||||
(NULL, 'Croque plz',5),
|
||||
(NULL, 'Sux Compagny',5),
|
||||
(NULL, 'JESUS SAVE ME',5),
|
||||
(NULL, 'anatheme',5),
|
||||
(NULL, 'heal mon pet ffs',5),
|
||||
(NULL, 'Bip bip',5),
|
||||
(NULL, 'MbT',5),
|
||||
(NULL, 'CYCLONECOPTER',5),
|
||||
(NULL, 'Sargeras',5),
|
||||
(NULL, 'Dots n Hots or something',5),
|
||||
(NULL, 'This bear can eat you',5),
|
||||
(NULL, 'Combination of Male love',5),
|
||||
(NULL, 'Right in Two',5),
|
||||
(NULL, 'Rends Wrath',5),
|
||||
(NULL, 'Vita Brevis',5),
|
||||
(NULL, 'Tysken Justus',5),
|
||||
(NULL, 'Iso Kikkeli',5),
|
||||
(NULL, 'imbas',5),
|
||||
(NULL, 'Me love You',5),
|
||||
(NULL, 'We love pie',5),
|
||||
(NULL, 'F U',5),
|
||||
(NULL, 'CRITICAL ERROR',5),
|
||||
(NULL, 'Epica',5),
|
||||
(NULL, 'V i X',5),
|
||||
(NULL, 'Derka Derka Derka',5),
|
||||
(NULL, 'Killalot',5),
|
||||
(NULL, 'Flagstång',5),
|
||||
(NULL, 'The beauty and the beast',5);
|
||||
649
sql/characters/playerbots_guild_names.sql
Normal file
649
sql/characters/playerbots_guild_names.sql
Normal file
@ -0,0 +1,649 @@
|
||||
DROP TABLE IF EXISTS `playerbot_guild_names`;
|
||||
CREATE TABLE `playerbot_guild_names` (
|
||||
`name_id` INT(11) NOT NULL AUTO_INCREMENT UNIQUE,
|
||||
`name` varchar(24) NOT NULL UNIQUE,
|
||||
PRIMARY KEY (`name_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Playerbot guild names';
|
||||
|
||||
INSERT INTO `playerbot_guild_names` VALUES
|
||||
(NULL, 'Black Guard'),
|
||||
(NULL, 'Abyssal Kingdoms'),
|
||||
(NULL, 'Acid Evil'),
|
||||
(NULL, 'Addicts Muskateers'),
|
||||
(NULL, 'Adventurers War'),
|
||||
(NULL, 'Age of Red Water Clan'),
|
||||
(NULL, 'Alivso Reason'),
|
||||
(NULL, 'All Knights'),
|
||||
(NULL, 'Allegiance of the Vile'),
|
||||
(NULL, 'Alliance Clan'),
|
||||
(NULL, 'Alliance of Defectives'),
|
||||
(NULL, 'Alti Legions'),
|
||||
(NULL, 'Anarchie Shi'),
|
||||
(NULL, 'Anchors of the Nominal'),
|
||||
(NULL, 'Ancients of Part Times'),
|
||||
(NULL, 'Angelus Gods'),
|
||||
(NULL, 'Angry Party'),
|
||||
(NULL, 'Apocalyptic Lamont'),
|
||||
(NULL, 'Architects of Green'),
|
||||
(NULL, 'Army of Black Widows'),
|
||||
(NULL, 'Army of Orgrimmar Minds'),
|
||||
(NULL, 'Army of Three Horses'),
|
||||
(NULL, 'Arrows of Midlight'),
|
||||
(NULL, 'Artisans of Best Guild'),
|
||||
(NULL, 'Assasins of the Pyrewood'),
|
||||
(NULL, 'Assassins Bane'),
|
||||
(NULL, 'Avatars of Warsong Stuff'),
|
||||
(NULL, 'Axis of the Funky Night'),
|
||||
(NULL, 'Azeroth Souls'),
|
||||
(NULL, 'Azeroths Rabbits'),
|
||||
(NULL, 'Bad Sentinels'),
|
||||
(NULL, 'Banana Song'),
|
||||
(NULL, 'Band of Tarantula Attack'),
|
||||
(NULL, 'Band of the Dark Reveren'),
|
||||
(NULL, 'Barcode Praised'),
|
||||
(NULL, 'Basher Goats'),
|
||||
(NULL, 'Basic Order'),
|
||||
(NULL, 'Batman of Banished'),
|
||||
(NULL, 'Betrayers of Lucky Child'),
|
||||
(NULL, 'Blackwater Committee'),
|
||||
(NULL, 'Blades of Lich Kings'),
|
||||
(NULL, 'Blades of the Hive'),
|
||||
(NULL, 'Blades of the Total'),
|
||||
(NULL, 'Bleeding War'),
|
||||
(NULL, 'Blessed Lair'),
|
||||
(NULL, 'Blizzards of the Iron'),
|
||||
(NULL, 'Blood Chaos'),
|
||||
(NULL, 'Blood Intrigue'),
|
||||
(NULL, 'Blood Samurai'),
|
||||
(NULL, 'Bloodlust Good'),
|
||||
(NULL, 'Bonds of Reported Ignore'),
|
||||
(NULL, 'Booty Cry'),
|
||||
(NULL, 'Border Knights'),
|
||||
(NULL, 'Bossmans Targaryen'),
|
||||
(NULL, 'Braveheart Heaven'),
|
||||
(NULL, 'Brotherhood of Twilight'),
|
||||
(NULL, 'Bruised Pain'),
|
||||
(NULL, 'Burning Control'),
|
||||
(NULL, 'Burning Oblivion'),
|
||||
(NULL, 'Cabal of Kalimdor'),
|
||||
(NULL, 'Cake Crusade'),
|
||||
(NULL, 'Call of the Ironforge'),
|
||||
(NULL, 'Carebears Thunder'),
|
||||
(NULL, 'Carpe Heaven'),
|
||||
(NULL, 'Carpe Regiment'),
|
||||
(NULL, 'Children of Order'),
|
||||
(NULL, 'Children of the Gods'),
|
||||
(NULL, 'Circle of Amor E Bobby'),
|
||||
(NULL, 'Clan of the Elven Toys'),
|
||||
(NULL, 'Clan of the Strike Light'),
|
||||
(NULL, 'Coalition of Super Best'),
|
||||
(NULL, 'Collective Pimps'),
|
||||
(NULL, 'Companions of the Gnome'),
|
||||
(NULL, 'Company of the Vibe'),
|
||||
(NULL, 'Conclave of the Triad'),
|
||||
(NULL, 'Council of Final Demise'),
|
||||
(NULL, 'Council of Hard Core Ord'),
|
||||
(NULL, 'Craaweh Thrall'),
|
||||
(NULL, 'Cradle Scourge'),
|
||||
(NULL, 'Crimson Angels'),
|
||||
(NULL, 'Crimson Saints'),
|
||||
(NULL, 'Crusade of Oh'),
|
||||
(NULL, 'Crusaders of Undead'),
|
||||
(NULL, 'Cryptic Serenity'),
|
||||
(NULL, 'Csa Rigged'),
|
||||
(NULL, 'Cult of the Raging Raid'),
|
||||
(NULL, 'Dalaran Fair'),
|
||||
(NULL, 'Damage Inc'),
|
||||
(NULL, 'Dark Alliance'),
|
||||
(NULL, 'Dark Azeroth'),
|
||||
(NULL, 'Dark Damage'),
|
||||
(NULL, 'Dark Resistus'),
|
||||
(NULL, 'Dark Samurai'),
|
||||
(NULL, 'Dark Turtles'),
|
||||
(NULL, 'Darken Mercenaries'),
|
||||
(NULL, 'Darkened Malevolence'),
|
||||
(NULL, 'Darkness of Sword Coast'),
|
||||
(NULL, 'Dawn of Knights Society'),
|
||||
(NULL, 'Dawn of Mad Sentry'),
|
||||
(NULL, 'Dead Zug'),
|
||||
(NULL, 'Death Darkness'),
|
||||
(NULL, 'Death Knights'),
|
||||
(NULL, 'Deathlike Goods'),
|
||||
(NULL, 'Deaths Venoms'),
|
||||
(NULL, 'Decree of the Phumpers'),
|
||||
(NULL, 'Defenders of Da Raised'),
|
||||
(NULL, 'Defenders of Hyuuga Dark'),
|
||||
(NULL, 'Defenders of Sacred Harm'),
|
||||
(NULL, 'Deths Lords'),
|
||||
(NULL, 'Devil Circl'),
|
||||
(NULL, 'Devils Klng'),
|
||||
(NULL, 'Dharma Hand'),
|
||||
(NULL, 'Dharma Thorn'),
|
||||
(NULL, 'Dies Ravager'),
|
||||
(NULL, 'Disciples of Dead Panda'),
|
||||
(NULL, 'Disciples of the Rot'),
|
||||
(NULL, 'Doomsday Youth'),
|
||||
(NULL, 'Dorcha Knights'),
|
||||
(NULL, 'Dots of Dead Skull'),
|
||||
(NULL, 'Dragon Arms'),
|
||||
(NULL, 'Dragonhawk Revolution'),
|
||||
(NULL, 'Dragons Erythnul'),
|
||||
(NULL, 'Dragons of the Black'),
|
||||
(NULL, 'Drunken Thunder'),
|
||||
(NULL, 'Drunks of Matoskan'),
|
||||
(NULL, 'Dwarven Rock'),
|
||||
(NULL, 'Dynasty of the Emerald'),
|
||||
(NULL, 'Eastern Asylum'),
|
||||
(NULL, 'Echo Sanctus'),
|
||||
(NULL, 'Echoes of the Muphin'),
|
||||
(NULL, 'Effreno Death'),
|
||||
(NULL, 'Elite Guild'),
|
||||
(NULL, 'Elite Legion'),
|
||||
(NULL, 'Elite Veritas'),
|
||||
(NULL, 'Elunes Meat'),
|
||||
(NULL, 'Emerald Men'),
|
||||
(NULL, 'Emerald Mjolnir'),
|
||||
(NULL, 'Endless Defense'),
|
||||
(NULL, 'Enemies of Bleeding'),
|
||||
(NULL, 'Enternal Saber'),
|
||||
(NULL, 'Evictors of the Returned'),
|
||||
(NULL, 'Evil Guard'),
|
||||
(NULL, 'Exalted Effect'),
|
||||
(NULL, 'Eyes of a Night Elf'),
|
||||
(NULL, 'Eyes of the Elton Souls'),
|
||||
(NULL, 'Fallen Clan'),
|
||||
(NULL, 'Fallen Milk'),
|
||||
(NULL, 'Fenrir Seeker'),
|
||||
(NULL, 'Final Army'),
|
||||
(NULL, 'Flames of Ale Drinkers'),
|
||||
(NULL, 'Flames of Antarian Chaos'),
|
||||
(NULL, 'Forestt''s Wrath'),
|
||||
(NULL, 'Forgotten Within'),
|
||||
(NULL, 'From Synergy'),
|
||||
(NULL, 'Frozen Oblivion'),
|
||||
(NULL, 'Gashlycrumb Rollers'),
|
||||
(NULL, 'Giovannitwos Elune'),
|
||||
(NULL, 'Glass Meridian'),
|
||||
(NULL, 'Gnome Faction'),
|
||||
(NULL, 'Gods Gold'),
|
||||
(NULL, 'Gods of the Complete'),
|
||||
(NULL, 'Gold Catchers'),
|
||||
(NULL, 'Golden Legendz'),
|
||||
(NULL, 'Golden Souls'),
|
||||
(NULL, 'Goldshire Goats'),
|
||||
(NULL, 'Good Azeroth'),
|
||||
(NULL, 'Gotz Safety'),
|
||||
(NULL, 'Grammaton Alliance'),
|
||||
(NULL, 'Great Circle'),
|
||||
(NULL, 'Guardians of Honor'),
|
||||
(NULL, 'Guards of Frostmane'),
|
||||
(NULL, 'Guild of La Mano Dragons'),
|
||||
(NULL, 'Guild of the Puppet'),
|
||||
(NULL, 'Haggles Brigade'),
|
||||
(NULL, 'Hammer of the Moral'),
|
||||
(NULL, 'Hand of the Iron'),
|
||||
(NULL, 'Hands of Far Con Buddies'),
|
||||
(NULL, 'Hearts Knights'),
|
||||
(NULL, 'Hell Angels'),
|
||||
(NULL, 'Hells Thorn'),
|
||||
(NULL, 'Holy Darnassus'),
|
||||
(NULL, 'Horde Abh'),
|
||||
(NULL, 'Horde Dragons'),
|
||||
(NULL, 'Horde Leaders'),
|
||||
(NULL, 'Horde Squad'),
|
||||
(NULL, 'Horde of Omnia'),
|
||||
(NULL, 'Horde of Free Brigade'),
|
||||
(NULL, 'Horde of Shadow Flush'),
|
||||
(NULL, 'Hordes Buccaneers'),
|
||||
(NULL, 'Hordes Marauders'),
|
||||
(NULL, 'House Crusaders'),
|
||||
(NULL, 'Immortality Honor'),
|
||||
(NULL, 'Inside Poof'),
|
||||
(NULL, 'Iron Boyz'),
|
||||
(NULL, 'Iscariot Ginas'),
|
||||
(NULL, 'Island Kimchi'),
|
||||
(NULL, 'Jenovas Wild'),
|
||||
(NULL, 'Kalimdor Darkness'),
|
||||
(NULL, 'Keepers of Golden Misery'),
|
||||
(NULL, 'Keggers of Alt Hand Aton'),
|
||||
(NULL, 'Kill Mafia'),
|
||||
(NULL, 'Killer Durotar'),
|
||||
(NULL, 'Killer Force'),
|
||||
(NULL, 'Kindred Yardies'),
|
||||
(NULL, 'Kindred of King Assassin'),
|
||||
(NULL, 'Kingdom of the Ordo Crew'),
|
||||
(NULL, 'Kings Boys'),
|
||||
(NULL, 'Kings Windstorm'),
|
||||
(NULL, 'Kings of Blood Knuckle'),
|
||||
(NULL, 'Kings of Dol Aegis'),
|
||||
(NULL, 'Knight Combat'),
|
||||
(NULL, 'Knight of Fuzzy Night'),
|
||||
(NULL, 'Knights of Darkspear'),
|
||||
(NULL, 'Knights of Heavens Grave'),
|
||||
(NULL, 'Knights of Myrmidon Ivxx'),
|
||||
(NULL, 'Knights of the Avenging'),
|
||||
(NULL, 'Knights of the Ballpeen'),
|
||||
(NULL, 'Knights of the Black'),
|
||||
(NULL, 'Knights of the Bloodhoof'),
|
||||
(NULL, 'Knights of the Sovereign'),
|
||||
(NULL, 'Knights of the Storm'),
|
||||
(NULL, 'Knights of the Zulian'),
|
||||
(NULL, 'Last Ptesanwi'),
|
||||
(NULL, 'League of Hate Crew Seek'),
|
||||
(NULL, 'Legacy of Ninth Beard'),
|
||||
(NULL, 'Legendary Sons'),
|
||||
(NULL, 'Legion of Maple Syrup'),
|
||||
(NULL, 'Legion of Public Works'),
|
||||
(NULL, 'Legion of Three Course'),
|
||||
(NULL, 'Legion of United Souls'),
|
||||
(NULL, 'Legion of Westfall Gold'),
|
||||
(NULL, 'Legion of the Dark'),
|
||||
(NULL, 'Legionnaires of Skull'),
|
||||
(NULL, 'Les Warriors'),
|
||||
(NULL, 'Lifetakers Inc'),
|
||||
(NULL, 'Light of Dark Spire'),
|
||||
(NULL, 'Light of Jade Renegade'),
|
||||
(NULL, 'Liquid Guild'),
|
||||
(NULL, 'Lone Side'),
|
||||
(NULL, 'Lords of Fallen Blood'),
|
||||
(NULL, 'Los Frum'),
|
||||
(NULL, 'Lost Boyz'),
|
||||
(NULL, 'Lost Squad'),
|
||||
(NULL, 'Mad Daggers'),
|
||||
(NULL, 'Malice Fatale'),
|
||||
(NULL, 'Mandate of Jade'),
|
||||
(NULL, 'Marines of the Butt'),
|
||||
(NULL, 'Mercenaries of the Death'),
|
||||
(NULL, 'Midget Council'),
|
||||
(NULL, 'Midgets of Dark Sexy'),
|
||||
(NULL, 'Midnight Norrathians'),
|
||||
(NULL, 'Midnight Slayer'),
|
||||
(NULL, 'Midnight War'),
|
||||
(NULL, 'Minions of the Shadow'),
|
||||
(NULL, 'Ministry of the Allince'),
|
||||
(NULL, 'Mithril Destiny'),
|
||||
(NULL, 'Monarchs of Party Crew'),
|
||||
(NULL, 'Money Call'),
|
||||
(NULL, 'Moonwood Redeye'),
|
||||
(NULL, 'Narrow Patrol'),
|
||||
(NULL, 'New Clan'),
|
||||
(NULL, 'Night Pack'),
|
||||
(NULL, 'Nightmare Guild'),
|
||||
(NULL, 'Ninja Pledge'),
|
||||
(NULL, 'Nocturne of Totally Dead'),
|
||||
(NULL, 'Obsidian Fish'),
|
||||
(NULL, 'Old Cosa'),
|
||||
(NULL, 'One Valor'),
|
||||
(NULL, 'Opus Faithful'),
|
||||
(NULL, 'Order of Alts oF Fate'),
|
||||
(NULL, 'Order of Nagas Bike Hunt'),
|
||||
(NULL, 'Order of Omega Wards'),
|
||||
(NULL, 'Order of Pink'),
|
||||
(NULL, 'Order of Shield Bed'),
|
||||
(NULL, 'Order of the Alt Sheep'),
|
||||
(NULL, 'Order of the Honor'),
|
||||
(NULL, 'Order of the Divine Lord'),
|
||||
(NULL, 'Ordo Force'),
|
||||
(NULL, 'Orgrimmar Ones'),
|
||||
(NULL, 'Out of Lw Downed Wrynn'),
|
||||
(NULL, 'Out of Mithril Avengers'),
|
||||
(NULL, 'Oxbloods Medivh'),
|
||||
(NULL, 'Pally Guard'),
|
||||
(NULL, 'Path of the Brain'),
|
||||
(NULL, 'Peddlers of the Hidden'),
|
||||
(NULL, 'Phantoms of Wicked'),
|
||||
(NULL, 'Phoenix Keepers'),
|
||||
(NULL, 'Pillowcase Azeroth'),
|
||||
(NULL, 'Pillowcase Cats'),
|
||||
(NULL, 'Pius Tribe'),
|
||||
(NULL, 'Plague of Human Slayer'),
|
||||
(NULL, 'Plan Hand'),
|
||||
(NULL, 'Power of Tuatha De Blood'),
|
||||
(NULL, 'Priest Guild'),
|
||||
(NULL, 'Prophets of Fatima War'),
|
||||
(NULL, 'Prophets of Outlaw'),
|
||||
(NULL, 'Prophets of the Red Mean'),
|
||||
(NULL, 'Protectors of Black Hand'),
|
||||
(NULL, 'Pure Aequitas'),
|
||||
(NULL, 'Question Thrall'),
|
||||
(NULL, 'Quintessential Sister'),
|
||||
(NULL, 'Rage of Prairie Black'),
|
||||
(NULL, 'Rage of the Flame'),
|
||||
(NULL, 'Raiders of Candy Heart'),
|
||||
(NULL, 'Raiders of the Purple'),
|
||||
(NULL, 'Raiders of the Sil'),
|
||||
(NULL, 'Ram Runners'),
|
||||
(NULL, 'Rangers Vengeance'),
|
||||
(NULL, 'Rangers of Interitus'),
|
||||
(NULL, 'Raven Clan'),
|
||||
(NULL, 'Razzle Guardian'),
|
||||
(NULL, 'Reapers of the Shadow'),
|
||||
(NULL, 'Reckless Knights'),
|
||||
(NULL, 'Red Byam'),
|
||||
(NULL, 'Red Death'),
|
||||
(NULL, 'Reign of Alliance Task'),
|
||||
(NULL, 'Reign of Blazing Frell'),
|
||||
(NULL, 'Reign of Pure Conway'),
|
||||
(NULL, 'Restoration of Illegal'),
|
||||
(NULL, 'Resurrection of Tenui'),
|
||||
(NULL, 'Ronin Kalimdor'),
|
||||
(NULL, 'Rotting Tears'),
|
||||
(NULL, 'Ruins of Dark Azeroth'),
|
||||
(NULL, 'Rulers of Devils'),
|
||||
(NULL, 'Sacred Parts'),
|
||||
(NULL, 'Sacred Society'),
|
||||
(NULL, 'Sacrificial Brotherhood'),
|
||||
(NULL, 'Sanguine Council'),
|
||||
(NULL, 'Sapphic Exiles'),
|
||||
(NULL, 'Savage Kalimdor'),
|
||||
(NULL, 'Scourge of Eight Inches'),
|
||||
(NULL, 'Scourge of Wow Knights'),
|
||||
(NULL, 'Scythe Sauce'),
|
||||
(NULL, 'Secret Clan'),
|
||||
(NULL, 'Seki Council'),
|
||||
(NULL, 'Seraph Legends'),
|
||||
(NULL, 'Shaded Judgement'),
|
||||
(NULL, 'Shadow America'),
|
||||
(NULL, 'Shadow Boys'),
|
||||
(NULL, 'Shadow Knights'),
|
||||
(NULL, 'Shadowed Ghosts'),
|
||||
(NULL, 'Shadowed Goat'),
|
||||
(NULL, 'Shadows of Cole Trainz'),
|
||||
(NULL, 'Shadows of Los Banditos'),
|
||||
(NULL, 'Shattered Stormrage'),
|
||||
(NULL, 'Silent Night'),
|
||||
(NULL, 'Silver Fools'),
|
||||
(NULL, 'Silversky Sun'),
|
||||
(NULL, 'Sisters of Kalimdor'),
|
||||
(NULL, 'Skulled Ironforge'),
|
||||
(NULL, 'Slayers of the Primals'),
|
||||
(NULL, 'Sleepy Steel'),
|
||||
(NULL, 'Soldiers of Azeroth'),
|
||||
(NULL, 'Soldiers of Stalker'),
|
||||
(NULL, 'Sons of Lambent Virtue'),
|
||||
(NULL, 'Sons of the Top Truth'),
|
||||
(NULL, 'Soul Wish'),
|
||||
(NULL, 'Souls of Elite Gnome'),
|
||||
(NULL, 'Spanaway Metalheadz'),
|
||||
(NULL, 'Spoony Demise'),
|
||||
(NULL, 'Squires of Sacred Tribe'),
|
||||
(NULL, 'Stagnant Jesters'),
|
||||
(NULL, 'Stars of Gear Farming'),
|
||||
(NULL, 'Stupid Crusaders'),
|
||||
(NULL, 'Stop Guides'),
|
||||
(NULL, 'Storm of the Mope''s'),
|
||||
(NULL, 'Stormrage Ferguson'),
|
||||
(NULL, 'Stormtroopers of Fatima '),
|
||||
(NULL, 'Stormwind Crew'),
|
||||
(NULL, 'Straight Caedes'),
|
||||
(NULL, 'Stronghold Angels'),
|
||||
(NULL, 'Sturgeon Empire'),
|
||||
(NULL, 'Survivors of Devil Club'),
|
||||
(NULL, 'Sweet Bear'),
|
||||
(NULL, 'Sword of Lost Evil'),
|
||||
(NULL, 'Tainted Bunnies'),
|
||||
(NULL, 'Talon of the Eclectic'),
|
||||
(NULL, 'Team Kingdom'),
|
||||
(NULL, 'Team United'),
|
||||
(NULL, 'Tears of Eternal Kitties'),
|
||||
(NULL, 'Tears of Phantom Druids'),
|
||||
(NULL, 'Templar of Raid Dodgers'),
|
||||
(NULL, 'Templars of Plagueware'),
|
||||
(NULL, 'Terra Totem'),
|
||||
(NULL, 'Terra War'),
|
||||
(NULL, 'The Abiem'),
|
||||
(NULL, 'The Aceofchaos'),
|
||||
(NULL, 'The Afterlife'),
|
||||
(NULL, 'The Aggression'),
|
||||
(NULL, 'The Alliance of Dark'),
|
||||
(NULL, 'The Altimate'),
|
||||
(NULL, 'The Ancona Fire'),
|
||||
(NULL, 'The Apocalypse'),
|
||||
(NULL, 'The Arcane Monkey'),
|
||||
(NULL, 'The Army of Spartans'),
|
||||
(NULL, 'The Avalon'),
|
||||
(NULL, 'The Avengers of Shining'),
|
||||
(NULL, 'The Azure Gangstaz'),
|
||||
(NULL, 'The Battlegnome'),
|
||||
(NULL, 'The Black Hand Haven'),
|
||||
(NULL, 'The Blackdraygon'),
|
||||
(NULL, 'The Blackout'),
|
||||
(NULL, 'The Blade'),
|
||||
(NULL, 'The Blades of Caer Eel'),
|
||||
(NULL, 'The Blades of Onyxia'),
|
||||
(NULL, 'The Blood Red Violence'),
|
||||
(NULL, 'The Blood of Red Powers'),
|
||||
(NULL, 'The Bloodycrusaders'),
|
||||
(NULL, 'The Blues Azeroth'),
|
||||
(NULL, 'The Blues Grimfang'),
|
||||
(NULL, 'The Bluethunder'),
|
||||
(NULL, 'The Bonds of Arcane'),
|
||||
(NULL, 'The Brimstone'),
|
||||
(NULL, 'The Broken Chaos'),
|
||||
(NULL, 'The Brood of Unknown'),
|
||||
(NULL, 'The Burning Dog Firewall'),
|
||||
(NULL, 'The Cabal'),
|
||||
(NULL, 'The Cake Gankers'),
|
||||
(NULL, 'The Cannabuddies'),
|
||||
(NULL, 'The Circle of Shadow'),
|
||||
(NULL, 'The Clan Blackwatch Few'),
|
||||
(NULL, 'The Clan Cats'),
|
||||
(NULL, 'The Clan Knights'),
|
||||
(NULL, 'The Clean Combinations'),
|
||||
(NULL, 'The Clean Up Guard'),
|
||||
(NULL, 'The Council of Dark'),
|
||||
(NULL, 'The Covenant'),
|
||||
(NULL, 'The Crimson Guild'),
|
||||
(NULL, 'The Crimson Marbock'),
|
||||
(NULL, 'The Crusaders of Horde'),
|
||||
(NULL, 'The Crusaders of Seksoni'),
|
||||
(NULL, 'The Cult of Clan Brigade'),
|
||||
(NULL, 'The Cult of the Pink'),
|
||||
(NULL, 'The Daggers of the Vile'),
|
||||
(NULL, 'The Dark'),
|
||||
(NULL, 'The Dark Dogs'),
|
||||
(NULL, 'The Dark Pain'),
|
||||
(NULL, 'The Darkfall'),
|
||||
(NULL, 'The Darkside Vanguard'),
|
||||
(NULL, 'The Darkside of Initium'),
|
||||
(NULL, 'The Daughters of the Elite'),
|
||||
(NULL, 'The Daytripper'),
|
||||
(NULL, 'The Deadfriends'),
|
||||
(NULL, 'The Defiant'),
|
||||
(NULL, 'The Dont Overwhelming'),
|
||||
(NULL, 'The Doom Pasta'),
|
||||
(NULL, 'The Dragon Redeye'),
|
||||
(NULL, 'The Dragons Flame'),
|
||||
(NULL, 'The Dreadlords'),
|
||||
(NULL, 'The Dublainn Crown'),
|
||||
(NULL, 'The Durban Protecters'),
|
||||
(NULL, 'The Echoes of Goldshire'),
|
||||
(NULL, 'The Elit of Dark Elune'),
|
||||
(NULL, 'The Emissaries of Furiou'),
|
||||
(NULL, 'The Eternal Chaos'),
|
||||
(NULL, 'The Eternus'),
|
||||
(NULL, 'The Exiie'),
|
||||
(NULL, 'The Expendable Shadow'),
|
||||
(NULL, 'The Faith of Desert'),
|
||||
(NULL, 'The Family Misfits'),
|
||||
(NULL, 'The Fere Darkness'),
|
||||
(NULL, 'The Final Tears'),
|
||||
(NULL, 'The Forsaken Boochies'),
|
||||
(NULL, 'The Gates of the Bloody'),
|
||||
(NULL, 'The Gnomes Lordaero'),
|
||||
(NULL, 'The Gods of Blackscar'),
|
||||
(NULL, 'The Gods of Twilight'),
|
||||
(NULL, 'The Gold Fighters'),
|
||||
(NULL, 'The Guardian Thieves'),
|
||||
(NULL, 'The Guardians of Gnome'),
|
||||
(NULL, 'The Hands of Redridge'),
|
||||
(NULL, 'The Hawk'),
|
||||
(NULL, 'The Hearts Images'),
|
||||
(NULL, 'The Hellborn Die'),
|
||||
(NULL, 'The Heroes Plague'),
|
||||
(NULL, 'The Horde Farmer'),
|
||||
(NULL, 'The Horde Honor'),
|
||||
(NULL, 'The Hotpocket'),
|
||||
(NULL, 'The Ignis Prophecy'),
|
||||
(NULL, 'The Illuminatie'),
|
||||
(NULL, 'The Immortal League'),
|
||||
(NULL, 'The Independant'),
|
||||
(NULL, 'The Infragilis Legion'),
|
||||
(NULL, 'The Jag'),
|
||||
(NULL, 'The Jookmaster'),
|
||||
(NULL, 'The Kataclysm'),
|
||||
(NULL, 'The Knight'),
|
||||
(NULL, 'The Knightelf'),
|
||||
(NULL, 'The Knights Thorn'),
|
||||
(NULL, 'The Knights of Gods Fury'),
|
||||
(NULL, 'The Knights of Lost Peon'),
|
||||
(NULL, 'The Knights of Mortal'),
|
||||
(NULL, 'The Knights of Samurai'),
|
||||
(NULL, 'The Kobra'),
|
||||
(NULL, 'The Leaders of Evil'),
|
||||
(NULL, 'The Leaders of Life'),
|
||||
(NULL, 'The League of Red Knight'),
|
||||
(NULL, 'The Legacy Meathooks'),
|
||||
(NULL, 'The Legion of the Blue'),
|
||||
(NULL, 'The Legion of Death'),
|
||||
(NULL, 'The Lemmings of Flaming'),
|
||||
(NULL, 'The Let Blood Gamer'),
|
||||
(NULL, 'The Light'),
|
||||
(NULL, 'The Little Hunters'),
|
||||
(NULL, 'The Lords of Vae Knight'),
|
||||
(NULL, 'The Mercenaries'),
|
||||
(NULL, 'The Midieval Vanguard'),
|
||||
(NULL, 'The Might of Dark Tong'),
|
||||
(NULL, 'The Mithril Justice'),
|
||||
(NULL, 'The Mithril Pepsi'),
|
||||
(NULL, 'The Mjollnir'),
|
||||
(NULL, 'The Moo Licht'),
|
||||
(NULL, 'The Morgantis'),
|
||||
(NULL, 'The Mulletmen'),
|
||||
(NULL, 'The Necrontyr of Eternal'),
|
||||
(NULL, 'The Nedrage Kills'),
|
||||
(NULL, 'The Night'),
|
||||
(NULL, 'The Nightfall'),
|
||||
(NULL, 'The Ninja Heroes'),
|
||||
(NULL, 'The Order of Gold'),
|
||||
(NULL, 'The Order of Warcraft'),
|
||||
(NULL, 'The Order of Warsong'),
|
||||
(NULL, 'The Over Louder'),
|
||||
(NULL, 'The Overlord'),
|
||||
(NULL, 'The Pants'),
|
||||
(NULL, 'The Pie'),
|
||||
(NULL, 'The Pretectors'),
|
||||
(NULL, 'The Project Disease'),
|
||||
(NULL, 'The Psychotics'),
|
||||
(NULL, 'The Puggers'),
|
||||
(NULL, 'The Pyreborne'),
|
||||
(NULL, 'The Queen of Meow'),
|
||||
(NULL, 'The Red Hood Thunder'),
|
||||
(NULL, 'The Reign of Uber Enigma'),
|
||||
(NULL, 'The Resurrection'),
|
||||
(NULL, 'The Ring of Honor'),
|
||||
(NULL, 'The Ropetown'),
|
||||
(NULL, 'The Royal Militia Blanco'),
|
||||
(NULL, 'The Samurai Banda'),
|
||||
(NULL, 'The Sanity'),
|
||||
(NULL, 'The Sauce'),
|
||||
(NULL, 'The Schoolyard Reapers'),
|
||||
(NULL, 'The Secrets of Hehog'),
|
||||
(NULL, 'The Seers'),
|
||||
(NULL, 'The Servants of Cyclone'),
|
||||
(NULL, 'The Seven'),
|
||||
(NULL, 'The Shadow Gate'),
|
||||
(NULL, 'The Shadow Misfits'),
|
||||
(NULL, 'The Shadow of Ninja Pain'),
|
||||
(NULL, 'The Shadowborn'),
|
||||
(NULL, 'The Shizam'),
|
||||
(NULL, 'The Shockers'),
|
||||
(NULL, 'The Shriek of Nightmare'),
|
||||
(NULL, 'The Silent Grunts'),
|
||||
(NULL, 'The Silent Legion'),
|
||||
(NULL, 'The Skunkdesigns'),
|
||||
(NULL, 'The Sorrow'),
|
||||
(NULL, 'The Souls of Azeroth Old'),
|
||||
(NULL, 'The Spazler'),
|
||||
(NULL, 'The Squirrels'),
|
||||
(NULL, 'The Stringville'),
|
||||
(NULL, 'The Stronghold of Reds'),
|
||||
(NULL, 'The Tha Handlers'),
|
||||
(NULL, 'The Thieves of Moral'),
|
||||
(NULL, 'The Thorium Claw'),
|
||||
(NULL, 'The Thread'),
|
||||
(NULL, 'The Thule'),
|
||||
(NULL, 'The Thunderslayers'),
|
||||
(NULL, 'The True Wow'),
|
||||
(NULL, 'The Trusted Minions'),
|
||||
(NULL, 'The Twilight Rangers'),
|
||||
(NULL, 'The Tyraels Aggression'),
|
||||
(NULL, 'The Ultimates'),
|
||||
(NULL, 'The Unforgiven Heresy'),
|
||||
(NULL, 'The Unholy Bards'),
|
||||
(NULL, 'The Unsung Efficiency'),
|
||||
(NULL, 'The Valley of the Demon'),
|
||||
(NULL, 'The Valor'),
|
||||
(NULL, 'The Violent Chaos'),
|
||||
(NULL, 'The Virus Eternal'),
|
||||
(NULL, 'The War'),
|
||||
(NULL, 'The Warsong Gnomeregan'),
|
||||
(NULL, 'The Westcoast'),
|
||||
(NULL, 'The Wicked'),
|
||||
(NULL, 'The Will of Chronicles'),
|
||||
(NULL, 'The Windsword Nightmare'),
|
||||
(NULL, 'The Wings of Oxy Claw'),
|
||||
(NULL, 'The Wrath of Elton'),
|
||||
(NULL, 'The Wut'),
|
||||
(NULL, 'The Yoricks Assassins'),
|
||||
(NULL, 'The Zeksonic Thieves'),
|
||||
(NULL, 'Theramore Azeroth'),
|
||||
(NULL, 'Thirstquencher Chaos'),
|
||||
(NULL, 'Thralls Caribous'),
|
||||
(NULL, 'Three Alive'),
|
||||
(NULL, 'Titans of Blood Sun'),
|
||||
(NULL, 'Torvus Dragons'),
|
||||
(NULL, 'Tower of the Little'),
|
||||
(NULL, 'True Team'),
|
||||
(NULL, 'Tul Inc'),
|
||||
(NULL, 'Twinks of Cold Club'),
|
||||
(NULL, 'Twinks of Hidden Venture'),
|
||||
(NULL, 'Ultimate Rules'),
|
||||
(NULL, 'Undead Kingdom'),
|
||||
(NULL, 'Unforgiven Destiny'),
|
||||
(NULL, 'Unguilded War'),
|
||||
(NULL, 'Unholy Cats'),
|
||||
(NULL, 'Unholy Teeth'),
|
||||
(NULL, 'Union of Burning Prz'),
|
||||
(NULL, 'Unusual Guard'),
|
||||
(NULL, 'Valiant Riderz'),
|
||||
(NULL, 'Vanguard Omen'),
|
||||
(NULL, 'Vanguard Redeemers'),
|
||||
(NULL, 'Vanguard of Teutonic'),
|
||||
(NULL, 'Vengeful Mayhem'),
|
||||
(NULL, 'Verata Blackflame'),
|
||||
(NULL, 'Vicious Renegade'),
|
||||
(NULL, 'Vile Dead'),
|
||||
(NULL, 'Voodoo Hearth'),
|
||||
(NULL, 'War Legion'),
|
||||
(NULL, 'Warlockian Tree'),
|
||||
(NULL, 'Warlords of Kungfu Army'),
|
||||
(NULL, 'Warriors of Happy Death'),
|
||||
(NULL, 'Warriors of the Tundra'),
|
||||
(NULL, 'Warsong Insanity'),
|
||||
(NULL, 'Waste of Grey Death'),
|
||||
(NULL, 'Wayfarers of Maple Leaf'),
|
||||
(NULL, 'Wayward Agenda'),
|
||||
(NULL, 'Web of Forgoten Warfare'),
|
||||
(NULL, 'Wet Guard'),
|
||||
(NULL, 'Wild Fire'),
|
||||
(NULL, 'Will of the Forgotten'),
|
||||
(NULL, 'Winds of Steve Irwin'),
|
||||
(NULL, 'Wings of Emerald Minions'),
|
||||
(NULL, 'Wintermane Good'),
|
||||
(NULL, 'Witchhunters of Chaos'),
|
||||
(NULL, 'With Sea'),
|
||||
(NULL, 'Wrath of the Horde Troop'),
|
||||
(NULL, 'Wtf Losers'),
|
||||
(NULL, 'Xcalibur of Shogunz Depo'),
|
||||
(NULL, 'Xelium Determination');
|
||||
10691
sql/characters/playerbots_names.sql
Normal file
10691
sql/characters/playerbots_names.sql
Normal file
File diff suppressed because it is too large
Load Diff
20
sql/playerbots/base/playerbots_custom_strategy.sql
Normal file
20
sql/playerbots/base/playerbots_custom_strategy.sql
Normal file
@ -0,0 +1,20 @@
|
||||
DROP TABLE IF EXISTS `playerbots_custom_strategy`;
|
||||
CREATE TABLE `playerbots_custom_strategy` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`idx` int(11),
|
||||
`owner` int(11),
|
||||
`action_line` varchar(1024) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
DELETE FROM `playerbots_custom_strategy`;
|
||||
INSERT INTO `playerbots_custom_strategy` VALUES
|
||||
(NULL, 'say', 1, 0, 'critical health>emote::helpme!99,say::critical health!98'),
|
||||
(NULL, 'say', 2, 0, 'low health>emote::healme!99,say::low health!98'),
|
||||
(NULL, 'say', 3, 0, 'low mana>emote::oom!99,say::low mana!98'),
|
||||
(NULL, 'say', 4, 0, 'tank aoe>charge!99,say::taunt!98'),
|
||||
(NULL, 'say', 5, 0, 'medium aoe>say::aoe!99'),
|
||||
(NULL, 'say', 6, 0, 'can loot>say::loot!99'),
|
||||
(NULL, 'say', 7, 0, 'dps assist>say::taunt!97');
|
||||
9
sql/playerbots/base/playerbots_db_store.sql
Normal file
9
sql/playerbots/base/playerbots_db_store.sql
Normal file
@ -0,0 +1,9 @@
|
||||
DROP TABLE IF EXISTS `playerbots_db_store`;
|
||||
CREATE TABLE `playerbots_db_store` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`guid` int(11) NOT NULL,
|
||||
`key` varchar(32) NOT NULL,
|
||||
`value` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `guid` (`guid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
252
sql/playerbots/base/playerbots_enchants.sql
Normal file
252
sql/playerbots/base/playerbots_enchants.sql
Normal file
@ -0,0 +1,252 @@
|
||||
-- --------------------------------------------------------
|
||||
-- Host: 127.0.0.1
|
||||
-- Server version: 5.7.21 - MySQL Community Server (GPL)
|
||||
-- Server OS: Win64
|
||||
-- HeidiSQL Verzió: 9.5.0.5338
|
||||
-- --------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
|
||||
-- Dumping data for table characters-tbc.ai_playerbot_enchants: ~220 rows (approximately)
|
||||
DROP TABLE IF EXISTS `playerbots_enchants`;
|
||||
CREATE TABLE `playerbots_enchants` (
|
||||
`class` TINYINT(3) NOT NULL,
|
||||
`spec` TINYINT(3) NOT NULL,
|
||||
`spellid` INT(11) NOT NULL,
|
||||
`slotid` TINYINT(3) DEFAULT 1,
|
||||
`name` VARCHAR(255) NOT NULL COMMENT 'name of the enchant',
|
||||
PRIMARY KEY (`class`,`spec`,`spellid`,`slotid`)
|
||||
) ENGINE=INNODB DEFAULT CHARSET=latin1;
|
||||
|
||||
/*!40000 ALTER TABLE `playerbots_enchants` DISABLE KEYS */;
|
||||
DELETE FROM `playerbots_enchants`;
|
||||
INSERT INTO `playerbots_enchants` (`class`, `spec`, `spellid`, `slotid`, `name`) VALUES
|
||||
(1, 10, 20034, 15, 'Crusader '),
|
||||
(1, 10, 22779, 17, '30 Hit '),
|
||||
(1, 10, 27927, 10, '4 All Stats '),
|
||||
(1, 10, 27927, 11, '4 All Stats '),
|
||||
(1, 10, 27960, 4, '6 All Stats '),
|
||||
(1, 10, 27984, 16, 'Mongoose '),
|
||||
(1, 10, 29483, 2, '26 Attackpower 14 Crit '),
|
||||
(1, 10, 33996, 9, '26 Attackpower '),
|
||||
(1, 10, 34002, 8, '24 Attackpower '),
|
||||
(1, 10, 34004, 14, '12 Agility '),
|
||||
(1, 10, 34007, 7, 'Minor Speed 6 Agility'),
|
||||
(1, 10, 35452, 0, '34 Attackpower 16 Hit '),
|
||||
(1, 10, 35490, 6, '50 Attackpower 12 Crit '),
|
||||
(1, 11, 20034, 15, 'Crusader '),
|
||||
(1, 11, 20034, 16, 'Crusader '),
|
||||
(1, 11, 22779, 17, '30 Hit '),
|
||||
(1, 11, 27927, 10, '4 All Stats '),
|
||||
(1, 11, 27927, 11, '4 All Stats '),
|
||||
(1, 11, 27960, 4, '6 All Stats '),
|
||||
(1, 11, 29483, 2, '26 Attackpower 14 Crit '),
|
||||
(1, 11, 33996, 9, '26 Attackpower '),
|
||||
(1, 11, 34002, 8, '24 Attackpower '),
|
||||
(1, 11, 34004, 14, '12 Agility '),
|
||||
(1, 11, 34007, 7, 'Minor Speed 6 Agility'),
|
||||
(1, 11, 35452, 0, '34 Attackpower 16 Hit '),
|
||||
(1, 11, 35490, 6, '50 Attackpower 12 Crit '),
|
||||
(1, 12, 22779, 17, '30 Hit '),
|
||||
(1, 12, 25072, 9, '2% Threat '),
|
||||
(1, 12, 27906, 8, '12 Defense '),
|
||||
(1, 12, 27927, 10, '4 All Stats '),
|
||||
(1, 12, 27927, 11, '4 All Stats '),
|
||||
(1, 12, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(1, 12, 27960, 4, '6 All Stats '),
|
||||
(1, 12, 28004, 15, 'Battlemaster '),
|
||||
(1, 12, 34009, 16, '18 Stamina '),
|
||||
(1, 12, 35433, 2, '10 Dodge 15 Defense '),
|
||||
(1, 12, 35443, 0, '16 Defense 17 Dodge '),
|
||||
(1, 12, 35495, 6, '40 Stamina 12 Agility '),
|
||||
(1, 12, 47051, 14, '12 Defense '),
|
||||
(2, 20, 22779, 17, '30 Hit '),
|
||||
(2, 20, 27926, 10, '20 Healing 7 Spelldamage '),
|
||||
(2, 20, 27926, 11, '20 Healing 7 Spelldamage '),
|
||||
(2, 20, 27945, 16, '12 Intellect '),
|
||||
(2, 20, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(2, 20, 27960, 4, '6 All Stats '),
|
||||
(2, 20, 29475, 2, '31 Healing 11 Spelldamage 5 mp5 '),
|
||||
(2, 20, 31370, 6, '66 Healing 22 Spelldamage 20 Stamina '),
|
||||
(2, 20, 33999, 9, '35 Healing 12 Spelldamage '),
|
||||
(2, 20, 34001, 8, '12 Intellect '),
|
||||
(2, 20, 34003, 14, '20 Spell Penetration '),
|
||||
(2, 20, 34010, 15, '81 Healing 27 Spelldamage '),
|
||||
(2, 20, 35445, 0, '35 Healing 12 Spelldamage 7 mp5 '),
|
||||
(2, 21, 22779, 17, '30 Hit '),
|
||||
(2, 21, 25072, 9, '2% Threat '),
|
||||
(2, 21, 27906, 8, '12 Defense '),
|
||||
(2, 21, 27927, 10, '4 All Stats '),
|
||||
(2, 21, 27927, 11, '4 All Stats '),
|
||||
(2, 21, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(2, 21, 27960, 4, '6 All Stats '),
|
||||
(2, 21, 28004, 15, 'Battlemaster '),
|
||||
(2, 21, 34009, 16, '18 Stamina '),
|
||||
(2, 21, 35433, 2, '10 Dodge 15 Defense '),
|
||||
(2, 21, 35443, 0, '16 Defense 17 Dodge '),
|
||||
(2, 21, 35495, 6, '40 Stamina 12 Agility '),
|
||||
(2, 21, 47051, 14, '12 Defense '),
|
||||
(2, 22, 20034, 15, 'Crusader '),
|
||||
(2, 22, 22779, 17, '30 Hit '),
|
||||
(2, 22, 27899, 8, '12 Strength '),
|
||||
(2, 22, 27927, 10, '4 All Stats '),
|
||||
(2, 22, 27927, 11, '4 All Stats '),
|
||||
(2, 22, 27960, 4, '6 All Stats '),
|
||||
(2, 22, 29483, 2, '26 Attackpower 14 Crit '),
|
||||
(2, 22, 33995, 6, '50 Attackpower 12 Crit '),
|
||||
(2, 22, 33996, 9, '15 Strength '),
|
||||
(2, 22, 34004, 14, '12 Agility '),
|
||||
(2, 22, 34007, 7, 'Minor Speed 6 Agility'),
|
||||
(2, 22, 37891, 0, '17 Strength16 Intellect '),
|
||||
(3, 30, 22779, 17, '30 Hit '),
|
||||
(3, 30, 25080, 9, '15 Agility '),
|
||||
(3, 30, 27927, 10, '4 All Stats '),
|
||||
(3, 30, 27927, 11, '4 All Stats '),
|
||||
(3, 30, 27951, 7, '12 Agility'),
|
||||
(3, 30, 27960, 4, '6 All Stats '),
|
||||
(3, 30, 29483, 2, '26 Attackpower 14 Crit '),
|
||||
(3, 30, 34002, 8, '24 Attackpower '),
|
||||
(3, 30, 34004, 14, '12 Agility '),
|
||||
(3, 30, 35452, 0, '34 Attackpower 16 Hit '),
|
||||
(3, 30, 35495, 6, '40 Stamina 12 Agility '),
|
||||
(3, 30, 42620, 15, 'Greater Agility '),
|
||||
(3, 30, 42620, 16, 'Greater Agility '),
|
||||
(4, 40, 22779, 17, '30 Hit '),
|
||||
(4, 40, 25080, 9, '15 Agility '),
|
||||
(4, 40, 27927, 10, '4 All Stats '),
|
||||
(4, 40, 27927, 11, '4 All Stats '),
|
||||
(4, 40, 27951, 7, '12 Agility'),
|
||||
(4, 40, 27960, 4, '6 All Stats '),
|
||||
(4, 40, 27984, 15, 'Mongoose '),
|
||||
(4, 40, 27984, 16, 'Mongoose '),
|
||||
(4, 40, 29483, 2, '26 Attackpower 14 Crit '),
|
||||
(4, 40, 34002, 8, '24 Attackpower '),
|
||||
(4, 40, 34004, 14, '12 Agility '),
|
||||
(4, 40, 35452, 0, '34 Attackpower 16 Hit '),
|
||||
(4, 40, 35495, 6, '40 Stamina 12 Agility '),
|
||||
(5, 50, 22779, 17, '30 Hit '),
|
||||
(5, 50, 27926, 10, '20 Healing 7 Spelldamage '),
|
||||
(5, 50, 27926, 11, '20 Healing 7 Spelldamage '),
|
||||
(5, 50, 27945, 16, '12 Intellect '),
|
||||
(5, 50, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(5, 50, 27960, 4, '6 All Stats '),
|
||||
(5, 50, 29475, 2, '31 Healing 11 Spelldamage 5 mp5 '),
|
||||
(5, 50, 31370, 6, '66 Healing 22 Spelldamage 20 Stamina '),
|
||||
(5, 50, 33999, 9, '35 Healing 12 Spelldamage '),
|
||||
(5, 50, 34001, 8, '12 Intellect '),
|
||||
(5, 50, 34003, 14, '20 Spell Penetration '),
|
||||
(5, 50, 34010, 15, '81 Healing 27 Spelldamage '),
|
||||
(5, 50, 35445, 0, '35 Healing 12 Spelldamage 7 mp5 '),
|
||||
(7, 70, 22779, 17, '30 Hit '),
|
||||
(7, 70, 27926, 10, '20 Healing 7 Spelldamage '),
|
||||
(7, 70, 27926, 11, '20 Healing 7 Spelldamage '),
|
||||
(7, 70, 27945, 16, '12 Intellect '),
|
||||
(7, 70, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(7, 70, 27960, 4, '6 All Stats '),
|
||||
(7, 70, 31370, 6, '66 Healing 22 Spelldamage 20 Stamina '),
|
||||
(7, 70, 33994, 9, '15 Spell Hit '),
|
||||
(7, 70, 34001, 8, '12 Intellect '),
|
||||
(7, 70, 34003, 14, '20 Spell Penetration '),
|
||||
(7, 70, 34010, 15, '81 Healing 27 Spelldamage '),
|
||||
(7, 70, 35406, 2, '18 Spelldamage 10 Crit '),
|
||||
(7, 70, 35447, 0, '22 Spelldamage 14 Hit '),
|
||||
(7, 71, 22779, 17, '30 Hit '),
|
||||
(7, 71, 25080, 9, '15 Agility '),
|
||||
(7, 71, 27927, 10, '4 All Stats '),
|
||||
(7, 71, 27927, 11, '4 All Stats '),
|
||||
(7, 71, 27951, 7, '12 Agility'),
|
||||
(7, 71, 27960, 4, '6 All Stats '),
|
||||
(7, 71, 27977, 15, '35 Agility '),
|
||||
(7, 71, 27984, 16, 'Mongoose '),
|
||||
(7, 71, 29483, 2, '26 Attackpower 14 Crit '),
|
||||
(7, 71, 34002, 8, '24 Attackpower '),
|
||||
(7, 71, 34004, 14, '12 Agility '),
|
||||
(7, 71, 35452, 0, '34 Attackpower 16 Hit '),
|
||||
(7, 71, 35495, 6, '40 Stamina 12 Agility '),
|
||||
(7, 72, 22779, 17, '30 Hit '),
|
||||
(7, 72, 27926, 10, '20 Healing 7 Spelldamage '),
|
||||
(7, 72, 27926, 11, '20 Healing 7 Spelldamage '),
|
||||
(7, 72, 27945, 16, '12 Intellect '),
|
||||
(7, 72, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(7, 72, 27960, 4, '6 All Stats '),
|
||||
(7, 72, 29475, 2, '31 Healing 11 Spelldamage 5 mp5 '),
|
||||
(7, 72, 31370, 6, '66 Healing 22 Spelldamage 20 Stamina '),
|
||||
(7, 72, 33999, 9, '35 Healing 12 Spelldamage '),
|
||||
(7, 72, 34001, 8, '12 Intellect '),
|
||||
(7, 72, 34003, 14, '20 Spell Penetration '),
|
||||
(7, 72, 34010, 15, '81 Healing 27 Spelldamage '),
|
||||
(7, 72, 35445, 0, '35 Healing 12 Spelldamage 7 mp5 '),
|
||||
(8, 80, 22779, 17, '30 Hit '),
|
||||
(8, 80, 27927, 10, '4 All Stats '),
|
||||
(8, 80, 27927, 11, '4 All Stats '),
|
||||
(8, 80, 27945, 16, '12 Intellect '),
|
||||
(8, 80, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(8, 80, 27960, 4, '6 All Stats '),
|
||||
(8, 80, 27975, 15, '40 Spelldamage '),
|
||||
(8, 80, 31372, 6, '35 Spelldamage 20 Stamina '),
|
||||
(8, 80, 33994, 9, '15 Spell Hit '),
|
||||
(8, 80, 34001, 8, '12 Intellect '),
|
||||
(8, 80, 34003, 14, '20 Spell Penetration '),
|
||||
(8, 80, 35406, 2, '18 Spelldamage 10 Crit '),
|
||||
(8, 80, 35447, 0, '22 Spelldamage 14 Hit '),
|
||||
(9, 90, 22779, 17, '30 Hit '),
|
||||
(9, 90, 27924, 11, '12 Spelldamage '),
|
||||
(9, 90, 27927, 10, '4 All Stats '),
|
||||
(9, 90, 27945, 16, '12 Intellect '),
|
||||
(9, 90, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(9, 90, 27960, 4, '6 All Stats '),
|
||||
(9, 90, 27975, 15, '40 Spelldamage '),
|
||||
(9, 90, 31372, 6, '35 Spelldamage 20 Stamina '),
|
||||
(9, 90, 33994, 9, '15 Spell Hit '),
|
||||
(9, 90, 34001, 8, '12 Intellect '),
|
||||
(9, 90, 34003, 14, '20 Spell Penetration '),
|
||||
(9, 90, 35406, 2, '18 Spelldamage 10 Crit '),
|
||||
(9, 90, 35447, 0, '22 Spelldamage 14 Hit '),
|
||||
(11, 110, 22779, 17, '30 Hit '),
|
||||
(11, 110, 27926, 10, '20 Healing 7 Spelldamage '),
|
||||
(11, 110, 27926, 11, '20 Healing 7 Spelldamage '),
|
||||
(11, 110, 27945, 16, '12 Intellect '),
|
||||
(11, 110, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(11, 110, 27960, 4, '6 All Stats '),
|
||||
(11, 110, 31370, 6, '66 Healing 22 Spelldamage 20 Stamina '),
|
||||
(11, 110, 33994, 9, '15 Spell Hit '),
|
||||
(11, 110, 34001, 8, '12 Intellect '),
|
||||
(11, 110, 34003, 14, '20 Spell Penetration '),
|
||||
(11, 110, 34010, 15, '81 Healing 27 Spelldamage '),
|
||||
(11, 110, 35406, 2, '18 Spelldamage 10 Crit '),
|
||||
(11, 110, 35447, 0, '22 Spelldamage 14 Hit '),
|
||||
(11, 111, 22779, 17, '30 Hit '),
|
||||
(11, 111, 25080, 9, '15 Agility '),
|
||||
(11, 111, 27927, 10, '4 All Stats '),
|
||||
(11, 111, 27927, 11, '4 All Stats '),
|
||||
(11, 111, 27951, 7, '12 Agility'),
|
||||
(11, 111, 27960, 4, '6 All Stats '),
|
||||
(11, 111, 29483, 2, '26 Attackpower 14 Crit '),
|
||||
(11, 111, 34002, 8, '24 Attackpower '),
|
||||
(11, 111, 34004, 14, '12 Agility '),
|
||||
(11, 111, 35452, 0, '34 Attackpower 16 Hit '),
|
||||
(11, 111, 35495, 6, '40 Stamina 12 Agility '),
|
||||
(11, 111, 42620, 15, 'Greater Agility '),
|
||||
(11, 111, 42620, 16, 'Greater Agility '),
|
||||
(11, 112, 22779, 17, '30 Hit '),
|
||||
(11, 112, 27926, 10, '20 Healing 7 Spelldamage '),
|
||||
(11, 112, 27926, 11, '20 Healing 7 Spelldamage '),
|
||||
(11, 112, 27945, 16, '12 Intellect '),
|
||||
(11, 112, 27954, 7, '5% Root/Snare Resist 10 Hit'),
|
||||
(11, 112, 27960, 4, '6 All Stats '),
|
||||
(11, 112, 29475, 2, '31 Healing 11 Spelldamage 5 mp5 '),
|
||||
(11, 112, 31370, 6, '66 Healing 22 Spelldamage 20 Stamina '),
|
||||
(11, 112, 33999, 9, '35 Healing 12 Spelldamage '),
|
||||
(11, 112, 34001, 8, '12 Intellect '),
|
||||
(11, 112, 34003, 14, '20 Spell Penetration '),
|
||||
(11, 112, 34010, 15, '81 Healing 27 Spelldamage '),
|
||||
(11, 112, 35445, 0, '35 Healing 12 Spelldamage 7 mp5 ');
|
||||
/*!40000 ALTER TABLE `playerbots_enchants` ENABLE KEYS */;
|
||||
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
10
sql/playerbots/base/playerbots_equip_cache.sql
Normal file
10
sql/playerbots/base/playerbots_equip_cache.sql
Normal file
@ -0,0 +1,10 @@
|
||||
DROP TABLE IF EXISTS `playerbots_equip_cache`;
|
||||
CREATE TABLE `playerbots_equip_cache` (
|
||||
`id` INT(11) auto_increment,
|
||||
`clazz` TINYINT(3) NOT NULL,
|
||||
`lvl` INT(11) NOT NULL,
|
||||
`slot` TINYINT(8) NOT NULL,
|
||||
`quality` INT(11) NOT NULL,
|
||||
`item` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Playerbots equip Cache';
|
||||
15
sql/playerbots/base/playerbots_guild_tasks.sql
Normal file
15
sql/playerbots/base/playerbots_guild_tasks.sql
Normal file
@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS `playerbots_guild_tasks`;
|
||||
CREATE TABLE `playerbots_guild_tasks` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`owner` INT(11) NOT NULL,
|
||||
`guildid` INT(11) NOT NULL,
|
||||
`time` INT(11) NOT NULL,
|
||||
`validIn` INT(11) DEFAULT NULL,
|
||||
`type` varchar(45) DEFAULT NULL,
|
||||
`value` INT(11) DEFAULT NULL,
|
||||
`data` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `owner` (`owner`),
|
||||
KEY `guildid` (`guildid`),
|
||||
KEY `type` (`type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
45
sql/playerbots/base/playerbots_item_info_cache.sql
Normal file
45
sql/playerbots/base/playerbots_item_info_cache.sql
Normal file
@ -0,0 +1,45 @@
|
||||
DROP TABLE IF EXISTS `playerbots_item_info_cache`;
|
||||
CREATE TABLE IF NOT EXISTS `playerbots_item_info_cache` (
|
||||
`id` int(11) NOT NULL,
|
||||
`quality` int(11) DEFAULT NULL,
|
||||
`slot` int(11) DEFAULT NULL,
|
||||
`source` mediumint(8) DEFAULT NULL,
|
||||
`sourceId` mediumint(8) DEFAULT NULL,
|
||||
`team` mediumint(8) DEFAULT NULL,
|
||||
`faction` mediumint(8) DEFAULT NULL,
|
||||
`factionRepRank` mediumint(8) DEFAULT NULL,
|
||||
`minLevel` mediumint(8) DEFAULT NULL,
|
||||
`scale_1` mediumint(8) DEFAULT NULL,
|
||||
`scale_2` mediumint(8) DEFAULT NULL,
|
||||
`scale_3` mediumint(8) DEFAULT NULL,
|
||||
`scale_4` mediumint(8) DEFAULT NULL,
|
||||
`scale_5` mediumint(8) DEFAULT NULL,
|
||||
`scale_6` mediumint(8) DEFAULT NULL,
|
||||
`scale_7` mediumint(8) DEFAULT NULL,
|
||||
`scale_8` mediumint(8) DEFAULT NULL,
|
||||
`scale_9` mediumint(8) DEFAULT NULL,
|
||||
`scale_10` mediumint(8) DEFAULT NULL,
|
||||
`scale_11` mediumint(8) DEFAULT NULL,
|
||||
`scale_12` mediumint(8) DEFAULT NULL,
|
||||
`scale_13` mediumint(8) DEFAULT NULL,
|
||||
`scale_14` mediumint(8) DEFAULT NULL,
|
||||
`scale_15` mediumint(8) DEFAULT NULL,
|
||||
`scale_16` mediumint(8) DEFAULT NULL,
|
||||
`scale_17` mediumint(8) DEFAULT NULL,
|
||||
`scale_18` mediumint(8) DEFAULT NULL,
|
||||
`scale_19` mediumint(8) DEFAULT NULL,
|
||||
`scale_20` mediumint(8) DEFAULT NULL,
|
||||
`scale_21` mediumint(8) DEFAULT NULL,
|
||||
`scale_22` mediumint(8) DEFAULT NULL,
|
||||
`scale_23` mediumint(8) DEFAULT NULL,
|
||||
`scale_24` mediumint(8) DEFAULT NULL,
|
||||
`scale_25` mediumint(8) DEFAULT NULL,
|
||||
`scale_26` mediumint(8) DEFAULT NULL,
|
||||
`scale_27` mediumint(8) DEFAULT NULL,
|
||||
`scale_28` mediumint(8) DEFAULT NULL,
|
||||
`scale_29` mediumint(8) DEFAULT NULL,
|
||||
`scale_30` mediumint(8) DEFAULT NULL,
|
||||
`scale_31` mediumint(8) DEFAULT NULL,
|
||||
`scale_32` mediumint(8) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='PlayerbotAI item info Cache';
|
||||
15
sql/playerbots/base/playerbots_random_bots.sql
Normal file
15
sql/playerbots/base/playerbots_random_bots.sql
Normal file
@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS `playerbots_random_bots`;
|
||||
CREATE TABLE `playerbots_random_bots` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`owner` INT(11) NOT NULL,
|
||||
`bot` INT(11) NOT NULL,
|
||||
`time` INT(11) NOT NULL,
|
||||
`validIn` INT(11) DEFAULT NULL,
|
||||
`event` varchar(45) DEFAULT NULL,
|
||||
`value` INT(11) DEFAULT NULL,
|
||||
`data` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `owner` (`owner`),
|
||||
KEY `bot` (`bot`),
|
||||
KEY `event` (`event`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
7
sql/playerbots/base/playerbots_rarity_cache.sql
Normal file
7
sql/playerbots/base/playerbots_rarity_cache.sql
Normal file
@ -0,0 +1,7 @@
|
||||
DROP TABLE IF EXISTS `playerbots_rarity_cache`;
|
||||
CREATE TABLE `playerbots_rarity_cache` (
|
||||
`id` INT(11) auto_increment,
|
||||
`item` INT(11) NOT NULL,
|
||||
`rarity` float NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Playerbots Rarity Cache';
|
||||
8
sql/playerbots/base/playerbots_rnditem_cache.sql
Normal file
8
sql/playerbots/base/playerbots_rnditem_cache.sql
Normal file
@ -0,0 +1,8 @@
|
||||
DROP TABLE IF EXISTS `playerbots_rnditem_cache`;
|
||||
CREATE TABLE `playerbots_rnditem_cache` (
|
||||
`id` INT(11) auto_increment,
|
||||
`lvl` INT(11) NOT NULL,
|
||||
`type` INT(11) NOT NULL,
|
||||
`item` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Playerbots Random Item Cache';
|
||||
236
sql/playerbots/base/playerbots_speech.sql
Normal file
236
sql/playerbots/base/playerbots_speech.sql
Normal file
@ -0,0 +1,236 @@
|
||||
DROP TABLE IF EXISTS `playerbots_speech`;
|
||||
CREATE TABLE `playerbots_speech` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`text` varchar(1024) NOT NULL,
|
||||
`type` varchar(10) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
INSERT INTO `playerbots_speech` VALUES
|
||||
(NULL, 'taunt', 'I have puppies under my armor!', 'say'),
|
||||
(NULL, 'taunt', 'Bite me, <target>!', 'say'),
|
||||
(NULL, 'taunt', 'Hey <target>! Guess what your mom said last night!', 'say'),
|
||||
(NULL, 'taunt', '<target>, you''re so ugly you couldn''t score in a monkey whorehouse with a bag of bananas!', 'say'),
|
||||
(NULL, 'taunt', 'Shut up <target>, you''ll never be the man your mother is!!', 'say'),
|
||||
(NULL, 'taunt', 'Your mother was a hampster and your father smelt of elderberries!!!!', 'say'),
|
||||
(NULL, 'taunt', 'I don''t want to talk to you no more, you empty headed animal food trough wiper!!!', 'say'),
|
||||
(NULL, 'taunt', 'I fart in your general direction!!!', 'say'),
|
||||
(NULL, 'taunt', 'Go and boil your bottom, you son of a silly person!!!', 'say'),
|
||||
(NULL, 'taunt', 'What are you going to do <target>, bleed on me? HAVE AT YOU!', 'say'),
|
||||
(NULL, 'taunt', 'M-O-O-N! That spells aggro!', 'say'),
|
||||
(NULL, 'taunt', 'You''re about as useful as a one-legged man in an ass kicking contest.', 'say'),
|
||||
(NULL, 'taunt', 'Hey <target>! Stop hitting on them, they''re not your type. They aren''t inflatable.', 'say'),
|
||||
(NULL, 'taunt', '<target> you''re so far outta your league, you''re playing a different sport.', 'say'),
|
||||
(NULL, 'taunt', 'You made a big mistake today <target>, you got out of bed.', 'say'),
|
||||
(NULL, 'taunt', 'I wanna try turning into a horse, but I need help. I''ll be the front, you be yourself.', 'say'),
|
||||
(NULL, 'taunt', 'Can I borrow your face for a few days? My ass is going on holiday....', 'say'),
|
||||
(NULL, 'taunt', 'I''d like to give you a going away present... First you do your part.', 'say'),
|
||||
(NULL, 'taunt', 'Before you came along we were hungry, Now we''re just fed up.', 'say'),
|
||||
(NULL, 'taunt', 'I like you. People say I have no taste, but I like you.', 'say'),
|
||||
(NULL, 'taunt', 'I think you have an inferiority complex, but that''s okay, it''s justified.', 'say'),
|
||||
(NULL, 'taunt', 'Hence rotten thing! Or I shall shake thy bones out of thy garments.', 'say'),
|
||||
(NULL, 'taunt', 'I can''t believe I''m wasting my time with you!', 'say'),
|
||||
(NULL, 'taunt', 'I love it when someone insults me, it means I don''t have to be nice anymore.', 'say'),
|
||||
(NULL, 'taunt', 'Thou leathern-jerkin, crystal-button, knot-pated, agatering, puke-stocking, caddis-garter, smooth-tongue, Spanish pouch!', 'say'),
|
||||
(NULL, 'taunt', 'Thou qualling bat-fowling malt-worm!', 'say'),
|
||||
(NULL, 'taunt', 'Thou art truely an idol of idiot-worshippers!', 'say'),
|
||||
(NULL, 'taunt', 'Thou misbegotten knotty-pated wagtail!', 'say'),
|
||||
(NULL, 'taunt', 'Thou whoreson mandrake, thou art fitter to be worn in my cap than to wait at my heels!', 'say'),
|
||||
(NULL, 'taunt', 'You! You scullion! You rampallian! You fustilarian! I''ll tickle your catastrophe!', 'say'),
|
||||
(NULL, 'taunt', 'Oh <target>! Thou infectious ill-nurtured flax-wench!', 'say'),
|
||||
(NULL, 'taunt', 'We leak in your chimney, <target>!', 'say'),
|
||||
(NULL, 'taunt', 'Oh thou bootless fen-sucked canker-blossom!', 'say'),
|
||||
(NULL, 'taunt', 'Were I like thee I''d throw away myself!', 'say'),
|
||||
(NULL, 'taunt', 'O teach me <target>, how I should forget to think!', 'say'),
|
||||
(NULL, 'taunt', 'Truly thou art damned, like an ill-roasted egg, all on one side!', 'say'),
|
||||
(NULL, 'taunt', 'You starvelling, you eel-skin, you dried neat''s-tongue, you bull''s-pizzle, you stock-fish- O for breath to utter what is like thee!! -you tailor''s-yard, you sheath, you bow-case, you vile standing tuck!', 'say'),
|
||||
(NULL, 'taunt', 'Fie! Drop thee into the rotten mouth of Death!', 'say'),
|
||||
(NULL, 'taunt', '<target>, you are a fishmonger!', 'say'),
|
||||
(NULL, 'taunt', 'I shall live to knock thy brains out!', 'say'),
|
||||
(NULL, 'taunt', 'Most shallow are you, <target>!! Thou art worms-meat in respect of a good piece of flesh, indeed!!', 'say'),
|
||||
(NULL, 'taunt', 'Vile wretch! O <target>, thou odiferous hell-hated pignut!', 'say'),
|
||||
(NULL, 'taunt', '<target>! Thy kiss is as comfortless as frozen water to a starved snake!', 'say'),
|
||||
(NULL, 'taunt', 'I scorn you, scurvy companion. What, you poor, base, rascally, cheating, lack-linen mate! Away, you moldy rogue, away!', 'say'),
|
||||
(NULL, 'taunt', 'Out of my sight! Thou dost infect my eyes <target>!', 'say'),
|
||||
(NULL, 'taunt', 'PLAY TIME!!!!', 'say'),
|
||||
(NULL, 'taunt', 'None shall pass!', 'say'),
|
||||
(NULL, 'taunt', 'We''re under attack! A vast, ye swabs! Repel the invaders!', 'say'),
|
||||
(NULL, 'taunt', 'None may challenge the Brotherhood!', 'say'),
|
||||
(NULL, 'taunt', 'Foolsss...Kill the one in the dress!', 'say'),
|
||||
(NULL, 'taunt', 'I''ll feed your soul to Hakkar himself! ', 'say'),
|
||||
(NULL, 'taunt', 'Pride heralds the end of your world! Come, mortals! Face the wrath of the <randomfaction>!', 'say'),
|
||||
(NULL, 'taunt', 'All my plans have led to this!', 'say'),
|
||||
(NULL, 'taunt', 'Ahh! More lambs to the slaughter!', 'say'),
|
||||
(NULL, 'taunt', 'Another day, another glorious battle!', 'say'),
|
||||
(NULL, 'taunt', 'So, business... or pleasure?', 'say'),
|
||||
(NULL, 'taunt', 'You are not prepared!', 'say'),
|
||||
(NULL, 'taunt', 'The <randomfaction>''s final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive! ', 'say'),
|
||||
(NULL, 'taunt', 'Your death will be a painful one. ', 'say'),
|
||||
(NULL, 'taunt', 'Cry for mercy! Your meaningless lives will soon be forfeit. ', 'say'),
|
||||
(NULL, 'taunt', 'Abandon all hope! The <randomfaction> has returned to finish what was begun so many years ago. This time there will be no escape! ', 'say'),
|
||||
(NULL, 'taunt', 'Alert! You are marked for Extermination! ', 'say'),
|
||||
(NULL, 'taunt', 'The <subzone> is for guests only...', 'say'),
|
||||
(NULL, 'taunt', 'Ha ha ha! You are hopelessly outmatched!', 'say'),
|
||||
(NULL, 'taunt', 'I will crush your delusions of grandeur! ', 'say'),
|
||||
(NULL, 'taunt', 'Forgive me, for you are about to lose the game.', 'say'),
|
||||
(NULL, 'taunt', 'Struggling only makes it worse.', 'say'),
|
||||
(NULL, 'taunt', 'Vermin! Leeches! Take my blood and choke on it!', 'say'),
|
||||
(NULL, 'taunt', 'Not again... NOT AGAIN!', 'say'),
|
||||
(NULL, 'taunt', 'My blood will be the end of you!', 'say'),
|
||||
(NULL, 'taunt', 'Good, now you fight me!', 'say'),
|
||||
(NULL, 'taunt', 'Get da move on, guards! It be killin'' time!', 'say'),
|
||||
(NULL, 'taunt', 'Don''t be delayin'' your fate. Come to me now. I make your sacrifice quick.', 'say'),
|
||||
(NULL, 'taunt', 'You be dead soon enough!', 'say'),
|
||||
(NULL, 'taunt', 'Mua-ha-ha!', 'say'),
|
||||
(NULL, 'taunt', 'I be da predator! You da prey...', 'say'),
|
||||
(NULL, 'taunt', 'You gonna leave in pieces!', 'say'),
|
||||
(NULL, 'taunt', 'Death comes. Will your conscience be clear? ', 'say'),
|
||||
(NULL, 'taunt', 'Your behavior will not be tolerated.', 'say'),
|
||||
(NULL, 'taunt', 'The Menagerie is for guests only.', 'say'),
|
||||
(NULL, 'taunt', 'Hmm, unannounced visitors, Preparations must be made... ', 'say'),
|
||||
(NULL, 'taunt', 'Hostile entities detected. Threat assessment protocol active. Primary target engaged. Time minus thirty seconds to re-evaluation.', 'say'),
|
||||
(NULL, 'taunt', 'New toys? For me? I promise I won''t break them this time!', 'say'),
|
||||
(NULL, 'taunt', 'I''m ready to play!', 'say'),
|
||||
(NULL, 'taunt', 'Shhh... it will all be over soon.', 'say'),
|
||||
(NULL, 'taunt', 'Aaaaaughibbrgubugbugrguburgle!', 'say'),
|
||||
(NULL, 'taunt', 'RwlRwlRwlRwl!', 'say'),
|
||||
(NULL, 'taunt', 'You too, shall serve!', 'say'),
|
||||
(NULL, 'taunt', 'Tell me... tell me everything! Naughty secrets! I''ll rip the secrets from your flesh!', 'say'),
|
||||
(NULL, 'taunt', 'Prepare yourselves, the bells have tolled! Shelter your weak, your young and your old! Each of you shall pay the final sum! Cry for mercy; the reckoning has come!', 'say'),
|
||||
(NULL, 'taunt', 'Where in Bonzo''s brass buttons am I?', 'say'),
|
||||
(NULL, 'taunt', 'I can bear it no longer! Goblin King! Goblin King! Wherever you may be! Take this <target> far away from me!', 'say'),
|
||||
(NULL, 'taunt', 'You have thirteen hours in which to solve the labyrinth, before your baby brother becomes one of us... forever.', 'say'),
|
||||
(NULL, 'taunt', 'So, the <subzone> is a piece of cake, is it? Well, let''s see how you deal with this little slice... ', 'say'),
|
||||
(NULL, 'taunt', 'Back off, I''ll take you on, headstrong to take on anyone, I know that you are wrong, and this is not where you belong', 'say'),
|
||||
(NULL, 'taunt', 'Show me whatcha got!', 'say'),
|
||||
(NULL, 'taunt', 'To the death!', 'say'),
|
||||
(NULL, 'taunt', 'Twin blade action, for a clean close shave every time.', 'say'),
|
||||
(NULL, 'taunt', 'Bring it on!', 'say'),
|
||||
(NULL, 'taunt', 'You''re goin'' down!', 'say'),
|
||||
(NULL, 'taunt', 'Stabby stab stab!', 'say'),
|
||||
(NULL, 'taunt', 'Let''s get this over quick; time is mana.', 'say'),
|
||||
(NULL, 'taunt', 'I do not think you realise the gravity of your situation.', 'say'),
|
||||
(NULL, 'taunt', 'I will bring honor to my family and my kingdom!', 'say'),
|
||||
(NULL, 'taunt', 'Light, give me strength!', 'say'),
|
||||
(NULL, 'taunt', 'My church is the field of battle - time to worship...', 'say'),
|
||||
(NULL, 'taunt', 'I hold you in contempt...', 'say'),
|
||||
(NULL, 'taunt', 'Face the hammer of justice!', 'say'),
|
||||
(NULL, 'taunt', 'Prove your worth in the test of arms under the Light!', 'say'),
|
||||
(NULL, 'taunt', 'All must fall before the might and right of my cause, you shall be next!', 'say'),
|
||||
(NULL, 'taunt', 'Prepare to die!', 'say'),
|
||||
(NULL, 'taunt', 'The beast with me is nothing compared to the beast within...', 'say'),
|
||||
(NULL, 'taunt', 'Witness the firepower of this fully armed huntsman!', 'say');
|
||||
|
||||
|
||||
INSERT INTO `playerbots_speech` VALUES
|
||||
(NULL, 'critical health', 'Heal me! Quick!', 'yell'),
|
||||
(NULL, 'critical health', 'Almost dead! Heal me!', 'yell'),
|
||||
(NULL, 'critical health', 'Help! Heal me!', 'yell'),
|
||||
(NULL, 'critical health', 'Somebody! Heal me!', 'yell'),
|
||||
(NULL, 'critical health', 'Heal! Heal! Heal!', 'yell'),
|
||||
(NULL, 'critical health', 'I am dying! Heal! Aaaaarhg!', 'yell'),
|
||||
(NULL, 'critical health', 'Heal me!', 'yell'),
|
||||
(NULL, 'critical health', 'I will die. I will die. I will die. Heal!', 'yell'),
|
||||
(NULL, 'critical health', 'Healers, where are you? I am dying!', 'yell'),
|
||||
(NULL, 'critical health', 'Oh the pain. Heal me quick!', 'yell');
|
||||
|
||||
|
||||
INSERT INTO `playerbots_speech` VALUES
|
||||
(NULL, 'low health', 'Need heal', 'say'),
|
||||
(NULL, 'low health', 'Low health', 'say'),
|
||||
(NULL, 'low health', 'Drop a heal. Please.', 'say'),
|
||||
(NULL, 'low health', 'Could somebody drop a heal on me?', 'say'),
|
||||
(NULL, 'low health', 'Hey! Better heal me now than rez later', 'say'),
|
||||
(NULL, 'low health', 'I am sorry. Need another heal', 'say'),
|
||||
(NULL, 'low health', 'Damn mobs. Heal me please', 'say'),
|
||||
(NULL, 'low health', 'One more hit and I am done for. Heal please', 'say'),
|
||||
(NULL, 'low health', 'Are there any healers?', 'say'),
|
||||
(NULL, 'low health', 'Why do they always punch me in the face? Need heal', 'say'),
|
||||
(NULL, 'low health', 'Can anybody heal me a bit?', 'say');
|
||||
|
||||
|
||||
INSERT INTO `playerbots_speech` VALUES
|
||||
(NULL, 'low mana', 'OOM', 'say'),
|
||||
(NULL, 'low mana', 'I am out of mana', 'say'),
|
||||
(NULL, 'low mana', 'Damn I wasted all my mana on this', 'say'),
|
||||
(NULL, 'low mana', 'You should wait until I drink or regenerate my mana', 'say'),
|
||||
(NULL, 'low mana', 'Low mana', 'say'),
|
||||
(NULL, 'low mana', 'No mana. Again?', 'say'),
|
||||
(NULL, 'low mana', 'Low mana. Wanna drink', 'say'),
|
||||
(NULL, 'low mana', 'Do we have a vending machine? Out of mana again', 'say'),
|
||||
(NULL, 'low mana', 'My mana is history', 'say'),
|
||||
(NULL, 'low mana', 'I''d get some drinks next time. Out of mana', 'say'),
|
||||
(NULL, 'low mana', 'Where is my mana?', 'say');
|
||||
|
||||
INSERT INTO `playerbots_speech` VALUES
|
||||
(NULL, 'aoe', 'Oh god!', 'say'),
|
||||
(NULL, 'aoe', 'I am scared', 'say'),
|
||||
(NULL, 'aoe', 'We are done for', 'say'),
|
||||
(NULL, 'aoe', 'This is over', 'say'),
|
||||
(NULL, 'aoe', 'This ends now', 'say'),
|
||||
(NULL, 'aoe', 'Could somebody cast blizzard or something?', 'say'),
|
||||
(NULL, 'aoe', 'Damn. The tank aggroed all the mobs around', 'say'),
|
||||
(NULL, 'aoe', 'We gonna die. We gonna die. We gonna die.', 'say'),
|
||||
(NULL, 'aoe', 'Whoa! So many toys to play with', 'say'),
|
||||
(NULL, 'aoe', 'I gonna kill them all!', 'say'),
|
||||
(NULL, 'aoe', 'If the tank dies we are history', 'say'),
|
||||
(NULL, 'aoe', 'Aaaaaargh!', 'yell'),
|
||||
(NULL, 'aoe', 'LEEEEERROOOYYYYYYYYYYYY JENNKINNNSSSSSS!!!!!!!', 'yell'),
|
||||
(NULL, 'aoe', 'Right. What do we have in AOE?', 'say'),
|
||||
(NULL, 'aoe', 'This gets interesting', 'say'),
|
||||
(NULL, 'aoe', 'Cool. Get them in one place for a good flamestrike', 'say'),
|
||||
(NULL, 'aoe', 'Kill! Kill! Kill!', 'say'),
|
||||
(NULL, 'aoe', 'I think my pants are wet', 'say'),
|
||||
(NULL, 'aoe', 'We are history', 'say'),
|
||||
(NULL, 'aoe', 'I hope healers are ready. Leeeeroy!', 'say'),
|
||||
(NULL, 'aoe', 'I hope they won''t come for me', 'say'),
|
||||
(NULL, 'aoe', 'Oh no. I can''t see at this slaugther', 'say');
|
||||
|
||||
INSERT INTO `playerbots_speech` VALUES
|
||||
(NULL, 'loot', 'I hope there will be some money', 'say'),
|
||||
(NULL, 'loot', 'Loot! Loot!', 'say'),
|
||||
(NULL, 'loot', 'My precious', 'say'),
|
||||
(NULL, 'loot', 'I hope there is a shiny epic item waiting for me there', 'say'),
|
||||
(NULL, 'loot', 'I have deep pockets and bags', 'say'),
|
||||
(NULL, 'loot', 'All is mine!', 'say'),
|
||||
(NULL, 'loot', 'Hope no gray shit today', 'say'),
|
||||
(NULL, 'loot', 'This loot is MINE!', 'say'),
|
||||
(NULL, 'loot', 'Looting is disgusting but I need money', 'say'),
|
||||
(NULL, 'loot', 'Gold!', 'say'),
|
||||
(NULL, 'loot', 'OK. Let''s see what they''ve got', 'say'),
|
||||
(NULL, 'loot', 'Do not worry. I will loot eveything', 'say'),
|
||||
(NULL, 'loot', 'I am loot ninja', 'say'),
|
||||
(NULL, 'loot', 'Do I neeed to roll?', 'say'),
|
||||
(NULL, 'loot', 'Somebody explain me, where they did put all this stuff?', 'say'),
|
||||
(NULL, 'loot', 'No, I won''t loot gray shit', 'say'),
|
||||
(NULL, 'loot', 'I''m first. I''m first. I''m first.', 'say'),
|
||||
(NULL, 'loot', 'Give me your money!', 'say'),
|
||||
(NULL, 'loot', 'My pockets are empty, I need to fill them', 'say'),
|
||||
(NULL, 'loot', 'I''ve got a new bag for this', 'say'),
|
||||
(NULL, 'loot', 'I hope I won''t aggro anybody while looting', 'say'),
|
||||
(NULL, 'loot', 'Please don''t watch. I am looting', 'say'),
|
||||
(NULL, 'loot', 'Ha! You won''t get any piece of it!', 'say'),
|
||||
(NULL, 'loot', 'Looting is cool', 'say'),
|
||||
(NULL, 'loot', 'I like new gear', 'say'),
|
||||
(NULL, 'loot', 'I''l quit if there is nothing valuable again', 'say'),
|
||||
(NULL, 'loot', 'I hope it is be a pretty ring', 'say'),
|
||||
(NULL, 'loot', 'I''l rip the loot from you', 'say'),
|
||||
(NULL, 'loot', 'Everybody stay off. I''m going to loot', 'say'),
|
||||
(NULL, 'loot', 'Sweet loot', 'say'),
|
||||
(NULL, 'loot', 'The Roll God! Give me an epic today', 'say'),
|
||||
(NULL, 'loot', 'Please give me new toys', 'say'),
|
||||
(NULL, 'loot', 'I hope they carry tasties', 'say'),
|
||||
(NULL, 'loot', 'The gold is mine. I''l leave everyting, I promise', 'say'),
|
||||
(NULL, 'loot', 'No, I can''t resist', 'say'),
|
||||
(NULL, 'loot', 'I want more!', 'say');
|
||||
|
||||
INSERT INTO `playerbots_speech` VALUES
|
||||
(NULL, 'low ammo', 'I have few <ammo> left!', 'say'),
|
||||
(NULL, 'low ammo', 'I need more <ammo>!', 'say'),
|
||||
(NULL, 'low ammo', '100 <ammo> left!', 'say'),
|
||||
(NULL, 'no ammo', 'That\'s it! No <ammo>!', 'say'),
|
||||
(NULL, 'no ammo', 'And you have my bow... Oops, no <ammo>!', 'say'),
|
||||
(NULL, 'no ammo', 'Need ammo!', 'yell');
|
||||
|
||||
12
sql/playerbots/base/playerbots_speech_probability.sql
Normal file
12
sql/playerbots/base/playerbots_speech_probability.sql
Normal file
@ -0,0 +1,12 @@
|
||||
DROP TABLE IF EXISTS `playerbots_speech_probability`;
|
||||
CREATE TABLE `playerbots_speech_probability` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`probability` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `playerbots_speech_probability` VALUES
|
||||
(NULL, 'taunt', 30),
|
||||
(NULL, 'aoe', 75),
|
||||
(NULL, 'loot', 20);
|
||||
10
sql/playerbots/base/playerbots_tele_cache.sql
Normal file
10
sql/playerbots/base/playerbots_tele_cache.sql
Normal file
@ -0,0 +1,10 @@
|
||||
DROP TABLE IF EXISTS `playerbots_tele_cache`;
|
||||
CREATE TABLE `playerbots_tele_cache` (
|
||||
`id` INT(11) auto_increment,
|
||||
`level` TINYINT(3) NOT NULL,
|
||||
`map_id` mediumint(8) NOT NULL,
|
||||
`x` float(8) NOT NULL,
|
||||
`y` float(8) NOT NULL,
|
||||
`z` float(8) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Playerbots Tele Cache';
|
||||
246
sql/playerbots/base/playerbots_text.sql
Normal file
246
sql/playerbots/base/playerbots_text.sql
Normal file
@ -0,0 +1,246 @@
|
||||
DROP TABLE IF EXISTS `playerbots_text`;
|
||||
CREATE TABLE `playerbots_text` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`key` varchar(255) NOT NULL,
|
||||
`text` varchar(1024) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `playerbots_text` VALUES
|
||||
|
||||
-- %role - Healer, Tank, Frost Mage, Elemental Shaman etc
|
||||
-- %instance - name of the dungeon by bot's level
|
||||
|
||||
(NULL, 'suggest_instance', 'Anyone wants %instance?'),
|
||||
(NULL, 'suggest_instance', 'Any groups for %instance?'),
|
||||
(NULL, 'suggest_instance', 'Need help for %instance?'),
|
||||
(NULL, 'suggest_instance', 'LFD: %instance.'),
|
||||
(NULL, 'suggest_instance', 'Anyone needs %role for %instance?'),
|
||||
(NULL, 'suggest_instance', 'Missing %role for %instance?'),
|
||||
(NULL, 'suggest_instance', 'Can be a %role for %instance.'),
|
||||
(NULL, 'suggest_instance', 'Need help with %instance?'),
|
||||
(NULL, 'suggest_instance', 'Need %role help with %instance?'),
|
||||
(NULL, 'suggest_instance', 'Anyone needs gear from %instance?'),
|
||||
(NULL, 'suggest_instance', 'A little grind in %instance?'),
|
||||
(NULL, 'suggest_instance', 'WTR %instance'),
|
||||
(NULL, 'suggest_instance', 'Need help for %instance.'),
|
||||
(NULL, 'suggest_instance', 'Wanna run %instance.'),
|
||||
(NULL, 'suggest_instance', '%role looks for %instance.'),
|
||||
(NULL, 'suggest_instance', 'What about %instance?'),
|
||||
(NULL, 'suggest_instance', 'Who wants to farm %instance?'),
|
||||
(NULL, 'suggest_instance', 'Go in %instance?'),
|
||||
(NULL, 'suggest_instance', 'Looking for %instance.'),
|
||||
(NULL, 'suggest_instance', 'Need help with %instance quests?'),
|
||||
(NULL, 'suggest_instance', 'Wanna quest in %instance.'),
|
||||
(NULL, 'suggest_instance', 'Anyone with quests in %instance?'),
|
||||
(NULL, 'suggest_instance', 'Could help with quests in %instance.'),
|
||||
(NULL, 'suggest_instance', '%role: any place in group for %instance?'),
|
||||
(NULL, 'suggest_instance', 'Does anybody still run %instance this days?'),
|
||||
(NULL, 'suggest_instance', '%instance: anyone wants to take a %role?'),
|
||||
(NULL, 'suggest_instance', 'Is there any point being %role in %instance?'),
|
||||
(NULL, 'suggest_instance', 'It is really worth to go to %instance?'),
|
||||
(NULL, 'suggest_instance', 'Anybody needs more people for %instance?'),
|
||||
(NULL, 'suggest_instance', '%instance bosses drop good gear. Wanna run?'),
|
||||
(NULL, 'suggest_instance', 'What about %instance?'),
|
||||
(NULL, 'suggest_instance', 'Anybody needs %role?'),
|
||||
(NULL, 'suggest_instance', 'Anyone needs %role?'),
|
||||
(NULL, 'suggest_instance', 'Who wants %instance?'),
|
||||
(NULL, 'suggest_instance', 'Can anybody summon me at %instance?'),
|
||||
(NULL, 'suggest_instance', 'Meet me in %instance'),
|
||||
(NULL, 'suggest_instance', 'Wanna quick %instance run'),
|
||||
(NULL, 'suggest_instance', 'Wanna full %instance run'),
|
||||
(NULL, 'suggest_instance', 'How many times were you in %instance?'),
|
||||
(NULL, 'suggest_instance', 'Another %instance run?'),
|
||||
(NULL, 'suggest_instance', 'Wiped in %instance? Take me instead!'),
|
||||
(NULL, 'suggest_instance', 'Take me in %instance please.'),
|
||||
(NULL, 'suggest_instance', 'Quick %instance run?'),
|
||||
(NULL, 'suggest_instance', 'Full %instance run?'),
|
||||
(NULL, 'suggest_instance', 'Who can take %role to %instance?'),
|
||||
|
||||
-- == Quest ==
|
||||
-- %quest - random player's quest
|
||||
|
||||
(NULL, 'suggest_quest', 'Need help with %quest?'),
|
||||
(NULL, 'suggest_quest', 'Anyone wants to share %quest?'),
|
||||
(NULL, 'suggest_quest', 'Anyone doing %quest?'),
|
||||
(NULL, 'suggest_quest', 'Wanna do %quest.'),
|
||||
|
||||
-- == Trade materials (AH) ==
|
||||
-- %category - AH category to grind
|
||||
|
||||
(NULL, 'suggest_trade', 'Anyone to farm %category?'),
|
||||
(NULL, 'suggest_trade', 'Looking for help farming %category.'),
|
||||
(NULL, 'suggest_trade', 'Damn %category are so expensive!'),
|
||||
(NULL, 'suggest_trade', 'Wanna %category.'),
|
||||
(NULL, 'suggest_trade', 'Need help with %category.'),
|
||||
(NULL, 'suggest_trade', 'WTB %category.'),
|
||||
(NULL, 'suggest_trade', 'Anyone interested in %category?'),
|
||||
(NULL, 'suggest_trade', 'WTS %category.'),
|
||||
(NULL, 'suggest_trade', 'I am selling %category cheaper than AH.'),
|
||||
(NULL, 'suggest_trade', 'Who wants to farm %category?'),
|
||||
(NULL, 'suggest_trade', 'Wanna farm %category.'),
|
||||
(NULL, 'suggest_trade', 'Looking for party after %category.'),
|
||||
(NULL, 'suggest_trade', 'Any %category are appreciated.'),
|
||||
(NULL, 'suggest_trade', 'Buying anything of %category.'),
|
||||
(NULL, 'suggest_trade', 'Wow, anybody is farming %category!'),
|
||||
(NULL, 'suggest_trade', '%category are selling mad in the AH.'),
|
||||
(NULL, 'suggest_trade', 'AH is hot for %category.'),
|
||||
(NULL, 'suggest_trade', '%category are on the market.'),
|
||||
(NULL, 'suggest_trade', 'Wanna trade some %category.'),
|
||||
(NULL, 'suggest_trade', 'Need more %category.'),
|
||||
(NULL, 'suggest_trade', 'Anybody can spare some %category?'),
|
||||
(NULL, 'suggest_trade', 'Who wants %category?'),
|
||||
(NULL, 'suggest_trade', 'Some %category please?'),
|
||||
(NULL, 'suggest_trade', 'I should have got skill for %category.'),
|
||||
(NULL, 'suggest_trade', 'I am dying for %category.'),
|
||||
(NULL, 'suggest_trade', 'People are killing for %category.'),
|
||||
(NULL, 'suggest_trade', '%category is a great bargain!'),
|
||||
(NULL, 'suggest_trade', 'Everybody is mad for %category!'),
|
||||
(NULL, 'suggest_trade', 'Where is the best place to farm for %category?'),
|
||||
(NULL, 'suggest_trade', 'I am all set for %category.'),
|
||||
(NULL, 'suggest_trade', 'Is it good to sell %category?'),
|
||||
(NULL, 'suggest_trade', 'I''d probably keep all my %category with me.'),
|
||||
(NULL, 'suggest_trade', 'Need group? Maybe to farm some %category?'),
|
||||
(NULL, 'suggest_trade', 'I am still thinking about %category.'),
|
||||
(NULL, 'suggest_trade', 'I heard about %category already, but my pockets are empty.'),
|
||||
(NULL, 'suggest_trade', 'LFG for %category'),
|
||||
(NULL, 'suggest_trade', 'Would selling %category make me rich?'),
|
||||
(NULL, 'suggest_trade', 'OK. I an farming %category tomorrow.'),
|
||||
(NULL, 'suggest_trade', 'Everyone is talking about %category.'),
|
||||
(NULL, 'suggest_trade', 'I saw at least ten people farming for %category.'),
|
||||
(NULL, 'suggest_trade', 'I sold all my %category yesterday. I am completely broke!'),
|
||||
(NULL, 'suggest_trade', 'Wanna join a guild farming for %category.'),
|
||||
|
||||
-- == Reputation ==
|
||||
-- %faction - random faction name
|
||||
-- %level - random level (honored, revered, exalted)
|
||||
-- %rnd - urand(1,5)
|
||||
|
||||
(NULL, 'suggest_faction', 'Anyone farming %faction rep?'),
|
||||
(NULL, 'suggest_faction', 'Anyone help with %faction?'),
|
||||
(NULL, 'suggest_faction', 'Wanna quest for %faction.'),
|
||||
(NULL, 'suggest_faction', '%faction is the best.'),
|
||||
(NULL, 'suggest_faction', 'Need just a bit to be %level with %faction.'),
|
||||
(NULL, 'suggest_faction', 'Anyone got %level with %faction?'),
|
||||
(NULL, 'suggest_faction', 'Who wants to be %level with %faction?'),
|
||||
(NULL, 'suggest_faction', 'I''ll never be %level with %faction.'),
|
||||
(NULL, 'suggest_faction', 'Someone missing %faction rep?'),
|
||||
(NULL, 'suggest_faction', 'Could help farming %faction rep.'),
|
||||
(NULL, 'suggest_faction', 'The more rep the better. Especially with %faction.'),
|
||||
(NULL, 'suggest_faction', '%faction: need %rndK for %level.'),
|
||||
(NULL, 'suggest_faction', 'Who can share %faction quests?'),
|
||||
(NULL, 'suggest_faction', 'Any dungeons for %faction?'),
|
||||
(NULL, 'suggest_faction', 'Wanna do %faction rep grind.'),
|
||||
(NULL, 'suggest_faction', 'Let''s farm %faction rep!'),
|
||||
(NULL, 'suggest_faction', 'Farming for %faction rep.'),
|
||||
(NULL, 'suggest_faction', 'Wanna farm for %faction.'),
|
||||
(NULL, 'suggest_faction', 'Need help with %faction.'),
|
||||
(NULL, 'suggest_faction', 'Is %faction sells something useful?'),
|
||||
(NULL, 'suggest_faction', 'Are there %faction vendors?'),
|
||||
(NULL, 'suggest_faction', 'Who farms %faction?'),
|
||||
(NULL, 'suggest_faction', 'Which is the best way to farm %faction?'),
|
||||
(NULL, 'suggest_faction', 'I hate %faction rep grind.'),
|
||||
(NULL, 'suggest_faction', 'I am so tired of %faction.'),
|
||||
(NULL, 'suggest_faction', 'Go for %faction?'),
|
||||
(NULL, 'suggest_faction', 'Seems everyone is %level with %faction. Only me is late as usually.'),
|
||||
(NULL, 'suggest_faction', 'LFG for %faction rep grind?'),
|
||||
(NULL, 'suggest_faction', 'Can anobody suggest a good spot for %faction rep grind?'),
|
||||
(NULL, 'suggest_faction', 'Would %faction rep benefit me?'),
|
||||
(NULL, 'suggest_faction', 'Who would''ve thought that %faction rep will be useful after all...'),
|
||||
(NULL, 'suggest_faction', 'I wanna be exalted with all factions, starting with %faction.'),
|
||||
(NULL, 'suggest_faction', 'Is there any point to improve my rep with %faction?'),
|
||||
(NULL, 'suggest_faction', 'What is better for %faction? Quests or mob grinding?'),
|
||||
(NULL, 'suggest_faction', 'Will grind %faction rep for you. Just give me some gold.'),
|
||||
(NULL, 'suggest_faction', 'I think grinding rep with %faction would take forever.'),
|
||||
(NULL, 'suggest_faction', 'I am killing for %faction every day now but still far from %level.'),
|
||||
(NULL, 'suggest_faction', 'At %level AH deposits will decrease, right?'),
|
||||
(NULL, 'suggest_faction', 'How many exalted reps do you have?'),
|
||||
(NULL, 'suggest_faction', 'Who wants to be %level with %faction?'),
|
||||
(NULL, 'suggest_faction', 'Damn. My guild did a good %faction grind yesterday without me.'),
|
||||
(NULL, 'suggest_faction', 'Nobody wants to help me because I am %level with %faction.'),
|
||||
(NULL, 'suggest_faction', 'Please stay away from %faction.'),
|
||||
|
||||
-- == Anything ==
|
||||
-- %role - Healer, Tank, Frost Mage, Elemental Shaman etc
|
||||
-- %zone - Name of the bot zone
|
||||
|
||||
(NULL, 'suggest_something', 'Wanna party in %zone.'),
|
||||
(NULL, 'suggest_something', 'Anyone is looking for %role?'),
|
||||
(NULL, 'suggest_something', '%role is looking for quild.'),
|
||||
(NULL, 'suggest_something', 'Looking for gold.'),
|
||||
(NULL, 'suggest_something', '%role wants to join a good guild.'),
|
||||
(NULL, 'suggest_something', 'Need a friend.'),
|
||||
(NULL, 'suggest_something', 'Anyone feels alone?'),
|
||||
(NULL, 'suggest_something', 'Boring...'),
|
||||
(NULL, 'suggest_something', 'Who wants some?'),
|
||||
(NULL, 'suggest_something', 'Go get me!'),
|
||||
(NULL, 'suggest_something', 'Maybe a duel in %zone?'),
|
||||
(NULL, 'suggest_something', 'Anybody doing something?'),
|
||||
(NULL, 'suggest_something', '%zone: is anybody here?'),
|
||||
(NULL, 'suggest_something', '%zone: where is everyone?'),
|
||||
(NULL, 'suggest_something', 'Looks like I am alone in %zone.'),
|
||||
(NULL, 'suggest_something', 'Meet me in %zone.'),
|
||||
(NULL, 'suggest_something', 'Let''s quest in %zone!'),
|
||||
(NULL, 'suggest_something', '%zone is the best place to be!'),
|
||||
(NULL, 'suggest_something', 'Wanna go to %zone. Anybody with me?'),
|
||||
(NULL, 'suggest_something', 'Who wants going to %zone?'),
|
||||
(NULL, 'suggest_something', 'I don''t like %zone. Where to go?'),
|
||||
(NULL, 'suggest_something', 'Are there a good quests in %zone?'),
|
||||
(NULL, 'suggest_something', 'Where to go after %zone?'),
|
||||
(NULL, 'suggest_something', 'Who is in %zone?'),
|
||||
(NULL, 'suggest_something', 'LFG in %zone.'),
|
||||
(NULL, 'suggest_something', '%zone is the worst place to be.'),
|
||||
(NULL, 'suggest_something', 'Catch me in %zone!'),
|
||||
(NULL, 'suggest_something', 'Go for %zone!'),
|
||||
(NULL, 'suggest_something', 'Wanna quest in %zone'),
|
||||
(NULL, 'suggest_something', 'Anyone has quests in %zone?'),
|
||||
(NULL, 'suggest_something', 'Come here to %zone!'),
|
||||
(NULL, 'suggest_something', 'Seems there is no Horde in %zone'),
|
||||
(NULL, 'suggest_something', 'Seems there is no Alliance in %zone'),
|
||||
(NULL, 'suggest_something', 'I am really tired of %zone. Maybe go somewhere else?'),
|
||||
|
||||
-- == Trade ==
|
||||
-- %item - [item]xN
|
||||
(NULL, 'suggest_sell', 'WTS %item for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Who wants %item for %gold?'),
|
||||
(NULL, 'suggest_sell', 'Anyone wants %item? Only %gold.'),
|
||||
(NULL, 'suggest_sell', 'Just %gold for %item!'),
|
||||
(NULL, 'suggest_sell', 'Selling %item for %gold.'),
|
||||
(NULL, 'suggest_sell', '%item is yours just for %gold!'),
|
||||
(NULL, 'suggest_sell', 'Ridiculus price of %gold for %item!'),
|
||||
(NULL, 'suggest_sell', 'Wanna sell %item for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Who needs %item? Only %gold.'),
|
||||
(NULL, 'suggest_sell', 'Anyone needs %item for %gold?'),
|
||||
(NULL, 'suggest_sell', '%gold for %item. Less than AH!'),
|
||||
(NULL, 'suggest_sell', '%item is expensive, but I''d sell it for %gold.'),
|
||||
(NULL, 'suggest_sell', 'You''ll never find %item cheaper than %gold!'),
|
||||
(NULL, 'suggest_sell', 'Need more than %item!'),
|
||||
(NULL, 'suggest_sell', 'I have %item and need more.'),
|
||||
(NULL, 'suggest_sell', 'Have %item. Who wants to buy for %gold?'),
|
||||
(NULL, 'suggest_sell', 'Anyone WTB %item for %gold?'),
|
||||
(NULL, 'suggest_sell', 'What about %item? For %gold.'),
|
||||
(NULL, 'suggest_sell', 'Who said I am a bastard? %item for %gold is a good price.'),
|
||||
(NULL, 'suggest_sell', 'I am selling %item? Just %gold.'),
|
||||
(NULL, 'suggest_sell', 'LFG for farming. You can still buy %item I have for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Sold almost everything today. Still have %item for %gold.'),
|
||||
(NULL, 'suggest_sell', 'What use for trade chat? Of course to sell %item for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Can anyone beat the price of %gold for %item?'),
|
||||
(NULL, 'suggest_sell', 'Wanna stop trade chat? Just buy %item? For %gold!'),
|
||||
(NULL, 'suggest_sell', 'Everybody spams in trade chat. Me too - %gold for %item!'),
|
||||
(NULL, 'suggest_sell', 'Is %item any use? Just selling it for %gold.'),
|
||||
(NULL, 'suggest_sell', 'I have %item ready to sell you for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Did nothing yesterday but have got %item. Selling it for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Farmed yesterday and got %item. Anyone wtb for %gold?'),
|
||||
(NULL, 'suggest_sell', 'Bought %item yesterday. Anyone needs it for %gold?'),
|
||||
(NULL, 'suggest_sell', 'Who asked for %item? The price is the same - %gold.'),
|
||||
(NULL, 'suggest_sell', 'I sill have %item. WTB for %gold?'),
|
||||
(NULL, 'suggest_sell', 'I used to have more than %item. Now needs to sell it for %gold.'),
|
||||
(NULL, 'suggest_sell', 'I wish I have more than %item. You could buy it for %gold anyways.'),
|
||||
(NULL, 'suggest_sell', 'What use for your gold? To buy my %item for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Please spare some gold for me. You can buy %item for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Is %gold is a good price for %item?'),
|
||||
(NULL, 'suggest_sell', 'Just bought yesterday %items, but do not need it anymore. Anyone wants for %gold?'),
|
||||
(NULL, 'suggest_sell', 'I am going to post %item on the AH but you can buy it now cheaper just for %gold.'),
|
||||
(NULL, 'suggest_sell', 'Why the #!@ have I bought %item? Anyone needs it for %gold?')
|
||||
|
||||
;
|
||||
3793
sql/playerbots/base/playerbots_travelnode.sql
Normal file
3793
sql/playerbots/base/playerbots_travelnode.sql
Normal file
File diff suppressed because it is too large
Load Diff
15056
sql/playerbots/base/playerbots_travelnode_link.sql
Normal file
15056
sql/playerbots/base/playerbots_travelnode_link.sql
Normal file
File diff suppressed because it is too large
Load Diff
1405047
sql/playerbots/base/playerbots_travelnode_path.sql
Normal file
1405047
sql/playerbots/base/playerbots_travelnode_path.sql
Normal file
File diff suppressed because it is too large
Load Diff
284
sql/playerbots/base/playerbots_weightscale_data.sql
Normal file
284
sql/playerbots/base/playerbots_weightscale_data.sql
Normal file
@ -0,0 +1,284 @@
|
||||
DROP TABLE IF EXISTS `playerbots_weightscale_data`;
|
||||
CREATE TABLE IF NOT EXISTS `playerbots_weightscale_data` (
|
||||
`id` int(32) NOT NULL,
|
||||
`field` varchar(18) NOT NULL,
|
||||
`val` smallint(6) unsigned NOT NULL,
|
||||
KEY `id` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `playerbots_weightscale_data` (`id`, `field`, `val`) VALUES
|
||||
(1, 'exprtng', 100),
|
||||
(1, 'str', 82),
|
||||
(1, 'critstrkrtng', 66),
|
||||
(1, 'agi', 53),
|
||||
(1, 'armorpenrtng', 52),
|
||||
(1, 'hitrtng', 48),
|
||||
(1, 'hastertng', 36),
|
||||
(1, 'atkpwr', 31),
|
||||
(1, 'armor', 5),
|
||||
(2, 'exprtng', 100),
|
||||
(2, 'str', 82),
|
||||
(2, 'critstrkrtng', 66),
|
||||
(2, 'agi', 53),
|
||||
(2, 'armorpenrtng', 52),
|
||||
(2, 'hitrtng', 48),
|
||||
(2, 'hastertng', 36),
|
||||
(2, 'atkpwr', 31),
|
||||
(2, 'armor', 5),
|
||||
(3, 'sta', 100),
|
||||
(3, 'dodgertng', 90),
|
||||
(3, 'defrtng', 86),
|
||||
(3, 'block', 81),
|
||||
(3, 'agi', 67),
|
||||
(3, 'parryrtng', 67),
|
||||
(3, 'blockrtng', 48),
|
||||
(3, 'str', 48),
|
||||
(3, 'exprtng', 19),
|
||||
(3, 'hitrtng', 10),
|
||||
(3, 'armorpenrtng', 10),
|
||||
(3, 'critstrkrtng', 7),
|
||||
(3, 'armor', 6),
|
||||
(3, 'hastertng', 1),
|
||||
(3, 'atkpwr', 1),
|
||||
(4, 'int', 100),
|
||||
(4, 'manargn', 88),
|
||||
(4, 'splpwr', 58),
|
||||
(4, 'critstrkrtng', 46),
|
||||
(4, 'hastertng', 35),
|
||||
(5, 'sta', 100),
|
||||
(5, 'dodgertng', 94),
|
||||
(5, 'block', 86),
|
||||
(5, 'defrtng', 86),
|
||||
(5, 'exprtng', 79),
|
||||
(5, 'agi', 76),
|
||||
(5, 'parryrtng', 76),
|
||||
(5, 'hitrtng', 58),
|
||||
(5, 'blockrtng', 52),
|
||||
(5, 'str', 50),
|
||||
(5, 'armor', 6),
|
||||
(5, 'atkpwr', 6),
|
||||
(5, 'splpwr', 4),
|
||||
(5, 'critstrkrtng', 3),
|
||||
(6, 'mledps', 470),
|
||||
(6, 'hitrtng', 100),
|
||||
(6, 'str', 80),
|
||||
(6, 'exprtng', 66),
|
||||
(6, 'critstrkrtng', 40),
|
||||
(6, 'atkpwr', 34),
|
||||
(6, 'agi', 32),
|
||||
(6, 'hastertng', 30),
|
||||
(6, 'armorpenrtng', 22),
|
||||
(6, 'splpwr', 9),
|
||||
(7, 'rgddps', 213),
|
||||
(7, 'hitrtng', 100),
|
||||
(7, 'agi', 58),
|
||||
(7, 'critstrkrtng', 40),
|
||||
(7, 'int', 37),
|
||||
(7, 'atkpwr', 30),
|
||||
(7, 'armorpenrtng', 28),
|
||||
(7, 'hastertng', 21),
|
||||
(8, 'rgddps', 379),
|
||||
(8, 'hitrtng', 100),
|
||||
(8, 'agi', 74),
|
||||
(8, 'critstrkrtng', 57),
|
||||
(8, 'armorpenrtng', 40),
|
||||
(8, 'int', 39),
|
||||
(8, 'atkpwr', 32),
|
||||
(8, 'hastertng', 24),
|
||||
(9, 'rgddps', 181),
|
||||
(9, 'hitrtng', 100),
|
||||
(9, 'agi', 76),
|
||||
(9, 'critstrkrtng', 42),
|
||||
(9, 'int', 35),
|
||||
(9, 'hastertng', 31),
|
||||
(9, 'atkpwr', 29),
|
||||
(9, 'armorpenrtng', 26),
|
||||
(10, 'mledps', 170),
|
||||
(10, 'agi', 100),
|
||||
(10, 'exprtng', 87),
|
||||
(10, 'hitrtng', 83),
|
||||
(10, 'critstrkrtng', 81),
|
||||
(10, 'atkpwr', 65),
|
||||
(10, 'armorpenrtng', 65),
|
||||
(10, 'hastertng', 64),
|
||||
(10, 'str', 55),
|
||||
(11, 'mledps', 220),
|
||||
(11, 'armorpenrtng', 100),
|
||||
(11, 'agi', 100),
|
||||
(11, 'exprtng', 82),
|
||||
(11, 'hitrtng', 80),
|
||||
(11, 'critstrkrtng', 75),
|
||||
(11, 'hastertng', 73),
|
||||
(11, 'str', 55),
|
||||
(11, 'atkpwr', 50),
|
||||
(12, 'mledps', 228),
|
||||
(12, 'exprtng', 100),
|
||||
(12, 'agi', 100),
|
||||
(12, 'hitrtng', 80),
|
||||
(12, 'armorpenrtng', 75),
|
||||
(12, 'critstrkrtng', 75),
|
||||
(12, 'hastertng', 75),
|
||||
(12, 'str', 55),
|
||||
(12, 'atkpwr', 50),
|
||||
(13, 'splpwr', 100),
|
||||
(13, 'manargn', 67),
|
||||
(13, 'int', 65),
|
||||
(13, 'hastertng', 59),
|
||||
(13, 'critstrkrtng', 48),
|
||||
(13, 'spi', 22),
|
||||
(14, 'manargn', 100),
|
||||
(14, 'int', 69),
|
||||
(14, 'splpwr', 60),
|
||||
(14, 'spi', 52),
|
||||
(14, 'critstrkrtng', 38),
|
||||
(14, 'hastertng', 31),
|
||||
(15, 'hitrtng', 100),
|
||||
(15, 'shasplpwr', 76),
|
||||
(15, 'splpwr', 76),
|
||||
(15, 'critstrkrtng', 54),
|
||||
(15, 'hastertng', 50),
|
||||
(15, 'spi', 16),
|
||||
(15, 'int', 16),
|
||||
(16, 'mledps', 360),
|
||||
(16, 'armorpenrtng', 100),
|
||||
(16, 'str', 99),
|
||||
(16, 'hitrtng', 91),
|
||||
(16, 'exprtng', 90),
|
||||
(16, 'critstrkrtng', 57),
|
||||
(16, 'hastertng', 55),
|
||||
(16, 'atkpwr', 36),
|
||||
(16, 'armor', 1),
|
||||
(17, 'mledps', 337),
|
||||
(17, 'hitrtng', 100),
|
||||
(17, 'str', 97),
|
||||
(17, 'exprtng', 81),
|
||||
(17, 'armorpenrtng', 61),
|
||||
(17, 'critstrkrtng', 45),
|
||||
(17, 'atkpwr', 35),
|
||||
(17, 'hastertng', 28),
|
||||
(17, 'armor', 1),
|
||||
(18, 'mledps', 419),
|
||||
(18, 'parryrtng', 100),
|
||||
(18, 'hitrtng', 97),
|
||||
(18, 'str', 96),
|
||||
(18, 'defrtng', 85),
|
||||
(18, 'exprtng', 69),
|
||||
(18, 'dodgertng', 61),
|
||||
(18, 'agi', 61),
|
||||
(18, 'sta', 61),
|
||||
(18, 'critstrkrtng', 49),
|
||||
(18, 'atkpwr', 41),
|
||||
(18, 'armorpenrtng', 31),
|
||||
(18, 'armor', 5),
|
||||
(19, 'mledps', 209),
|
||||
(19, 'str', 100),
|
||||
(19, 'hitrtng', 66),
|
||||
(19, 'exprtng', 51),
|
||||
(19, 'hastertng', 48),
|
||||
(19, 'critstrkrtng', 45),
|
||||
(19, 'atkpwr', 34),
|
||||
(19, 'armorpenrtng', 32),
|
||||
(19, 'armor', 1),
|
||||
(20, 'hitrtng', 100),
|
||||
(20, 'splpwr', 60),
|
||||
(20, 'hastertng', 56),
|
||||
(20, 'critstrkrtng', 40),
|
||||
(20, 'int', 11),
|
||||
(21, 'mledps', 135),
|
||||
(21, 'hitrtng', 100),
|
||||
(21, 'exprtng', 84),
|
||||
(21, 'agi', 55),
|
||||
(21, 'int', 55),
|
||||
(21, 'critstrkrtng', 55),
|
||||
(21, 'hastertng', 42),
|
||||
(21, 'str', 35),
|
||||
(21, 'atkpwr', 32),
|
||||
(21, 'splpwr', 29),
|
||||
(21, 'armorpenrtng', 26),
|
||||
(22, 'manargn', 100),
|
||||
(22, 'int', 85),
|
||||
(22, 'splpwr', 77),
|
||||
(22, 'critstrkrtng', 62),
|
||||
(22, 'hastertng', 35),
|
||||
(23, 'hitrtng', 100),
|
||||
(23, 'hastertng', 54),
|
||||
(23, 'arcsplpwr', 49),
|
||||
(23, 'splpwr', 49),
|
||||
(23, 'critstrkrtng', 37),
|
||||
(23, 'int', 34),
|
||||
(23, 'frosplpwr', 24),
|
||||
(23, 'firsplpwr', 24),
|
||||
(23, 'spi', 14),
|
||||
(24, 'hitrtng', 100),
|
||||
(24, 'hastertng', 53),
|
||||
(24, 'firsplpwr', 46),
|
||||
(24, 'splpwr', 46),
|
||||
(24, 'critstrkrtng', 43),
|
||||
(24, 'frosplpwr', 23),
|
||||
(24, 'arcsplpwr', 23),
|
||||
(24, 'int', 13),
|
||||
(25, 'hitrtng', 100),
|
||||
(25, 'hastertng', 42),
|
||||
(25, 'frosplpwr', 39),
|
||||
(25, 'splpwr', 39),
|
||||
(25, 'arcsplpwr', 19),
|
||||
(25, 'firsplpwr', 19),
|
||||
(25, 'critstrkrtng', 19),
|
||||
(25, 'int', 6),
|
||||
(26, 'hitrtng', 100),
|
||||
(26, 'shasplpwr', 72),
|
||||
(26, 'splpwr', 72),
|
||||
(26, 'hastertng', 61),
|
||||
(26, 'critstrkrtng', 38),
|
||||
(26, 'firsplpwr', 36),
|
||||
(26, 'spi', 34),
|
||||
(26, 'int', 15),
|
||||
(27, 'hitrtng', 100),
|
||||
(27, 'hastertng', 50),
|
||||
(27, 'firsplpwr', 45),
|
||||
(27, 'shasplpwr', 45),
|
||||
(27, 'splpwr', 45),
|
||||
(27, 'critstrkrtng', 31),
|
||||
(27, 'spi', 29),
|
||||
(27, 'int', 13),
|
||||
(28, 'hitrtng', 100),
|
||||
(28, 'firsplpwr', 47),
|
||||
(28, 'splpwr', 47),
|
||||
(28, 'hastertng', 46),
|
||||
(28, 'spi', 26),
|
||||
(28, 'shasplpwr', 23),
|
||||
(28, 'critstrkrtng', 16),
|
||||
(28, 'int', 13),
|
||||
(29, 'hitrtng', 100),
|
||||
(29, 'splpwr', 66),
|
||||
(29, 'hastertng', 54),
|
||||
(29, 'critstrkrtng', 43),
|
||||
(29, 'spi', 22),
|
||||
(29, 'int', 22),
|
||||
(30, 'agi', 100),
|
||||
(30, 'sta', 75),
|
||||
(30, 'dodgertng', 65),
|
||||
(30, 'defrtng', 60),
|
||||
(30, 'exprtng', 16),
|
||||
(30, 'str', 10),
|
||||
(30, 'armor', 10),
|
||||
(30, 'hitrtng', 8),
|
||||
(30, 'hastertng', 5),
|
||||
(30, 'atkpwr', 4),
|
||||
(30, 'feratkpwr', 4),
|
||||
(30, 'critstrkrtng', 3),
|
||||
(31, 'splpwr', 100),
|
||||
(31, 'manargn', 73),
|
||||
(31, 'hastertng', 57),
|
||||
(31, 'int', 51),
|
||||
(31, 'spi', 32),
|
||||
(31, 'critstrkrtng', 11),
|
||||
(32, 'agi', 100),
|
||||
(32, 'armorpenrtng', 90),
|
||||
(32, 'str', 80),
|
||||
(32, 'critstrkrtng', 55),
|
||||
(32, 'exprtng', 50),
|
||||
(32, 'hitrtng', 50),
|
||||
(32, 'feratkpwr', 40),
|
||||
(32, 'atkpwr', 40),
|
||||
(32, 'hastertng', 35);
|
||||
41
sql/playerbots/base/playerbots_weightscales.sql
Normal file
41
sql/playerbots/base/playerbots_weightscales.sql
Normal file
@ -0,0 +1,41 @@
|
||||
DROP TABLE IF EXISTS `playerbots_weightscales`;
|
||||
CREATE TABLE IF NOT EXISTS `playerbots_weightscales` (
|
||||
`id` int(32) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(32) NOT NULL,
|
||||
`class` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
|
||||
|
||||
INSERT INTO `playerbots_weightscales` (`id`, `name`, `class`) VALUES
|
||||
(1, 'arms', 1),
|
||||
(2, 'fury', 1),
|
||||
(3, 'prot', 1),
|
||||
(4, 'holy', 2),
|
||||
(5, 'prot', 2),
|
||||
(6, 'retrib', 2),
|
||||
(7, 'beast', 3),
|
||||
(8, 'marks', 3),
|
||||
(9, 'surv', 3),
|
||||
(10, 'assas', 4),
|
||||
(11, 'combat', 4),
|
||||
(12, 'subtle', 4),
|
||||
(13, 'disc', 5),
|
||||
(14, 'holy', 5),
|
||||
(15, 'shadow', 5),
|
||||
(16, 'blooddps', 6),
|
||||
(17, 'frostdps', 6),
|
||||
(18, 'frosttank', 6),
|
||||
(19, 'unholydps', 6),
|
||||
(20, 'elem', 7),
|
||||
(21, 'enhance', 7),
|
||||
(22, 'resto', 7),
|
||||
(23, 'arcane', 8),
|
||||
(24, 'fire', 8),
|
||||
(25, 'frost', 8),
|
||||
(26, 'afflic', 9),
|
||||
(27, 'demo', 9),
|
||||
(28, 'destro', 9),
|
||||
(29, 'balance', 11),
|
||||
(30, 'feraltank', 11),
|
||||
(31, 'resto', 11),
|
||||
(32, 'feraldps', 11);
|
||||
31
sql/playerbots/base/updates.sql
Normal file
31
sql/playerbots/base/updates.sql
Normal file
@ -0,0 +1,31 @@
|
||||
-- --------------------------------------------------------
|
||||
-- Хост: 127.0.0.1
|
||||
-- Версия сервера: 10.6.4-MariaDB - mariadb.org binary distribution
|
||||
-- Операционная система: Win64
|
||||
-- HeidiSQL Версия: 11.3.0.6295
|
||||
-- --------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
-- Дамп структуры для таблица _acore_playerbots.updates
|
||||
DROP TABLE IF EXISTS `updates`;
|
||||
CREATE TABLE IF NOT EXISTS `updates` (
|
||||
`name` varchar(200) NOT NULL COMMENT 'filename with extension of the update.',
|
||||
`hash` char(40) DEFAULT '' COMMENT 'sha1 hash of the sql file.',
|
||||
`state` enum('RELEASED','ARCHIVED','CUSTOM') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if an update is released or archived.',
|
||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'timestamp when the query was applied.',
|
||||
`speed` INT unsigned NOT NULL DEFAULT 0 COMMENT 'time the query takes to apply in ms.',
|
||||
PRIMARY KEY (`name`) USING BTREE
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='List of all applied updates in this database.';
|
||||
|
||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;
|
||||
35
sql/playerbots/base/updates_include.sql
Normal file
35
sql/playerbots/base/updates_include.sql
Normal file
@ -0,0 +1,35 @@
|
||||
-- --------------------------------------------------------
|
||||
-- Хост: 127.0.0.1
|
||||
-- Версия сервера: 10.6.4-MariaDB - mariadb.org binary distribution
|
||||
-- Операционная система: Win64
|
||||
-- HeidiSQL Версия: 11.3.0.6295
|
||||
-- --------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
-- Дамп структуры для таблица _acore_playerbots.updates_include
|
||||
DROP TABLE IF EXISTS `updates_include`;
|
||||
CREATE TABLE IF NOT EXISTS `updates_include` (
|
||||
`path` varchar(200) NOT NULL COMMENT 'directory to include. $ means relative to the source directory.',
|
||||
`state` enum('RELEASED','ARCHIVED','CUSTOM') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if the directory contains released or archived updates.',
|
||||
PRIMARY KEY (`path`) USING BTREE
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='List of directories where we want to include sql updates.';
|
||||
|
||||
-- Дамп данных таблицы _acore_playerbots.updates_include: 3 rows
|
||||
DELETE FROM `updates_include`;
|
||||
/*!40000 ALTER TABLE `updates_include` DISABLE KEYS */;
|
||||
INSERT INTO `updates_include` (`path`, `state`) VALUES
|
||||
('$/sql/playerbots/updates', 'RELEASED'),
|
||||
('$/sql/playerbots/custom', 'CUSTOM'),
|
||||
('$/sql/playerbots/archive', 'ARCHIVED');
|
||||
/*!40000 ALTER TABLE `updates_include` ENABLE KEYS */;
|
||||
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;
|
||||
31
sql/playerbots/base/version_db_playerbots.sql
Normal file
31
sql/playerbots/base/version_db_playerbots.sql
Normal file
@ -0,0 +1,31 @@
|
||||
-- --------------------------------------------------------
|
||||
-- Хост: 127.0.0.1
|
||||
-- Версия сервера: 10.6.4-MariaDB - mariadb.org binary distribution
|
||||
-- Операционная система: Win64
|
||||
-- HeidiSQL Версия: 11.3.0.6295
|
||||
-- --------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
-- Дамп структуры для таблица _acore_playerbots.version_db_playerbots
|
||||
DROP TABLE IF EXISTS `version_db_playerbots`;
|
||||
CREATE TABLE IF NOT EXISTS `version_db_playerbots` (
|
||||
`sql_rev` varchar(100) NOT NULL,
|
||||
`required_rev` varchar(100) DEFAULT NULL,
|
||||
`date` varchar(50) DEFAULT NULL,
|
||||
PRIMARY KEY (`sql_rev`),
|
||||
KEY `required` (`required_rev`),
|
||||
CONSTRAINT `required` FOREIGN KEY (`required_rev`) REFERENCES `version_db_playerbots` (`sql_rev`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='Last applied sql update to DB';
|
||||
|
||||
/*!40000 ALTER TABLE `version_db_playerbots` ENABLE KEYS */;
|
||||
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;
|
||||
5
sql/playerbots/create/create_mysql.sql
Normal file
5
sql/playerbots/create/create_mysql.sql
Normal file
@ -0,0 +1,5 @@
|
||||
GRANT ALL PRIVILEGES ON * . * TO 'acore'@'localhost' WITH GRANT OPTION;
|
||||
|
||||
CREATE DATABASE `acore_playerbots` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_general_ci;
|
||||
|
||||
GRANT ALL PRIVILEGES ON `acore_playerbots` . * TO 'acore'@'localhost' WITH GRANT OPTION;
|
||||
9
sql/playerbots/create/drop_mysql.sql
Normal file
9
sql/playerbots/create/drop_mysql.sql
Normal file
@ -0,0 +1,9 @@
|
||||
REVOKE ALL PRIVILEGES ON * . * FROM 'acore'@'localhost';
|
||||
|
||||
REVOKE ALL PRIVILEGES ON `acore_playerbots` . * FROM 'acore'@'localhost';
|
||||
|
||||
REVOKE GRANT OPTION ON `acore_playerbots` . * FROM 'acore'@'localhost';
|
||||
|
||||
DROP USER 'acore'@'localhost';
|
||||
|
||||
DROP DATABASE IF EXISTS `acore_playerbots`;
|
||||
5
sql/playerbots/create/drop_mysql_8.sql
Normal file
5
sql/playerbots/create/drop_mysql_8.sql
Normal file
@ -0,0 +1,5 @@
|
||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'acore'@'localhost';
|
||||
|
||||
DROP USER 'acore'@'localhost';
|
||||
|
||||
DROP DATABASE IF EXISTS `acore_playerbots`;
|
||||
10
sql/playerbots/custom/README.md
Normal file
10
sql/playerbots/custom/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
This folder should contains only re-applicable sql
|
||||
|
||||
e.g:
|
||||
|
||||
- CREATE IF NOT EXISTS
|
||||
- REPLACE INTO
|
||||
- DELETE + INSERT
|
||||
- UPDATES with fixed values
|
||||
|
||||
etc.
|
||||
2
sql/playerbots/updates/README.md
Normal file
2
sql/playerbots/updates/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
Please read [this](http://www.azerothcore.org/wiki/Dealing-with-SQL-files) before adding new SQL-update files.
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
-- Put only sql data in this file (insert, update, replace into, delete etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
-- If no data, just delete this file.
|
||||
@ -1,3 +0,0 @@
|
||||
-- Put only sql data in this file (insert, update, replace into, delete etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
-- If no data, just delete this file.
|
||||
@ -1,2 +0,0 @@
|
||||
-- Put only sql structure in this file (create table if exists, delete table, alter table etc...).
|
||||
-- If you don't use this database, then delete this file.
|
||||
14
sql/world/world_charsections_dbc.sql
Normal file
14
sql/world/world_charsections_dbc.sql
Normal file
@ -0,0 +1,14 @@
|
||||
DROP TABLE IF EXISTS `charsections_dbc`;
|
||||
CREATE TABLE `charsections_dbc` (
|
||||
`Id` INT NOT NULL DEFAULT '0',
|
||||
`Race` INT NOT NULL DEFAULT '0',
|
||||
`Gender` INT NOT NULL DEFAULT '0',
|
||||
`GenType` INT NOT NULL DEFAULT '0',
|
||||
`TexturePath1` VARCHAR(100) DEFAULT NULL,
|
||||
`TexturePath2` VARCHAR(100) DEFAULT NULL,
|
||||
`TexturePath3` VARCHAR(100) DEFAULT NULL,
|
||||
`Flags` INT NOT NULL DEFAULT '0',
|
||||
`Type` INT NOT NULL DEFAULT '0',
|
||||
`Color` INT NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`) USING BTREE
|
||||
) ENGINE=MYISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC;
|
||||
9
sql/world/world_emotetextsound_dbc.sql
Normal file
9
sql/world/world_emotetextsound_dbc.sql
Normal file
@ -0,0 +1,9 @@
|
||||
DROP TABLE IF EXISTS `emotetextsound_dbc`;
|
||||
CREATE TABLE `emotetextsound_dbc` (
|
||||
`Id` INT NOT NULL DEFAULT '0',
|
||||
`EmotesTextId` INT NOT NULL DEFAULT '0',
|
||||
`RaceId` INT NOT NULL DEFAULT '0',
|
||||
`SexId` INT NOT NULL DEFAULT '0',
|
||||
`SoundId` INT NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`Id`) USING BTREE
|
||||
) ENGINE=MYISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC;
|
||||
782
sql/world/world_playerbots_rpg_races.sql
Normal file
782
sql/world/world_playerbots_rpg_races.sql
Normal file
@ -0,0 +1,782 @@
|
||||
DROP TABLE IF EXISTS `playerbots_rpg_races`;
|
||||
CREATE TABLE `playerbots_rpg_races`
|
||||
(
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`entry` int(11),
|
||||
`race` int(11),
|
||||
`minl` int(11),
|
||||
`maxl` int(11),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `entry` (`entry`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
DELETE FROM `playerbots_rpg_races`;
|
||||
|
||||
-- say
|
||||
|
||||
INSERT INTO `playerbots_rpg_races` VALUES
|
||||
--
|
||||
-- DRAENEI
|
||||
--
|
||||
-- Draenei Azumeryst Isle
|
||||
(NULL, 16553, 11, 1, 10),
|
||||
-- Draenei Bloodmyst Isle
|
||||
(NULL, 17553, 11, 10, 20),
|
||||
--
|
||||
-- HUMANS
|
||||
--
|
||||
-- Innkeeper Farley, Goldshire
|
||||
(NULL, 295, 1, 1, 10),
|
||||
-- Innkeeper Heather, Westfall
|
||||
(NULL, 8931, 1, 10, 20),
|
||||
--
|
||||
-- DWARVES & GNOMES
|
||||
--
|
||||
-- Innkeeper Belm, Kharanos
|
||||
(NULL, 1247, 3, 1, 10),
|
||||
(NULL, 1247, 7, 1, 10),
|
||||
-- Innkeeper Hearthstove, Loch Modan
|
||||
(NULL, 6734, 3, 10, 20),
|
||||
(NULL, 6734, 7, 10, 20),
|
||||
--
|
||||
-- NIGHT ELVES
|
||||
--
|
||||
-- Innkeeper Keldamyr, Dolanaar
|
||||
(NULL, 6736, 4, 1, 10),
|
||||
-- Innkeeper Shaussiy, Auberdine
|
||||
(NULL, 6737, 4, 10, 20),
|
||||
--
|
||||
-- ALLIANCE CITIES
|
||||
--
|
||||
-- Innkeeper Saelienne, Darnassus
|
||||
(NULL, 6735, 4, 10, 80), -- elves
|
||||
--
|
||||
-- Innkeeper Firebrew, Ironforge
|
||||
(NULL, 5111, 3, 10, 80), -- dwarves
|
||||
(NULL, 5111, 7, 10, 80), -- gnomes
|
||||
(NULL, 5111, 4, 10, 80), -- elves
|
||||
(NULL, 5111, 1, 10, 80), -- human
|
||||
(NULL, 5111, 11, 20, 80), -- draenei
|
||||
--
|
||||
-- Innkeeper Allison, Stormwind
|
||||
(NULL, 6740, 1, 10, 80), -- human
|
||||
(NULL, 6740, 3, 10, 80), -- dwarves
|
||||
(NULL, 6740, 4, 10, 80), -- elves
|
||||
(NULL, 6740, 7, 10, 80), -- gnomes
|
||||
(NULL, 6740, 11, 20, 80), -- draenei
|
||||
--
|
||||
-- Caregiver Breel Exodar
|
||||
(NULL, 16739, 11, 10, 80), -- draenei
|
||||
(NULL, 16739, 1, 60, 80), -- human
|
||||
(NULL, 16739, 3, 60, 80), -- dwarves
|
||||
(NULL, 16739, 4, 60, 80), -- elves
|
||||
(NULL, 16739, 7, 60, 80), -- gnomes
|
||||
--
|
||||
-- ALLIANCE CONTESTED LOCATIONS
|
||||
--
|
||||
-- Innkeeper Kimlya, Astranaar
|
||||
--
|
||||
(NULL, 6738, 4, 15, 30), -- elves
|
||||
(NULL, 6738, 11, 20, 30), -- draenei
|
||||
--
|
||||
-- Innkeeper Faralia, Stonetalon Peak
|
||||
--
|
||||
(NULL, 16458, 4, 15, 27), -- elves
|
||||
--
|
||||
-- Innkeeper Lyshaerya, Desolase
|
||||
--
|
||||
(NULL, 11103, 4, 30, 40), -- elves
|
||||
--
|
||||
-- Innkeeper Shyria, Feathermoon, Feralas
|
||||
(NULL, 7736, 4, 40, 50), -- elves
|
||||
--
|
||||
-- Falfindel Waywarder, Feralas elf camp
|
||||
(NULL, 4048, 4, 40, 50), -- elves
|
||||
--
|
||||
-- Innkeeper Helbrek, Wetlands
|
||||
--
|
||||
(NULL, 1464, 3, 20, 30), -- dwarves
|
||||
(NULL, 1464, 7, 20, 30), -- gnomes
|
||||
--
|
||||
-- Innkeeper Trelayne, Duskwood
|
||||
--
|
||||
(NULL, 6790, 1, 18, 30), -- human
|
||||
(NULL, 6790, 3, 18, 30), -- dwarves
|
||||
(NULL, 6790, 7, 18, 30), -- gnomes
|
||||
(NULL, 6790, 11, 20, 30), -- draenei
|
||||
--
|
||||
-- Innkeeper Brianna, Redridge Mountains
|
||||
--
|
||||
(NULL, 6727, 1, 15, 25), -- human
|
||||
--
|
||||
-- Innkeeper Anderson, Southshore, Hillsbrad
|
||||
(NULL, 2352, 1, 20, 30), -- human
|
||||
(NULL, 2352, 3, 20, 30), -- dwarves
|
||||
(NULL, 2352, 7, 20, 30), -- gnomes
|
||||
(NULL, 2352, 11, 20, 30), -- draenei
|
||||
--
|
||||
-- Captain Nials, Refuge Pointe, Arathi
|
||||
(NULL, 2700, 1, 30, 40), -- human
|
||||
(NULL, 2700, 3, 30, 40), -- dwarves
|
||||
(NULL, 2700, 7, 30, 40), -- gnomes
|
||||
(NULL, 2700, 4, 30, 40), -- elves
|
||||
(NULL, 2700, 11, 30, 40), -- draenei
|
||||
--
|
||||
-- Lt. Doren, Stranglethorn Vale
|
||||
(NULL, 469, 1, 30, 45), -- human
|
||||
(NULL, 469, 3, 30, 45), -- dwarves
|
||||
(NULL, 469, 4, 30, 45), -- elves
|
||||
(NULL, 469, 7, 30, 45), -- gnomes
|
||||
(NULL, 469, 11, 30, 45), -- draenei
|
||||
--
|
||||
-- Innkeeper Janene, Theramore
|
||||
(NULL, 6272, 1, 35, 45), -- human
|
||||
(NULL, 6272, 3, 35, 45), -- dwarves
|
||||
(NULL, 6272, 7, 35, 45), -- gnomes
|
||||
(NULL, 6272, 11, 35, 45), -- draenei
|
||||
--
|
||||
-- Innkeeper Prospector Ryedol, Badlands Q-giver
|
||||
(NULL, 2910, 3, 35, 45), -- dwarves
|
||||
(NULL, 2910, 7, 35, 45), -- gnomes
|
||||
--
|
||||
-- Innkeeper Thulfram, Hinterlands, Dwarven Outpost
|
||||
(NULL, 7744, 3, 40, 50), -- dwarves
|
||||
(NULL, 7744, 1, 40, 50), -- human
|
||||
(NULL, 7744, 7, 40, 50), -- gnomes
|
||||
--
|
||||
-- Loh'atu, Azshara alliance camp Q-giver 11548
|
||||
(NULL, 11548, 4, 45, 55), -- elves
|
||||
(NULL, 11548, 1, 45, 55), -- human
|
||||
(NULL, 11548, 11, 45, 55), -- draenei
|
||||
--
|
||||
-- Thadius Grimshade, Nethergarde Keep, Blasted Lands
|
||||
(NULL, 8022, 1, 45, 55), -- human
|
||||
(NULL, 8022, 3, 45, 55), -- dwarves
|
||||
(NULL, 8022, 4, 45, 55), -- elves
|
||||
(NULL, 8022, 7, 45, 55), -- gnomes
|
||||
(NULL, 8022, 11, 45, 55), -- draenei
|
||||
--
|
||||
-- Gothine the Hooded, Felwood Alliance camp
|
||||
(NULL, 9465, 4, 48, 55), -- elves
|
||||
(NULL, 9465, 1, 48, 55), -- human
|
||||
(NULL, 9465, 3, 48, 55), -- dwarves
|
||||
(NULL, 9465, 7, 48, 55), -- gnomes
|
||||
(NULL, 9465, 11, 48, 55), -- draenei
|
||||
--
|
||||
-- Muigin, Alliance Q-giver, Un'Goro
|
||||
(NULL, 9119, 1, 48, 55), -- human
|
||||
(NULL, 9119, 3, 48, 55), -- dwarves
|
||||
(NULL, 9119, 4, 48, 55), -- elves
|
||||
(NULL, 9119, 7, 48, 55), -- gnomes
|
||||
(NULL, 9119, 11, 48, 55), -- draenei
|
||||
--
|
||||
-- Alchemist Arbington, West Plaguelands, Human
|
||||
(NULL, 11056, 1, 51, 58), -- human
|
||||
(NULL, 11056, 3, 51, 58), -- dwarves
|
||||
(NULL, 11056, 4, 51, 58), -- elves
|
||||
(NULL, 11056, 7, 51, 58), -- gnomes
|
||||
(NULL, 11056, 11, 51, 58), -- draenei
|
||||
--
|
||||
-- Borgus Stourarm, Alliance Taxi, Burning Steppes
|
||||
(NULL, 2299, 1, 50, 60), -- human
|
||||
(NULL, 2299, 3, 50, 60), -- dwarves
|
||||
(NULL, 2299, 4, 50, 60), -- elves
|
||||
(NULL, 2299, 7, 50, 60), -- gnomes
|
||||
(NULL, 2299, 11, 50, 60), -- draenei
|
||||
--
|
||||
-- Marshal Bluewall, Alliance camp, Silithus
|
||||
(NULL, 17080, 1, 55, 60), -- human
|
||||
(NULL, 17080, 3, 55, 60), -- dwarves
|
||||
(NULL, 17080, 4, 55, 60), -- elves
|
||||
(NULL, 17080, 7, 55, 60), -- gnomes
|
||||
(NULL, 17080, 11, 55, 60), -- draenei
|
||||
--
|
||||
-- OUTLAND
|
||||
--
|
||||
-- Commander Duron, Dark Portal
|
||||
(NULL, 19229, 1, 58, 59), -- human
|
||||
(NULL, 19229, 3, 58, 59), -- dwarves
|
||||
(NULL, 19229, 4, 58, 59), -- elves
|
||||
(NULL, 19229, 7, 58, 59), -- gnomes
|
||||
(NULL, 19229, 11, 58, 59), -- draenei
|
||||
--
|
||||
-- Sid Limbardi, Honor Hold, Hellfire
|
||||
(NULL, 16826, 1, 58, 63), -- human
|
||||
(NULL, 16826, 3, 58, 63), -- dwarves
|
||||
(NULL, 16826, 4, 58, 63), -- elves
|
||||
(NULL, 16826, 7, 58, 63), -- gnomes
|
||||
(NULL, 16826, 11, 58, 63), -- draenei
|
||||
--
|
||||
-- Caregiver Ophera Windfury, Draenei, Hellfire
|
||||
(NULL, 18906, 1, 60, 63), -- human
|
||||
(NULL, 18906, 3, 60, 63), -- dwarves
|
||||
(NULL, 18906, 4, 60, 63), -- elves
|
||||
(NULL, 18906, 7, 60, 63), -- gnomes
|
||||
(NULL, 18906, 11, 60, 63), -- draenei
|
||||
--
|
||||
-- Caregiver Abidaar, Telredor, Zangarmarsh
|
||||
(NULL, 18251, 1, 60, 63), -- human
|
||||
(NULL, 18251, 3, 60, 63), -- dwarves
|
||||
(NULL, 18251, 4, 60, 63), -- elves
|
||||
(NULL, 18251, 7, 60, 63), -- gnomes
|
||||
(NULL, 18251, 11, 60, 63), -- draenei
|
||||
--
|
||||
-- Caregiver Kerp, Orebor, Zangarmarsh
|
||||
(NULL, 18908, 1, 61, 64), -- human
|
||||
(NULL, 18908, 3, 61, 64), -- dwarves
|
||||
(NULL, 18908, 4, 61, 64), -- elves
|
||||
(NULL, 18908, 7, 61, 64), -- gnomes
|
||||
(NULL, 18908, 11, 61, 64), -- draenei
|
||||
--
|
||||
-- Innkeeper Biribi, Terrokar
|
||||
(NULL, 19296, 1, 62, 65), -- human
|
||||
(NULL, 19296, 3, 62, 65), -- dwarves
|
||||
(NULL, 19296, 4, 62, 65), -- elves
|
||||
(NULL, 19296, 7, 62, 65), -- gnomes
|
||||
(NULL, 19296, 11, 62, 65), -- draenei
|
||||
--
|
||||
-- Caregiver Isel, Telaar, Nagrand
|
||||
(NULL, 18914, 1, 64, 67), -- human
|
||||
(NULL, 18914, 3, 64, 67), -- dwarves
|
||||
(NULL, 18914, 4, 64, 67), -- elves
|
||||
(NULL, 18914, 7, 64, 67), -- gnomes
|
||||
(NULL, 18914, 11, 64, 67), -- draenei
|
||||
--
|
||||
-- Innkeeper Shaunessy, Sylvanaar, Blade's Edge
|
||||
(NULL, 19495, 1, 65, 68), -- human
|
||||
(NULL, 19495, 3, 65, 68), -- dwarves
|
||||
(NULL, 19495, 4, 65, 68), -- elves
|
||||
(NULL, 19495, 7, 65, 68), -- gnomes
|
||||
(NULL, 19495, 11, 65, 68), -- draenei
|
||||
--
|
||||
-- Innkeeper Fizir Doc Clocktock, Blade's Edge
|
||||
(NULL, 21110, 1, 65, 68), -- human
|
||||
(NULL, 21110, 3, 65, 68), -- dwarves
|
||||
(NULL, 21110, 4, 65, 68), -- elves
|
||||
(NULL, 21110, 7, 65, 68), -- gnomes
|
||||
(NULL, 21110, 11, 65, 68), -- draenei
|
||||
--
|
||||
-- Innkeeper Dreg Cloudsweeper, Shadowmoon
|
||||
(NULL, 19352, 1, 67, 70), -- human
|
||||
(NULL, 19352, 3, 67, 70), -- dwarves
|
||||
(NULL, 19352, 4, 67, 70), -- elves
|
||||
(NULL, 19352, 7, 67, 70), -- gnomes
|
||||
(NULL, 19352, 11, 67, 70), -- draenei
|
||||
--
|
||||
-- NORTHREND
|
||||
--
|
||||
-- Isirami Fairwind, Dalaran
|
||||
(NULL, 32413, 1, 72, 80), -- human
|
||||
(NULL, 32413, 3, 72, 80), -- dwarves
|
||||
(NULL, 32413, 4, 72, 80), -- elves
|
||||
(NULL, 32413, 7, 72, 80), -- gnomes
|
||||
(NULL, 32413, 11, 72, 80), -- draenei
|
||||
--
|
||||
-- James Deacon, Valiance Keep, Borean Tundra
|
||||
(NULL, 25245, 1, 68, 72), -- human
|
||||
(NULL, 25245, 3, 68, 72), -- dwarves
|
||||
(NULL, 25245, 4, 68, 72), -- elves
|
||||
(NULL, 25245, 7, 68, 72), -- gnomes
|
||||
(NULL, 25245, 11, 68, 72), -- draenei
|
||||
--
|
||||
-- "Charlie" Northtop, Fizzcrank Airstrip, Borean Tundra
|
||||
(NULL, 26596, 1, 69, 72), -- human
|
||||
(NULL, 26596, 3, 69, 72), -- dwarves
|
||||
(NULL, 26596, 4, 69, 72), -- elves
|
||||
(NULL, 26596, 7, 69, 72), -- gnomes
|
||||
(NULL, 26596, 11, 69, 72), -- draenei
|
||||
--
|
||||
-- Innkeeper Hazel Lagras, Valgarde, Howling Fjord
|
||||
(NULL, 23731, 1, 68, 72), -- human
|
||||
(NULL, 23731, 3, 68, 72), -- dwarves
|
||||
(NULL, 23731, 4, 68, 72), -- elves
|
||||
(NULL, 23731, 7, 68, 72), -- gnomes
|
||||
(NULL, 23731, 11, 68, 72), -- draenei
|
||||
--
|
||||
-- Innkeeper Celeste Goodhutch, Westguard Keep, Howling Fjord
|
||||
(NULL, 23937, 1, 69, 72), -- human
|
||||
(NULL, 23937, 3, 69, 72), -- dwarves
|
||||
(NULL, 23937, 4, 69, 72), -- elves
|
||||
(NULL, 23937, 7, 69, 72), -- gnomes
|
||||
(NULL, 23937, 11, 69, 72), -- draenei
|
||||
--
|
||||
-- Christina Daniels, Fort Wildervar, Howling Fjord
|
||||
(NULL, 24057, 1, 70, 72), -- human
|
||||
(NULL, 24057, 3, 70, 72), -- dwarves
|
||||
(NULL, 24057, 4, 70, 72), -- elves
|
||||
(NULL, 24057, 7, 70, 72), -- gnomes
|
||||
(NULL, 24057, 11, 70, 72), -- draenei
|
||||
--
|
||||
-- Jennifer Bell, Amberpine Lodge, Grizzly Hills
|
||||
(NULL, 27066, 1, 70, 74), -- human
|
||||
(NULL, 27066, 3, 70, 74), -- dwarves
|
||||
(NULL, 27066, 4, 70, 74), -- elves
|
||||
(NULL, 27066, 7, 70, 74), -- gnomes
|
||||
(NULL, 27066, 11, 70, 74), -- draenei
|
||||
--
|
||||
-- Quartermaster McCarty, Westfall Brigade Encampment, Grizzly Hills
|
||||
(NULL, 26375, 1, 70, 74), -- human
|
||||
(NULL, 26375, 3, 70, 74), -- dwarves
|
||||
(NULL, 26375, 4, 70, 74), -- elves
|
||||
(NULL, 26375, 7, 70, 74), -- gnomes
|
||||
(NULL, 26375, 11, 70, 74), -- draenei
|
||||
--
|
||||
-- Illusia Lune, Wintergarde Keep, Dragonblight
|
||||
(NULL, 27042, 1, 71, 75), -- human
|
||||
(NULL, 27042, 3, 71, 75), -- dwarves
|
||||
(NULL, 27042, 4, 71, 75), -- elves
|
||||
(NULL, 27042, 7, 71, 75), -- gnomes
|
||||
(NULL, 27042, 11, 71, 75), -- draenei
|
||||
--
|
||||
-- Naohain, Stars' Rest, Dragonblight
|
||||
(NULL, 27052, 1, 71, 75), -- human
|
||||
(NULL, 27052, 3, 71, 75), -- dwarves
|
||||
(NULL, 27052, 4, 71, 75), -- elves
|
||||
(NULL, 27052, 7, 71, 75), -- gnomes
|
||||
(NULL, 27052, 11, 71, 75), -- draenei
|
||||
--
|
||||
-- Gunda Boldhammer, Frosthold, Storm Peaks
|
||||
(NULL, 29926, 1, 77, 80), -- human
|
||||
(NULL, 29926, 3, 77, 80), -- dwarves
|
||||
(NULL, 29926, 4, 77, 80), -- elves
|
||||
(NULL, 29926, 7, 77, 80), -- gnomes
|
||||
(NULL, 29926, 11, 77, 80), -- draenei
|
||||
--
|
||||
-- Caris Sunlance, Argent Tournament, Icecrown
|
||||
(NULL, 33970, 1, 80, 80), -- human
|
||||
(NULL, 33970, 3, 80, 80), -- dwarves
|
||||
(NULL, 33970, 4, 80, 80), -- elves
|
||||
(NULL, 33970, 7, 80, 80), -- gnomes
|
||||
(NULL, 33970, 11, 80, 80), -- draenei
|
||||
--
|
||||
-- ALLIANCE MOUNT VENDORS
|
||||
--
|
||||
-- Milli Featherwhistle, Gnome Mechanostrider merchant, Dun Morogh
|
||||
-- (NULL, 7955, 3),
|
||||
-- (NULL, 7955, 7),
|
||||
--
|
||||
-- Lelanai, Night Elf Night Saber vendor, Darnassus
|
||||
-- (NULL, 4730, 4),
|
||||
--
|
||||
-- Katie Hunter, Human Horse vendor, Elwynn Forest
|
||||
-- (NULL, 384, 1),
|
||||
--
|
||||
-- HORDE
|
||||
--
|
||||
-- ORCS & TROLLS
|
||||
--
|
||||
-- Innkeeper Grosk, Durotar
|
||||
(NULL, 6928, 2, 1, 10),
|
||||
(NULL, 6928, 8, 1, 10),
|
||||
--
|
||||
-- TAUREN
|
||||
--
|
||||
-- Innkeeper Pala, Mulgore
|
||||
(NULL, 6746, 6, 1, 10),
|
||||
--
|
||||
-- UNDEAD
|
||||
--
|
||||
-- Innkeeper Renee, Brill, Tirisfal Glades
|
||||
(NULL, 5688, 5, 1, 10),
|
||||
-- Innkeeper Bates, The Sepulcher, Silverpine Forest
|
||||
(NULL, 6739, 5, 10, 20),
|
||||
--
|
||||
-- BLOOD ELVES
|
||||
--
|
||||
-- Blood Elves Eversong Woods
|
||||
(NULL, 15397, 10, 1, 10),
|
||||
-- Blood Elves Ghostlands
|
||||
(NULL, 16542, 10, 10, 20),
|
||||
--
|
||||
-- HORDE CITIES
|
||||
--
|
||||
-- Innkeeper Gryshka, Orgrimmar
|
||||
(NULL, 6929, 2, 10, 80), -- orcs
|
||||
(NULL, 6929, 8, 10, 80), -- trolls
|
||||
(NULL, 6929, 6, 10, 80), -- tauren
|
||||
(NULL, 6929, 5, 20, 80), -- undead
|
||||
(NULL, 6929, 10, 20, 80), -- blood elves
|
||||
--
|
||||
-- Innkeeper Pala, Thunder Bluff, Mulgore
|
||||
(NULL, 6746, 6, 10, 80), -- tauren
|
||||
--
|
||||
-- Innkeeper Norman, Undercity
|
||||
(NULL, 6741, 5, 10, 80), -- undead
|
||||
(NULL, 6741, 10, 20, 80), -- blood elves
|
||||
--
|
||||
-- Innkeeper Velandra Silvermoon
|
||||
(NULL, 16618, 10, 10, 80), -- blood elves
|
||||
-- Innkeeper Jovia Silvermoon
|
||||
(NULL, 17630, 2, 60, 80), -- orcs
|
||||
(NULL, 17630, 5, 60, 80), -- undead
|
||||
(NULL, 17630, 6, 60, 80), -- tauren
|
||||
(NULL, 17630, 8, 60, 80), -- trolls
|
||||
-- Innkeeper Delaniel Silvermoon Entrance
|
||||
(NULL, 15433, 10, 5, 7), -- blood elves
|
||||
--
|
||||
-- HORDE CONTESTED LOCATIONS
|
||||
--
|
||||
-- Innkeeper Boorand Plainswind, Crossroads, Barrens
|
||||
(NULL, 3934, 2, 10, 25), -- orcs
|
||||
(NULL, 3934, 6, 10, 25), -- tauren
|
||||
(NULL, 3934, 8, 10, 25), -- trolls
|
||||
(NULL, 3934, 10, 20, 25), -- blood elves
|
||||
-- (NULL, 3934, 5, 15, 25), -- undead
|
||||
--
|
||||
-- Innkeeper Byula, Camp Taurajo, Barrens
|
||||
(NULL, 7714, 2, 10, 25), -- orcs
|
||||
(NULL, 7714, 6, 10, 25), -- tauren
|
||||
(NULL, 7714, 8, 10, 25), -- trolls
|
||||
--
|
||||
-- Innkeeper Jayka, Stonetalon, Red Rock Retreat
|
||||
(NULL, 7731, 2, 15, 27), -- orcs
|
||||
(NULL, 7731, 6, 15, 27), -- tauren
|
||||
(NULL, 7731, 8, 15, 27), -- trolls
|
||||
(NULL, 7731, 10, 20, 27), -- blood elves
|
||||
--
|
||||
-- Innkeeper Abeqwa, Thousand Needles
|
||||
(NULL, 11116, 2, 25, 35), -- orcs
|
||||
(NULL, 11116, 6, 25, 35), -- tauren
|
||||
(NULL, 11116, 8, 25, 35), -- trolls
|
||||
(NULL, 11116, 10, 25, 35), -- blood elves
|
||||
--
|
||||
-- Innkeeper Shay, Tarren Mill, Hillsbrad
|
||||
(NULL, 2388, 5, 20, 30), -- undead
|
||||
(NULL, 2388, 10, 20, 30), -- blood elves
|
||||
--
|
||||
-- Innkeeper Greul, Feralas, Horde
|
||||
(NULL, 7737, 6, 40, 50), -- tauren
|
||||
--
|
||||
-- Innkeeper Kaylisk, Splitertree, Ashenvale
|
||||
(NULL, 12196, 2, 18, 30), -- orcs
|
||||
(NULL, 12196, 8, 18, 30), -- trolls
|
||||
(NULL, 12196, 10, 20, 30), -- blood elves
|
||||
--
|
||||
-- Marukai, Zoram'gar, Ashenvale
|
||||
(NULL, 12719, 2, 18, 30), -- orcs
|
||||
(NULL, 12719, 8, 18, 30), -- trolls
|
||||
--
|
||||
-- Innkeeper Sikewa, Desolace
|
||||
(NULL, 11106, 2, 30, 40), -- orcs
|
||||
(NULL, 11106, 6, 30, 40), -- tauren
|
||||
(NULL, 11106, 8, 30, 40), -- trolls
|
||||
--
|
||||
-- Innkeeper Adegwa, Arathi, Hammerfall
|
||||
(NULL, 9501, 2, 30, 40), -- orcs
|
||||
(NULL, 9501, 5, 30, 40), -- undead
|
||||
(NULL, 9501, 6, 30, 40), -- tauren
|
||||
(NULL, 9501, 8, 30, 40), -- trolls
|
||||
(NULL, 9501, 10, 30, 40), -- blood elves
|
||||
--
|
||||
-- Innkeeper Lard, Revantusk Village , Hinterlands
|
||||
(NULL, 14731, 2, 40, 50), -- orcs
|
||||
(NULL, 14731, 5, 40, 50), -- undead
|
||||
(NULL, 14731, 6, 40, 50), -- tauren
|
||||
(NULL, 14731, 8, 40, 50), -- trolls
|
||||
(NULL, 14731, 10, 40, 50), -- blood elves
|
||||
--
|
||||
-- Innkeeper Shul'kar, Kargath Outpost, Badlands
|
||||
(NULL, 9356, 2, 35, 45), -- orcs
|
||||
(NULL, 9356, 5, 35, 45), -- undead
|
||||
(NULL, 9356, 6, 35, 45), -- tauren
|
||||
(NULL, 9356, 8, 35, 45), -- trolls
|
||||
(NULL, 9356, 10, 35, 45), -- blood elves
|
||||
--
|
||||
-- Innkeeper Karakul, Swamp of Sorrows
|
||||
(NULL, 6930, 2, 35, 45), -- orcs
|
||||
(NULL, 6930, 5, 35, 45), -- undead
|
||||
(NULL, 6930, 6, 35, 45), -- tauren
|
||||
(NULL, 6930, 8, 35, 45), -- trolls
|
||||
(NULL, 6930, 10, 35, 45), -- blood elves
|
||||
--
|
||||
-- Innkeeper Thulbek, Grom Gol, Stranglethorn Vale
|
||||
(NULL, 5814, 2, 30, 45), -- orcs
|
||||
(NULL, 5814, 5, 30, 45), -- undead
|
||||
(NULL, 5814, 6, 30, 45), -- tauren
|
||||
(NULL, 5814, 8, 30, 45), -- trolls
|
||||
(NULL, 5814, 10, 30, 45), -- blood elves
|
||||
--
|
||||
-- Overlord Mok'Morokk, Dustwallow Marsh
|
||||
(NULL, 4500, 2, 35, 45), -- orcs
|
||||
(NULL, 4500, 6, 35, 45), -- tauren
|
||||
(NULL, 4500, 8, 35, 45), -- trolls
|
||||
--
|
||||
-- Jediga, Azshara horde camp
|
||||
(NULL, 8587, 2, 45, 55), -- orcs
|
||||
(NULL, 8587, 8, 45, 55), -- trolls
|
||||
(NULL, 8587, 6, 45, 55), -- tauren
|
||||
(NULL, 8587, 10, 45, 55), -- blood elves
|
||||
--
|
||||
-- Winna Hazzard, Felwood horde camp
|
||||
(NULL, 9996, 2, 48, 55), -- orcs
|
||||
(NULL, 9996, 6, 48, 55), -- tauren
|
||||
(NULL, 9996, 8, 48, 55), -- trolls
|
||||
(NULL, 9996, 5, 48, 55), -- undead
|
||||
(NULL, 9996, 10, 48, 55), -- blood elves
|
||||
--
|
||||
-- Larion, Horde Q-giver, Un'Goro
|
||||
(NULL, 9118, 2, 48, 55), -- orcs
|
||||
(NULL, 9118, 6, 48, 55), -- tauren
|
||||
(NULL, 9118, 8, 48, 55), -- trolls
|
||||
(NULL, 9118, 5, 48, 55), -- undead
|
||||
(NULL, 9118, 10, 48, 55), -- blood elves
|
||||
--
|
||||
-- Vahgruk, Horde Taxi, Burning Steppes
|
||||
(NULL, 13177, 2, 50, 60), -- orcs
|
||||
(NULL, 13177, 5, 50, 60), -- undead
|
||||
(NULL, 13177, 6, 50, 60), -- tauren
|
||||
(NULL, 13177, 8, 50, 60), -- trolls
|
||||
(NULL, 13177, 10, 50, 60), -- blood elves
|
||||
--
|
||||
-- General Kirika, Horde camp, Silithus
|
||||
(NULL, 17079, 2, 55, 60), -- orcs
|
||||
(NULL, 17079, 5, 55, 60), -- undead
|
||||
(NULL, 17079, 6, 55, 60), -- tauren
|
||||
(NULL, 17079, 8, 55, 60), -- trolls
|
||||
(NULL, 17079, 10, 55, 60), -- blood elves
|
||||
--
|
||||
-- OUTLAND
|
||||
--
|
||||
-- Lieutenant General Orion, Dark Portal
|
||||
(NULL, 19253, 2, 58, 59), -- orcs
|
||||
(NULL, 19253, 5, 58, 59), -- undead
|
||||
(NULL, 19253, 6, 58, 59), -- tauren
|
||||
(NULL, 19253, 8, 58, 59), -- trolls
|
||||
(NULL, 19253, 10, 58, 59), -- blood elves
|
||||
--
|
||||
-- Floyd Pinkus, Thrallmar, Hellfire
|
||||
(NULL, 16602, 2, 58, 63), -- orcs
|
||||
(NULL, 16602, 5, 58, 63), -- undead
|
||||
(NULL, 16602, 6, 58, 63), -- tauren
|
||||
(NULL, 16602, 8, 58, 63), -- trolls
|
||||
(NULL, 16602, 10, 58, 63), -- blood elves
|
||||
--
|
||||
-- Innkeeper Bazil, Falcon Watch, Hellfire
|
||||
(NULL, 18905, 2, 60, 63), -- orcs
|
||||
(NULL, 18905, 5, 60, 63), -- undead
|
||||
(NULL, 18905, 6, 60, 63), -- tauren
|
||||
(NULL, 18905, 8, 60, 63), -- trolls
|
||||
(NULL, 18905, 10, 60, 63), -- blood elves
|
||||
--
|
||||
-- Innkeeper Merajit, Zabra'jin, Zangarmarsh
|
||||
(NULL, 18245, 2, 60, 64), -- orcs
|
||||
(NULL, 18245, 5, 60, 64), -- undead
|
||||
(NULL, 18245, 6, 60, 64), -- tauren
|
||||
(NULL, 18245, 8, 60, 64), -- trolls
|
||||
(NULL, 18245, 10, 60, 64), -- blood elves
|
||||
--
|
||||
-- Innkeeper Grilka, Terrokar
|
||||
(NULL, 18957, 2, 62, 65), -- orcs
|
||||
(NULL, 18957, 5, 62, 65), -- undead
|
||||
(NULL, 18957, 6, 62, 65), -- tauren
|
||||
(NULL, 18957, 8, 62, 65), -- trolls
|
||||
(NULL, 18957, 10, 62, 65), -- blood elves
|
||||
--
|
||||
-- Matron Tikkit, Garadar, Nagrand
|
||||
(NULL, 18913, 2, 62, 65), -- orcs
|
||||
(NULL, 18913, 5, 62, 65), -- undead
|
||||
(NULL, 18913, 6, 62, 65), -- tauren
|
||||
(NULL, 18913, 8, 62, 65), -- trolls
|
||||
(NULL, 18913, 10, 62, 65), -- blood elves
|
||||
--
|
||||
-- Innkeeper Matron Varah, Mok'Nathal, Blade's Edge
|
||||
(NULL, 21088, 2, 65, 68), -- orcs
|
||||
(NULL, 21088, 5, 65, 68), -- undead
|
||||
(NULL, 21088, 6, 65, 68), -- tauren
|
||||
(NULL, 21088, 8, 65, 68), -- trolls
|
||||
(NULL, 21088, 10, 65, 68), -- blood elves
|
||||
--
|
||||
-- Innkeeper Gholah, Thunderlord, Blade's Edge
|
||||
(NULL, 19470, 2, 65, 68), -- orcs
|
||||
(NULL, 19470, 5, 65, 68), -- undead
|
||||
(NULL, 19470, 6, 65, 68), -- tauren
|
||||
(NULL, 19470, 8, 65, 68), -- trolls
|
||||
(NULL, 19470, 10, 65, 68), -- blood elves
|
||||
--
|
||||
-- Innkeeper Darg Bloodclaw, Shadowmoon Village
|
||||
(NULL, 19319, 2, 67, 70), -- orcs
|
||||
(NULL, 19319, 5, 67, 70), -- undead
|
||||
(NULL, 19319, 6, 67, 70), -- tauren
|
||||
(NULL, 19319, 8, 67, 70), -- trolls
|
||||
(NULL, 19319, 10, 67, 70), -- blood elves
|
||||
--
|
||||
-- NORTHREND
|
||||
--
|
||||
-- Uda the Beast, Dalaran
|
||||
(NULL, 31557, 2, 72, 80), -- orcs
|
||||
(NULL, 31557, 5, 72, 80), -- undead
|
||||
(NULL, 31557, 6, 72, 80), -- tauren
|
||||
(NULL, 31557, 8, 72, 80), -- trolls
|
||||
(NULL, 31557, 10, 72, 80), -- blood elves
|
||||
--
|
||||
-- Williamson, Warsong Hold, Borean Tundra
|
||||
(NULL, 25278, 2, 68, 72), -- orcs
|
||||
(NULL, 25278, 5, 68, 72), -- undead
|
||||
(NULL, 25278, 6, 68, 72), -- tauren
|
||||
(NULL, 25278, 8, 68, 72), -- trolls
|
||||
(NULL, 25278, 10, 68, 72), -- blood elves
|
||||
--
|
||||
-- Pahu Frosthoof, Taunka'le Village, Borean Tundra
|
||||
(NULL, 26709, 2, 69, 72), -- orcs
|
||||
(NULL, 26709, 5, 69, 72), -- undead
|
||||
(NULL, 26709, 6, 69, 72), -- tauren
|
||||
(NULL, 26709, 8, 69, 72), -- trolls
|
||||
(NULL, 26709, 10, 69, 72), -- blood elves
|
||||
--
|
||||
-- Matron Magah, Bor'Gorok Outpost, Borean Tundra
|
||||
(NULL, 26709, 2, 70, 72), -- orcs
|
||||
(NULL, 26709, 5, 70, 72), -- undead
|
||||
(NULL, 26709, 6, 70, 72), -- tauren
|
||||
(NULL, 26709, 8, 70, 72), -- trolls
|
||||
(NULL, 26709, 10, 70, 72), -- blood elves
|
||||
--
|
||||
-- Basil Osgood, New Agamand, Howling Fjord
|
||||
(NULL, 24149, 2, 68, 72), -- orcs
|
||||
(NULL, 24149, 5, 68, 72), -- undead
|
||||
(NULL, 24149, 6, 68, 72), -- tauren
|
||||
(NULL, 24149, 8, 68, 72), -- trolls
|
||||
(NULL, 24149, 10, 68, 72), -- blood elves
|
||||
--
|
||||
-- Timothy Holland, Vengeance Landing, Howling Fjord
|
||||
(NULL, 24342, 2, 69, 72), -- orcs
|
||||
(NULL, 24342, 5, 69, 72), -- undead
|
||||
(NULL, 24342, 6, 69, 72), -- tauren
|
||||
(NULL, 24342, 8, 69, 72), -- trolls
|
||||
(NULL, 24342, 10, 69, 72), -- blood elves
|
||||
--
|
||||
-- Bori Wintertotem, Camp Winterhoof, Howling Fjord
|
||||
(NULL, 24033, 2, 70, 72), -- orcs
|
||||
(NULL, 24033, 5, 70, 72), -- undead
|
||||
(NULL, 24033, 6, 70, 72), -- tauren
|
||||
(NULL, 24033, 8, 70, 72), -- trolls
|
||||
(NULL, 24033, 10, 70, 72), -- blood elves
|
||||
--
|
||||
-- Barracks Master Rhekku, Conquest Hold, Grizzly Hills
|
||||
(NULL, 27125, 2, 70, 74), -- orcs
|
||||
(NULL, 27125, 5, 70, 74), -- undead
|
||||
(NULL, 27125, 6, 70, 74), -- tauren
|
||||
(NULL, 27125, 8, 70, 74), -- trolls
|
||||
(NULL, 27125, 10, 70, 74), -- blood elves
|
||||
--
|
||||
-- Aiyan Coldwind, Capm Onequah, Grizzly Hills
|
||||
(NULL, 26680, 2, 70, 74), -- orcs
|
||||
(NULL, 26680, 5, 70, 74), -- undead
|
||||
(NULL, 26680, 6, 70, 74), -- tauren
|
||||
(NULL, 26680, 8, 70, 74), -- trolls
|
||||
(NULL, 26680, 10, 70, 74), -- blood elves
|
||||
--
|
||||
-- Mrs. Winterby, Venomspite, Dragonblight
|
||||
(NULL, 27027, 2, 71, 75), -- orcs
|
||||
(NULL, 27027, 5, 71, 75), -- undead
|
||||
(NULL, 27027, 6, 71, 75), -- tauren
|
||||
(NULL, 27027, 8, 71, 75), -- trolls
|
||||
(NULL, 27027, 10, 71, 75), -- blood elves
|
||||
--
|
||||
-- Barracks Master Harga, Agmar's Hammer, Dragonblight
|
||||
(NULL, 26985, 2, 71, 75), -- orcs
|
||||
(NULL, 26985, 5, 71, 75), -- undead
|
||||
(NULL, 26985, 6, 71, 75), -- tauren
|
||||
(NULL, 26985, 8, 71, 75), -- trolls
|
||||
(NULL, 26985, 10, 71, 75), -- blood elves
|
||||
--
|
||||
-- Wabada Whiteflower, Camp Tunka'lo, Storm Peaks
|
||||
(NULL, 29971, 2, 77, 80), -- orcs
|
||||
(NULL, 29971, 5, 77, 80), -- undead
|
||||
(NULL, 29971, 6, 77, 80), -- tauren
|
||||
(NULL, 29971, 8, 77, 80), -- trolls
|
||||
(NULL, 29971, 10, 77, 80), -- blood elves
|
||||
--
|
||||
-- Jarin Dawnglow, Argent Tournament, Icecrown
|
||||
(NULL, 33971, 2, 80, 80), -- orcs
|
||||
(NULL, 33971, 5, 80, 80), -- undead
|
||||
(NULL, 33971, 6, 80, 80), -- tauren
|
||||
(NULL, 33971, 8, 80, 80), -- trolls
|
||||
(NULL, 33971, 10, 80, 80), -- blood elves
|
||||
--
|
||||
-- NEUTRAL AREAS
|
||||
--
|
||||
-- Innkeeper Skindle, Booty Bay 6807 (Neutral)
|
||||
(NULL, 6807, 0, 30, 45),
|
||||
-- Innkeeper Wiley, Ratchet 6791 (Neutral)
|
||||
(NULL, 6791, 2, 10, 25),
|
||||
(NULL, 6791, 8, 10, 25),
|
||||
-- Innkeeper Fizzgrimble, Tanaris 7733 (Neutral)
|
||||
(NULL, 7733, 0, 40, 50),
|
||||
-- Master Smith Burninate, Searing Gorge
|
||||
(NULL, 14624, 0, 45, 50),
|
||||
-- Marin Noggenfogger 7564 (Neutral)
|
||||
-- Innkeeper Vizzie, Everlook 11118 (Neutral)
|
||||
(NULL, 11118, 0, 53, 60),
|
||||
-- Calandrath, Silithus 15174 (Neutral)
|
||||
(NULL, 15174, 0, 55, 60),
|
||||
-- Jessica Chambers, East Plaguelands 16256 (Neutral)
|
||||
(NULL, 16256, 0, 53, 60),
|
||||
--
|
||||
-- OUTLAND
|
||||
--
|
||||
-- Innkeeper Coryth Stoktron, Cenarion Refuge (Neutral)
|
||||
(NULL, 18907, 0, 60, 64),
|
||||
-- Minalei, Aldors, Shattrath
|
||||
(NULL, 19046, 0, 65, 70),
|
||||
-- Innkeeper Haelthol, Scryers, Shattrath
|
||||
(NULL, 19232, 0, 65, 70),
|
||||
-- Shaarubo, World End Tavern
|
||||
(NULL, 19182, 0, 65, 70),
|
||||
-- Innkeeper Aelerya, Blade's Edge (Neutral)
|
||||
(NULL, 22922, 0, 65, 68),
|
||||
-- Innkeeper Eyonix, Stormspire, Netherstorm
|
||||
(NULL, 19531, 0, 67, 70),
|
||||
-- Innkeeper Remi Dodoso, Area 52, Netherstorm
|
||||
(NULL, 19571, 0, 67, 70),
|
||||
-- Caregiver Inaara, Isle if Quel'Danas
|
||||
(NULL, 25036, 0, 69, 70),
|
||||
--
|
||||
-- NORTHREND
|
||||
--
|
||||
-- Amisi Azuregaze, Dalaran Inn
|
||||
(NULL, 28687, 0, 72, 80),
|
||||
-- Afsaneh Asrar, Dalaran Underbelly
|
||||
(NULL, 32411, 0, 77, 80),
|
||||
-- Caregiver Poallu, Kaluak Camp, Borean Tundra
|
||||
(NULL, 27187, 0, 68, 72),
|
||||
-- Caregiver Iqniq, Kamagua, Howling Fjord
|
||||
(NULL, 27187, 0, 68, 72),
|
||||
-- Caregiver Mumik, Mo'Aki Harbor, Dragonblight
|
||||
(NULL, 27174, 0, 71, 73),
|
||||
-- Marissa Everwatch, The Argent Stand, Zul'Drak
|
||||
(NULL, 28791, 0, 73, 75),
|
||||
-- Pan'ya, Zim'Torga, Zul'Drak
|
||||
(NULL, 29583, 0, 75, 77),
|
||||
-- Purser Boulian, Nesingwary Base Camp, Sholazar Basin
|
||||
(NULL, 29583, 0, 75, 79),
|
||||
-- Smilin' Slirk Brassknob, K3, The Storm Peaks
|
||||
(NULL, 29904, 0, 77, 80),
|
||||
-- Magorn, Snow Drift Plains, The Storm Peaks
|
||||
(NULL, 29963, 0, 77, 80),
|
||||
-- Initiate Brenners, The Argent Stand, Zul'Drak
|
||||
-- (NULL, 30308, 0, 77, 80),
|
||||
--
|
||||
--
|
||||
-- UNUSED
|
||||
--
|
||||
--
|
||||
-- Bashana Runetotem, Thunder Bluff (Tauren npc in TB)
|
||||
-- (NULL, 9087, 6),
|
||||
--
|
||||
-- Alchemist Arbington, West Plaguelands, Human
|
||||
-- (NULL, 11056, 1),
|
||||
-- (NULL, 11056, 3),
|
||||
-- (NULL, 11056, 4),
|
||||
-- (NULL, 11056, 7),
|
||||
--
|
||||
-- Lokhtos Darkbargainer, Blackrock Depths, 12944
|
||||
--
|
||||
-- Gregan Brewspewer, Feralas, Dwarf (Some swarf Q-giver in Feralas)
|
||||
-- (NULL, 7775, 3),
|
||||
--
|
||||
-- Augustus the Touched, East Plaguelands, Undead (Some undead vendor near stratholme)
|
||||
-- (NULL, 12384, 5),
|
||||
--
|
||||
-- ENDING PLACEHOLDER
|
||||
(NULL, 6807, 15, 90, 90)
|
||||
;
|
||||
696
src/AiFactory.cpp
Normal file
696
src/AiFactory.cpp
Normal file
@ -0,0 +1,696 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "AiFactory.h"
|
||||
#include "BattlegroundMgr.h"
|
||||
#include "Playerbots.h"
|
||||
#include "Engine.h"
|
||||
#include "Group.h"
|
||||
#include "DKAiObjectContext.h"
|
||||
#include "PriestAiObjectContext.h"
|
||||
#include "MageAiObjectContext.h"
|
||||
#include "WarlockAiObjectContext.h"
|
||||
#include "WarriorAiObjectContext.h"
|
||||
#include "ShamanAiObjectContext.h"
|
||||
#include "PaladinAiObjectContext.h"
|
||||
#include "DruidAiObjectContext.h"
|
||||
#include "HunterAiObjectContext.h"
|
||||
#include "RogueAiObjectContext.h"
|
||||
|
||||
AiObjectContext* AiFactory::createAiObjectContext(Player* player, PlayerbotAI* botAI)
|
||||
{
|
||||
switch (player->getClass())
|
||||
{
|
||||
case CLASS_PRIEST:
|
||||
return new PriestAiObjectContext(botAI);
|
||||
case CLASS_MAGE:
|
||||
return new MageAiObjectContext(botAI);
|
||||
case CLASS_WARLOCK:
|
||||
return new WarlockAiObjectContext(botAI);
|
||||
case CLASS_WARRIOR:
|
||||
return new WarriorAiObjectContext(botAI);
|
||||
case CLASS_SHAMAN:
|
||||
return new ShamanAiObjectContext(botAI);
|
||||
case CLASS_PALADIN:
|
||||
return new PaladinAiObjectContext(botAI);
|
||||
case CLASS_DRUID:
|
||||
return new DruidAiObjectContext(botAI);
|
||||
case CLASS_HUNTER:
|
||||
return new HunterAiObjectContext(botAI);
|
||||
case CLASS_ROGUE:
|
||||
return new RogueAiObjectContext(botAI);
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
return new DKAiObjectContext(botAI);
|
||||
}
|
||||
|
||||
return new AiObjectContext(botAI);
|
||||
}
|
||||
|
||||
uint8 AiFactory::GetPlayerSpecTab(Player* bot)
|
||||
{
|
||||
std::map<uint8, uint32> tabs = GetPlayerSpecTabs(bot);
|
||||
|
||||
if (bot->getLevel() >= 10 && ((tabs[0] + tabs[1] + tabs[2]) > 0))
|
||||
{
|
||||
std::map<uint8, uint32> tabs = GetPlayerSpecTabs(bot);
|
||||
|
||||
int8 tab = -1;
|
||||
uint32 max = 0;
|
||||
for (uint32 i = 0; i < uint32(3); i++)
|
||||
{
|
||||
if (tab == -1 || max < tabs[i])
|
||||
{
|
||||
tab = i;
|
||||
max = tabs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 tab = 0;
|
||||
|
||||
switch (bot->getClass())
|
||||
{
|
||||
case CLASS_MAGE:
|
||||
tab = 1;
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
tab = 2;
|
||||
break;
|
||||
case CLASS_PRIEST:
|
||||
tab = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<uint8, uint32> AiFactory::GetPlayerSpecTabs(Player* bot)
|
||||
{
|
||||
std::map<uint8, uint32> tabs;
|
||||
for (uint32 i = 0; i < 3; i++)
|
||||
tabs[i] = 0;
|
||||
|
||||
uint32 classMask = bot->getClassMask();
|
||||
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
|
||||
{
|
||||
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
|
||||
if (!talentInfo)
|
||||
continue;
|
||||
|
||||
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
|
||||
if (!talentTabInfo)
|
||||
continue;
|
||||
|
||||
if ((classMask & talentTabInfo->ClassMask) == 0)
|
||||
continue;
|
||||
|
||||
uint32 maxRank = 0;
|
||||
for (int32 rank = MAX_TALENT_RANK - 1; rank >= 0; --rank)
|
||||
{
|
||||
if (!talentInfo->RankID[rank])
|
||||
continue;
|
||||
|
||||
uint32 spellid = talentInfo->RankID[rank];
|
||||
if (spellid && bot->HasSpell(spellid))
|
||||
maxRank = rank + 1;
|
||||
|
||||
}
|
||||
|
||||
tabs[talentTabInfo->tabpage] += maxRank;
|
||||
}
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
BotRoles AiFactory::GetPlayerRoles(Player* player)
|
||||
{
|
||||
BotRoles role = BOT_ROLE_NONE;
|
||||
uint8 tab = GetPlayerSpecTab(player);
|
||||
|
||||
switch (player->getClass())
|
||||
{
|
||||
case CLASS_PRIEST:
|
||||
if (tab == 2)
|
||||
role = BOT_ROLE_DPS;
|
||||
else
|
||||
role = BOT_ROLE_HEALER;
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
if (tab == 2)
|
||||
role = BOT_ROLE_HEALER;
|
||||
else
|
||||
role = BOT_ROLE_DPS;
|
||||
break;
|
||||
case CLASS_WARRIOR:
|
||||
if (tab == 2)
|
||||
role = BOT_ROLE_TANK;
|
||||
else
|
||||
role = BOT_ROLE_DPS;
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
if (tab == 0)
|
||||
role = BOT_ROLE_HEALER;
|
||||
else if (tab == 1)
|
||||
role = BOT_ROLE_TANK;
|
||||
else if (tab == 2)
|
||||
role = BOT_ROLE_DPS;
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
if (tab == 0)
|
||||
role = BOT_ROLE_DPS;
|
||||
else if (tab == 1)
|
||||
role = (BotRoles)(BOT_ROLE_TANK | BOT_ROLE_DPS);
|
||||
else if (tab == 2)
|
||||
role = BOT_ROLE_HEALER;
|
||||
break;
|
||||
default:
|
||||
role = BOT_ROLE_DPS;
|
||||
break;
|
||||
}
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
std::string AiFactory::GetPlayerSpecName(Player* player)
|
||||
{
|
||||
std::string specName;
|
||||
int tab = GetPlayerSpecTab(player);
|
||||
switch (player->getClass())
|
||||
{
|
||||
case CLASS_PRIEST:
|
||||
if (tab == 2)
|
||||
specName = "shadow";
|
||||
else if (tab == 1)
|
||||
specName = "holy";
|
||||
else
|
||||
specName = "disc";
|
||||
; break;
|
||||
case CLASS_SHAMAN:
|
||||
if (tab == 2)
|
||||
specName = "resto";
|
||||
else if (tab == 1)
|
||||
specName = "enhance";
|
||||
else
|
||||
specName = "elem";
|
||||
break;
|
||||
case CLASS_WARRIOR:
|
||||
if (tab == 2)
|
||||
specName = "prot";
|
||||
else if (tab == 1)
|
||||
specName = "fury";
|
||||
else
|
||||
specName = "arms";
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
if (tab == 0)
|
||||
specName = "holy";
|
||||
else if (tab == 1)
|
||||
specName = "prot";
|
||||
else if (tab == 2)
|
||||
specName = "retrib";
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
if (tab == 0)
|
||||
specName = "balance";
|
||||
else if (tab == 1)
|
||||
specName = "feraldps";
|
||||
else if (tab == 2)
|
||||
specName = "resto";
|
||||
break;
|
||||
case CLASS_ROGUE:
|
||||
if (tab == 0)
|
||||
specName = "assas";
|
||||
else if (tab == 1)
|
||||
specName = "combat";
|
||||
else if (tab == 2)
|
||||
specName = "subtle";
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
if (tab == 0)
|
||||
specName = "beast";
|
||||
else if (tab == 1)
|
||||
specName = "marks";
|
||||
else if (tab == 2)
|
||||
specName = "surv";
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
if (tab == 0)
|
||||
specName = "blooddps";
|
||||
else if (tab == 1)
|
||||
specName = "frostdps";
|
||||
else if (tab == 2)
|
||||
specName = "unholydps";
|
||||
break;
|
||||
case CLASS_MAGE:
|
||||
if (tab == 0)
|
||||
specName = "arcane";
|
||||
else if (tab == 1)
|
||||
specName = "fire";
|
||||
else if (tab == 2)
|
||||
specName = "frost";
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
if (tab == 0)
|
||||
specName = "afflic";
|
||||
else if (tab == 1)
|
||||
specName = "demo";
|
||||
else if (tab == 2)
|
||||
specName = "destro";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return std::move(specName);
|
||||
}
|
||||
|
||||
void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* engine)
|
||||
{
|
||||
uint8 tab = GetPlayerSpecTab(player);
|
||||
|
||||
if (!player->InBattleground())
|
||||
{
|
||||
engine->addStrategies("racials", "chat", "default", "potions", "cast time", "conserve mana", "duel", nullptr);
|
||||
}
|
||||
|
||||
switch (player->getClass())
|
||||
{
|
||||
case CLASS_PRIEST:
|
||||
if (tab == 2)
|
||||
{
|
||||
engine->addStrategies("dps", "shadow debuff", "shadow aoe", "threat", nullptr);
|
||||
}
|
||||
else if (tab == 0)
|
||||
{
|
||||
engine->addStrategies("holy", "shadow debuff", "shadow aoe", "threat", nullptr);
|
||||
//if (player->getLevel() >= 4)
|
||||
//engine->addStrategy("dps debuff");
|
||||
}
|
||||
else
|
||||
engine->addStrategies("heal", "threat", nullptr);
|
||||
|
||||
engine->addStrategies("dps assist", "flee", "cure", "ranged", "cc", nullptr);
|
||||
break;
|
||||
case CLASS_MAGE:
|
||||
if (tab == 0)
|
||||
engine->addStrategies("arcane", "threat", nullptr);
|
||||
else if (tab == 1)
|
||||
engine->addStrategies("fire", "fire aoe", "threat", nullptr);
|
||||
else
|
||||
engine->addStrategies("frost", "frost aoe", "threat", "dps aoe", nullptr);
|
||||
|
||||
engine->addStrategies("dps", "dps assist", "flee", "cure", "ranged", "cc", nullptr);
|
||||
break;
|
||||
case CLASS_WARRIOR:
|
||||
if (tab == 2)
|
||||
engine->addStrategies("tank", "tank assist", "aoe", "close", "mark rti", nullptr);
|
||||
else if (player->getLevel() < 30 || tab == 0)
|
||||
engine->addStrategies("arms", "aoe", "dps assist", "threat", "close", nullptr);
|
||||
else
|
||||
engine->addStrategies("fury", "aoe", "dps assist", "threat", "close", nullptr);
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
if (tab == 0)
|
||||
engine->addStrategies("caster", "caster aoe", "bmana", "threat", "flee", "ranged", nullptr);
|
||||
else if (tab == 2)
|
||||
engine->addStrategies("heal", "bmana", "flee", "ranged", nullptr);
|
||||
else
|
||||
engine->addStrategies("dps", "melee aoe", "bdps", "threat", "close", nullptr);
|
||||
|
||||
engine->addStrategies("dps assist", "cure", "totems", nullptr);
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
if (tab == 1)
|
||||
engine->addStrategies("tank", "tank assist", "bthreat", "cure", "barmor", "bstats", "close", "cc", nullptr);
|
||||
else if (tab == 0)
|
||||
engine->addStrategies("heal", "bmana", "dps assist", "cure", "flee", "barmor", nullptr);
|
||||
else
|
||||
engine->addStrategies("dps", "bdps", "dps assist", "cure", "baoe", "close", "cc", nullptr);
|
||||
|
||||
if (player->getLevel() < 14)
|
||||
{
|
||||
engine->addStrategy("bdps");
|
||||
}
|
||||
|
||||
if (player->getLevel() < 16)
|
||||
{
|
||||
engine->addStrategy("barmor");
|
||||
}
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
if (tab == 0)
|
||||
{
|
||||
engine->addStrategies("caster", "cure", "caster aoe", "threat", "flee", "dps assist", "ranged", "cc", nullptr);
|
||||
if (player->getLevel() > 19)
|
||||
engine->addStrategy("caster debuff");
|
||||
}
|
||||
else if (tab == 2)
|
||||
engine->addStrategies("heal", "cure", "flee", "dps assist", "ranged", "cc", nullptr);
|
||||
else
|
||||
{
|
||||
engine->removeStrategy("ranged");
|
||||
engine->addStrategies("bear", "tank assist", "flee", "close", nullptr);
|
||||
}
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
engine->addStrategies("dps", "bdps", "threat", "dps assist", "ranged", "pet", "cc", nullptr);
|
||||
if (player->getLevel() > 19)
|
||||
engine->addStrategy("dps debuff");
|
||||
break;
|
||||
case CLASS_ROGUE:
|
||||
engine->addStrategies("dps", "threat", "dps assist", "aoe", "close", "cc", "behind", "stealth", nullptr);
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
if (player->getLevel() > 19)
|
||||
engine->addStrategy("dps debuff");
|
||||
|
||||
engine->addStrategies("dps assist", "dps", "flee", "ranged", "cc", "pet", "threat", nullptr);
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
if (tab == 0)
|
||||
engine->addStrategies("blood", nullptr);
|
||||
else if (tab == 1)
|
||||
engine->addStrategies("frost", "frost aoe", "dps assist", "threat", nullptr);
|
||||
else
|
||||
engine->addStrategies("unholy", "unholy aoe", "dps assist", "threat", nullptr);
|
||||
|
||||
engine->addStrategies("dps assist", "flee", "close", "cc", nullptr);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (facade->IsRealPlayer() || sRandomPlayerbotMgr->IsRandomBot(player))
|
||||
{
|
||||
if (!player->GetGroup())
|
||||
{
|
||||
engine->ChangeStrategy(sPlayerbotAIConfig->randomBotCombatStrategies);
|
||||
|
||||
engine->addStrategy("flee");
|
||||
engine->addStrategy("boost");
|
||||
|
||||
if (player->getClass() == CLASS_WARLOCK)
|
||||
{
|
||||
engine->removeStrategy("ranged");
|
||||
}
|
||||
|
||||
if (player->getClass() == CLASS_DRUID && tab == 2)
|
||||
{
|
||||
engine->addStrategies("caster", "caster aoe", nullptr);
|
||||
}
|
||||
|
||||
if (player->getClass() == CLASS_DRUID && tab == 1 && urand(0, 100) > 50 && player->getLevel() > 19)
|
||||
{
|
||||
engine->addStrategy("dps");
|
||||
}
|
||||
|
||||
if (player->getClass() == CLASS_PRIEST && tab == 1)
|
||||
{
|
||||
engine->removeStrategy("heal");
|
||||
engine->addStrategies("holy", "shadow debuff", "shadow aoe", "threat", nullptr);
|
||||
}
|
||||
|
||||
if (player->getClass() == CLASS_SHAMAN && tab == 2)
|
||||
{
|
||||
engine->addStrategies("caster", "caster aoe", nullptr);
|
||||
}
|
||||
|
||||
if (player->getClass() == CLASS_PALADIN && tab == 0)
|
||||
{
|
||||
engine->addStrategies("dps", "close", nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
engine->ChangeStrategy(sPlayerbotAIConfig->combatStrategies);
|
||||
}
|
||||
|
||||
// Battleground switch
|
||||
if (player->InBattleground())
|
||||
{
|
||||
BattlegroundTypeId bgType = player->GetBattlegroundTypeId();
|
||||
if (bgType == BATTLEGROUND_RB)
|
||||
bgType = player->GetBattleground()->GetBgTypeID(true);
|
||||
|
||||
if (bgType == BATTLEGROUND_WS)
|
||||
engine->addStrategy("warsong");
|
||||
|
||||
if (bgType == BATTLEGROUND_AB)
|
||||
engine->addStrategy("arathi");
|
||||
|
||||
if (bgType == BATTLEGROUND_AV)
|
||||
engine->addStrategy("alterac");
|
||||
|
||||
if (bgType == BATTLEGROUND_EY)
|
||||
engine->addStrategy("eye");
|
||||
|
||||
if (bgType == BATTLEGROUND_IC)
|
||||
engine->addStrategy("isle");
|
||||
|
||||
if (player->InArena())
|
||||
{
|
||||
engine->addStrategy("arena");
|
||||
}
|
||||
|
||||
engine->addStrategies("boost", "racials", "chat", "default", "aoe", "potions", "conserve mana", "cast time", "dps assist", nullptr);
|
||||
engine->removeStrategy("custom::say");
|
||||
engine->removeStrategy("flee");
|
||||
engine->removeStrategy("threat");
|
||||
engine->addStrategy("boost");
|
||||
|
||||
if ((player->getClass() == CLASS_DRUID && tab == 2) || (player->getClass() == CLASS_SHAMAN && tab == 2))
|
||||
engine->addStrategies("caster", "caster aoe", nullptr);
|
||||
|
||||
if (player->getClass() == CLASS_DRUID && tab == 1)
|
||||
engine->addStrategies("behind", "dps", nullptr);
|
||||
|
||||
if (player->getClass() == CLASS_ROGUE)
|
||||
engine->addStrategies("behind", "stealth", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Engine* AiFactory::createCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext)
|
||||
{
|
||||
Engine* engine = new Engine(facade, aiObjectContext);
|
||||
AddDefaultCombatStrategies(player, facade, engine);
|
||||
return engine;
|
||||
}
|
||||
|
||||
void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* nonCombatEngine)
|
||||
{
|
||||
uint8 tab = GetPlayerSpecTab(player);
|
||||
|
||||
switch (player->getClass())
|
||||
{
|
||||
case CLASS_PRIEST:
|
||||
nonCombatEngine->addStrategies("dps assist", "cure", nullptr);
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
if (tab == 1)
|
||||
nonCombatEngine->addStrategies("bthreat", "tank assist", "barmor", "bstats", nullptr);
|
||||
else if (tab == 0)
|
||||
nonCombatEngine->addStrategies("dps assist", "barmor", "bmana", nullptr);
|
||||
else
|
||||
nonCombatEngine->addStrategies("dps assist", "baoe", "bdps", nullptr);
|
||||
|
||||
nonCombatEngine->addStrategies("cure", nullptr);
|
||||
|
||||
if (player->getLevel() < 14)
|
||||
nonCombatEngine->addStrategies("bdps", nullptr);
|
||||
|
||||
if (player->getLevel() < 16)
|
||||
nonCombatEngine->addStrategies("barmor", nullptr);
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
nonCombatEngine->addStrategies("bdps", "dps assist", nullptr);
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
if (tab == 0 || tab == 2)
|
||||
nonCombatEngine->addStrategy("bmana");
|
||||
else
|
||||
nonCombatEngine->addStrategy("bdps");
|
||||
|
||||
nonCombatEngine->addStrategies("dps assist", "cure", nullptr);
|
||||
break;
|
||||
case CLASS_MAGE:
|
||||
if (tab == 1)
|
||||
nonCombatEngine->addStrategy("bdps");
|
||||
else
|
||||
nonCombatEngine->addStrategy("bmana");
|
||||
|
||||
nonCombatEngine->addStrategies("dps assist", "cure", nullptr);
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
if (tab == 1)
|
||||
nonCombatEngine->addStrategy("tank assist");
|
||||
else
|
||||
nonCombatEngine->addStrategies("dps assist", "cure", nullptr);
|
||||
break;
|
||||
case CLASS_WARRIOR:
|
||||
if (tab == 2)
|
||||
nonCombatEngine->addStrategy("tank assist");
|
||||
else
|
||||
nonCombatEngine->addStrategy("dps assist");
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
nonCombatEngine->addStrategies("pet", "dps assist", nullptr);
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
if (tab == 0)
|
||||
nonCombatEngine->addStrategy("tank assist");
|
||||
else
|
||||
nonCombatEngine->addStrategy("dps assist");
|
||||
break;
|
||||
default:
|
||||
nonCombatEngine->addStrategy("dps assist");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!player->InBattleground())
|
||||
{
|
||||
nonCombatEngine->addStrategies("nc", "food", "chat", "follow",
|
||||
"default", "quest", "loot", "gather", "duel", "emote", "conserve mana", "buff", "mount", nullptr);
|
||||
}
|
||||
|
||||
if ((facade->IsRealPlayer() || sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground())
|
||||
{
|
||||
Player* master = facade->GetMaster();
|
||||
|
||||
// let 25% of free bots start duels.
|
||||
if (!urand(0, 3))
|
||||
nonCombatEngine->addStrategy("start duel");
|
||||
|
||||
if (!player->GetGroup() || player->GetGroup()->GetLeaderGUID() == player->GetGUID())
|
||||
{
|
||||
// let 25% of random not grouped (or grp leader) bots help other players
|
||||
if (!urand(0, 3))
|
||||
nonCombatEngine->addStrategy("attack tagged");
|
||||
|
||||
nonCombatEngine->addStrategy("pvp");
|
||||
nonCombatEngine->addStrategy("collision");
|
||||
nonCombatEngine->addStrategy("grind");
|
||||
nonCombatEngine->addStrategy("group");
|
||||
nonCombatEngine->addStrategy("guild");
|
||||
|
||||
if (sPlayerbotAIConfig->autoDoQuests)
|
||||
{
|
||||
nonCombatEngine->addStrategy("travel");
|
||||
nonCombatEngine->addStrategy("rpg");
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->randomBotJoinLfg)
|
||||
nonCombatEngine->addStrategy("lfg");
|
||||
|
||||
if (sPlayerbotAIConfig->randomBotJoinBG)
|
||||
nonCombatEngine->addStrategy("bg");
|
||||
|
||||
if (!master || GET_PLAYERBOT_AI(master))
|
||||
nonCombatEngine->addStrategy("maintenance");
|
||||
|
||||
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (facade)
|
||||
{
|
||||
if (master)
|
||||
{
|
||||
PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master);
|
||||
if (masterBotAI || sRandomPlayerbotMgr->IsRandomBot(player))
|
||||
{
|
||||
nonCombatEngine->addStrategy("pvp");
|
||||
nonCombatEngine->addStrategy("collision");
|
||||
nonCombatEngine->addStrategy("grind");
|
||||
nonCombatEngine->addStrategy("group");
|
||||
nonCombatEngine->addStrategy("guild");
|
||||
|
||||
if (sPlayerbotAIConfig->autoDoQuests)
|
||||
{
|
||||
nonCombatEngine->addStrategy("travel");
|
||||
nonCombatEngine->addStrategy("rpg");
|
||||
}
|
||||
|
||||
if (masterBotAI)
|
||||
nonCombatEngine->addStrategy("maintenance");
|
||||
|
||||
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies);
|
||||
}
|
||||
else
|
||||
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies);
|
||||
}
|
||||
|
||||
// Battleground switch
|
||||
if (player->InBattleground())
|
||||
{
|
||||
nonCombatEngine->addStrategies("nc", "chat", "default", "buff", "food", "mount", "pvp", "collision", "dps assist", "attack tagged", "emote", nullptr);
|
||||
nonCombatEngine->removeStrategy("custom::say");
|
||||
nonCombatEngine->removeStrategy("travel");
|
||||
nonCombatEngine->removeStrategy("rpg");
|
||||
nonCombatEngine->removeStrategy("grind");
|
||||
|
||||
BattlegroundTypeId bgType = player->GetBattlegroundTypeId();
|
||||
if (bgType == BATTLEGROUND_RB)
|
||||
bgType = player->GetBattleground()->GetBgTypeID(true);
|
||||
|
||||
if (bgType <= BATTLEGROUND_EY || bgType == BATTLEGROUND_IC) // do not add for not supported bg
|
||||
nonCombatEngine->addStrategy("battleground");
|
||||
|
||||
if (bgType == BATTLEGROUND_WS)
|
||||
nonCombatEngine->addStrategy("warsong");
|
||||
|
||||
if (bgType == BATTLEGROUND_AV)
|
||||
nonCombatEngine->addStrategy("alterac");
|
||||
|
||||
if (bgType == BATTLEGROUND_AB)
|
||||
nonCombatEngine->addStrategy("arathi");
|
||||
|
||||
if (bgType == BATTLEGROUND_EY)
|
||||
nonCombatEngine->addStrategy("eye");
|
||||
|
||||
if (bgType == BATTLEGROUND_IC)
|
||||
nonCombatEngine->addStrategy("isle");
|
||||
|
||||
if (player->InArena())
|
||||
{
|
||||
nonCombatEngine->addStrategy("arena");
|
||||
nonCombatEngine->removeStrategy("mount");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Engine* AiFactory::createNonCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext)
|
||||
{
|
||||
Engine* nonCombatEngine = new Engine(facade, aiObjectContext);
|
||||
|
||||
AddDefaultNonCombatStrategies(player, facade, nonCombatEngine);
|
||||
return nonCombatEngine;
|
||||
}
|
||||
|
||||
void AiFactory::AddDefaultDeadStrategies(Player* player, PlayerbotAI* const facade, Engine* deadEngine)
|
||||
{
|
||||
deadEngine->addStrategies("dead", "stay", "chat", "default", "follow", nullptr);
|
||||
|
||||
if (sRandomPlayerbotMgr->IsRandomBot(player) && !player->GetGroup())
|
||||
{
|
||||
deadEngine->removeStrategy("follow");
|
||||
}
|
||||
}
|
||||
|
||||
Engine* AiFactory::createDeadEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* AiObjectContext)
|
||||
{
|
||||
Engine* deadEngine = new Engine(facade, AiObjectContext);
|
||||
AddDefaultDeadStrategies(player, facade, deadEngine);
|
||||
return deadEngine;
|
||||
}
|
||||
36
src/AiFactory.h
Normal file
36
src/AiFactory.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_AIFACTORY_H
|
||||
#define _PLAYERBOT_AIFACTORY_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class AiObjectContext;
|
||||
class Engine;
|
||||
class Player;
|
||||
class PlayerbotAI;
|
||||
|
||||
enum BotRoles : uint8;
|
||||
|
||||
class AiFactory
|
||||
{
|
||||
public:
|
||||
static AiObjectContext* createAiObjectContext(Player* player, PlayerbotAI* botAI);
|
||||
static Engine* createCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext);
|
||||
static Engine* createNonCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext);
|
||||
static Engine* createDeadEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aibjectContext);
|
||||
static void AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* nonCombatEngine);
|
||||
static void AddDefaultDeadStrategies(Player* player, PlayerbotAI* const facade, Engine* deadEngine);
|
||||
static void AddDefaultCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* engine);
|
||||
|
||||
static uint8 GetPlayerSpecTab(Player* player);
|
||||
static std::map<uint8, uint32> GetPlayerSpecTabs(Player* player);
|
||||
static BotRoles GetPlayerRoles(Player* player);
|
||||
static std::string GetPlayerSpecName(Player* player);
|
||||
};
|
||||
|
||||
#endif
|
||||
298
src/ChatFilter.cpp
Normal file
298
src/ChatFilter.cpp
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "ChatFilter.h"
|
||||
#include "Group.h"
|
||||
#include "Playerbots.h"
|
||||
#include "RtiTargetValue.h"
|
||||
|
||||
std::string const ChatFilter::Filter(std::string& message)
|
||||
{
|
||||
if (message.find("@") == std::string::npos)
|
||||
return message;
|
||||
|
||||
return message.substr(message.find(" ") + 1);
|
||||
}
|
||||
|
||||
class StrategyChatFilter : public ChatFilter
|
||||
{
|
||||
public:
|
||||
StrategyChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) { }
|
||||
|
||||
std::string const Filter(std::string& message) override
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
|
||||
bool tank = message.find("@tank") == 0;
|
||||
if (tank && !botAI->IsTank(bot))
|
||||
return "";
|
||||
|
||||
bool dps = message.find("@dps") == 0;
|
||||
if (dps && (botAI->IsTank(bot) || botAI->IsHeal(bot)))
|
||||
return "";
|
||||
|
||||
bool heal = message.find("@heal") == 0;
|
||||
if (heal && !botAI->IsHeal(bot))
|
||||
return "";
|
||||
|
||||
bool ranged = message.find("@ranged") == 0;
|
||||
if (ranged && !botAI->IsRanged(bot))
|
||||
return "";
|
||||
|
||||
bool melee = message.find("@melee") == 0;
|
||||
if (melee && botAI->IsRanged(bot))
|
||||
return "";
|
||||
|
||||
if (tank || dps || heal || ranged || melee)
|
||||
return ChatFilter::Filter(message);
|
||||
|
||||
return message;
|
||||
}
|
||||
};
|
||||
|
||||
class LevelChatFilter : public ChatFilter
|
||||
{
|
||||
public:
|
||||
LevelChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) { }
|
||||
|
||||
std::string const Filter(std::string& message) override
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
|
||||
if (message[0] != '@')
|
||||
return message;
|
||||
|
||||
if (message.find("-") != std::string::npos)
|
||||
{
|
||||
uint32 fromLevel = atoi(message.substr(message.find("@") + 1, message.find("-")).c_str());
|
||||
uint32 toLevel = atoi(message.substr(message.find("-") + 1, message.find(" ")).c_str());
|
||||
|
||||
if (bot->getLevel() >= fromLevel && bot->getLevel() <= toLevel)
|
||||
return ChatFilter::Filter(message);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
uint32 level = atoi(message.substr(message.find("@") + 1, message.find(" ")).c_str());
|
||||
if (bot->getLevel() == level)
|
||||
return ChatFilter::Filter(message);
|
||||
|
||||
return message;
|
||||
}
|
||||
};
|
||||
|
||||
class CombatTypeChatFilter : public ChatFilter
|
||||
{
|
||||
public:
|
||||
CombatTypeChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) { }
|
||||
|
||||
std::string const Filter(std::string& message) override
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
|
||||
bool melee = message.find("@melee") == 0;
|
||||
bool ranged = message.find("@ranged") == 0;
|
||||
|
||||
if (!melee && !ranged)
|
||||
return message;
|
||||
|
||||
switch (bot->getClass())
|
||||
{
|
||||
case CLASS_WARRIOR:
|
||||
case CLASS_PALADIN:
|
||||
case CLASS_ROGUE:
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
if (ranged)
|
||||
return "";
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
case CLASS_PRIEST:
|
||||
case CLASS_MAGE:
|
||||
case CLASS_WARLOCK:
|
||||
if (melee)
|
||||
return "";
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
if (ranged && botAI->IsTank(bot))
|
||||
return "";
|
||||
if (melee && !botAI->IsTank(bot))
|
||||
return "";
|
||||
break;
|
||||
case CLASS_SHAMAN:
|
||||
if (melee && botAI->IsHeal(bot))
|
||||
return "";
|
||||
if (ranged && !botAI->IsHeal(bot))
|
||||
return "";
|
||||
break;
|
||||
}
|
||||
|
||||
return ChatFilter::Filter(message);
|
||||
}
|
||||
};
|
||||
|
||||
class RtiChatFilter : public ChatFilter
|
||||
{
|
||||
public:
|
||||
RtiChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI)
|
||||
{
|
||||
rtis.push_back("@star");
|
||||
rtis.push_back("@circle");
|
||||
rtis.push_back("@diamond");
|
||||
rtis.push_back("@triangle");
|
||||
rtis.push_back("@moon");
|
||||
rtis.push_back("@square");
|
||||
rtis.push_back("@cross");
|
||||
rtis.push_back("@skull");
|
||||
}
|
||||
|
||||
std::string const Filter(std::string& message) override
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
Group* group = bot->GetGroup();
|
||||
if (!group)
|
||||
return message;
|
||||
|
||||
bool found = false;
|
||||
bool isRti = false;
|
||||
for (std::vector<std::string>::iterator i = rtis.begin(); i != rtis.end(); i++)
|
||||
{
|
||||
std::string const rti = *i;
|
||||
|
||||
bool isRti = message.find(rti) == 0;
|
||||
if (!isRti)
|
||||
continue;
|
||||
|
||||
ObjectGuid rtiTarget = group->GetTargetIcon(RtiTargetValue::GetRtiIndex(rti.substr(1)));
|
||||
if (bot->GetGUID() == rtiTarget)
|
||||
return ChatFilter::Filter(message);
|
||||
|
||||
Unit* target = *botAI->GetAiObjectContext()->GetValue<Unit*>("current target");
|
||||
if (!target)
|
||||
return "";
|
||||
|
||||
if (target->GetGUID() != rtiTarget)
|
||||
return "";
|
||||
|
||||
found |= isRti;
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
return ChatFilter::Filter(message);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> rtis;
|
||||
};
|
||||
|
||||
class ClassChatFilter : public ChatFilter
|
||||
{
|
||||
public:
|
||||
ClassChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI)
|
||||
{
|
||||
classNames["@death_knight"] = CLASS_DEATH_KNIGHT;
|
||||
classNames["@druid"] = CLASS_DRUID;
|
||||
classNames["@hunter"] = CLASS_HUNTER;
|
||||
classNames["@mage"] = CLASS_MAGE;
|
||||
classNames["@paladin"] = CLASS_PALADIN;
|
||||
classNames["@priest"] = CLASS_PRIEST;
|
||||
classNames["@rogue"] = CLASS_ROGUE;
|
||||
classNames["@shaman"] = CLASS_SHAMAN;
|
||||
classNames["@warlock"] = CLASS_WARLOCK;
|
||||
classNames["@warrior"] = CLASS_WARRIOR;
|
||||
}
|
||||
|
||||
std::string const Filter(std::string& message) override
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
|
||||
bool found = false;
|
||||
bool isClass = false;
|
||||
for (std::map<std::string, uint8>::iterator i = classNames.begin(); i != classNames.end(); i++)
|
||||
{
|
||||
bool isClass = message.find(i->first) == 0;
|
||||
if (isClass && bot->getClass() != i->second)
|
||||
return "";
|
||||
|
||||
found |= isClass;
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
return ChatFilter::Filter(message);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, uint8> classNames;
|
||||
};
|
||||
|
||||
class SubGroupChatFilter : public ChatFilter
|
||||
{
|
||||
public:
|
||||
SubGroupChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) { }
|
||||
|
||||
std::string const Filter(std::string& message) override
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
|
||||
if (message.find("@group") == 0)
|
||||
{
|
||||
std::string const pnum = message.substr(6, message.find(" "));
|
||||
uint32 from = atoi(pnum.c_str());
|
||||
uint32 to = from;
|
||||
if (pnum.find("-") != std::string::npos)
|
||||
{
|
||||
from = atoi(pnum.substr(pnum.find("@") + 1, pnum.find("-")).c_str());
|
||||
to = atoi(pnum.substr(pnum.find("-") + 1, pnum.find(" ")).c_str());
|
||||
}
|
||||
|
||||
if (!bot->GetGroup())
|
||||
return message;
|
||||
|
||||
uint32 sg = bot->GetSubGroup() + 1;
|
||||
if (sg >= from && sg <= to)
|
||||
return ChatFilter::Filter(message);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
};
|
||||
|
||||
CompositeChatFilter::CompositeChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI)
|
||||
{
|
||||
filters.push_back(new StrategyChatFilter(botAI));
|
||||
filters.push_back(new ClassChatFilter(botAI));
|
||||
filters.push_back(new RtiChatFilter(botAI));
|
||||
filters.push_back(new CombatTypeChatFilter(botAI));
|
||||
filters.push_back(new LevelChatFilter(botAI));
|
||||
filters.push_back(new SubGroupChatFilter(botAI));
|
||||
}
|
||||
|
||||
CompositeChatFilter::~CompositeChatFilter()
|
||||
{
|
||||
for (std::vector<ChatFilter*>::iterator i = filters.begin(); i != filters.end(); i++)
|
||||
delete (*i);
|
||||
}
|
||||
|
||||
std::string const CompositeChatFilter::Filter(std::string& message)
|
||||
{
|
||||
for (uint32 j = 0; j < filters.size(); ++j)
|
||||
{
|
||||
for (std::vector<ChatFilter*>::iterator i = filters.begin(); i != filters.end(); i++)
|
||||
{
|
||||
message = (*i)->Filter(message);
|
||||
if (message.empty())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
36
src/ChatFilter.h
Normal file
36
src/ChatFilter.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_CHATFILTER_H
|
||||
#define _PLAYERBOT_CHATFILTER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "PlayerbotAIAware.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class ChatFilter : public PlayerbotAIAware
|
||||
{
|
||||
public:
|
||||
ChatFilter(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) { }
|
||||
virtual ~ChatFilter() { }
|
||||
|
||||
virtual std::string const Filter(std::string& message);
|
||||
};
|
||||
|
||||
class CompositeChatFilter : public ChatFilter
|
||||
{
|
||||
public:
|
||||
CompositeChatFilter(PlayerbotAI* botAI);
|
||||
|
||||
virtual ~CompositeChatFilter();
|
||||
std::string const Filter(std::string& message) override;
|
||||
|
||||
private:
|
||||
std::vector<ChatFilter*> filters;
|
||||
};
|
||||
|
||||
#endif
|
||||
569
src/ChatHelper.cpp
Normal file
569
src/ChatHelper.cpp
Normal file
@ -0,0 +1,569 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "ChatHelper.h"
|
||||
#include "AiFactory.h"
|
||||
#include "Playerbots.h"
|
||||
#include "SpellInfo.h"
|
||||
|
||||
std::map<std::string, uint32> ChatHelper::consumableSubClasses;
|
||||
std::map<std::string, uint32> ChatHelper::tradeSubClasses;
|
||||
std::map<std::string, uint32> ChatHelper::itemQualities;
|
||||
std::map<std::string, uint32> ChatHelper::projectileSubClasses;
|
||||
std::map<std::string, uint32> ChatHelper::slots;
|
||||
std::map<std::string, uint32> ChatHelper::skills;
|
||||
std::map<std::string, ChatMsg> ChatHelper::chats;
|
||||
std::map<uint8, std::string> ChatHelper::classes;
|
||||
std::map<uint8, std::string> ChatHelper::races;
|
||||
std::map<uint8, std::map<uint8, std::string> > ChatHelper::specs;
|
||||
|
||||
template<class T>
|
||||
static bool substrContainsInMap(std::string const searchTerm, std::map<std::string, T> searchIn)
|
||||
{
|
||||
for (typename std::map<std::string, T>::iterator i = searchIn.begin(); i != searchIn.end(); ++i)
|
||||
{
|
||||
std::string const term = i->first;
|
||||
if (term.size() > 1 && searchTerm.find(term) != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ChatHelper::ChatHelper(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
|
||||
{
|
||||
itemQualities["poor"] = ITEM_QUALITY_POOR;
|
||||
itemQualities["gray"] = ITEM_QUALITY_POOR;
|
||||
itemQualities["normal"] = ITEM_QUALITY_NORMAL;
|
||||
itemQualities["white"] = ITEM_QUALITY_NORMAL;
|
||||
itemQualities["uncommon"] = ITEM_QUALITY_UNCOMMON;
|
||||
itemQualities["green"] = ITEM_QUALITY_UNCOMMON;
|
||||
itemQualities["rare"] = ITEM_QUALITY_RARE;
|
||||
itemQualities["blue"] = ITEM_QUALITY_RARE;
|
||||
itemQualities["epic"] = ITEM_QUALITY_EPIC;
|
||||
itemQualities["violet"] = ITEM_QUALITY_EPIC;
|
||||
itemQualities["legendary"] = ITEM_QUALITY_LEGENDARY;
|
||||
itemQualities["yellow"] = ITEM_QUALITY_LEGENDARY;
|
||||
|
||||
consumableSubClasses["potion"] = ITEM_SUBCLASS_POTION;
|
||||
consumableSubClasses["elixir"] = ITEM_SUBCLASS_ELIXIR;
|
||||
consumableSubClasses["flask"] = ITEM_SUBCLASS_FLASK;
|
||||
consumableSubClasses["scroll"] = ITEM_SUBCLASS_SCROLL;
|
||||
consumableSubClasses["food"] = ITEM_SUBCLASS_FOOD;
|
||||
consumableSubClasses["bandage"] = ITEM_SUBCLASS_BANDAGE;
|
||||
consumableSubClasses["enchant"] = ITEM_SUBCLASS_CONSUMABLE_OTHER;
|
||||
|
||||
projectileSubClasses["arrows"] = ITEM_SUBCLASS_ARROW;
|
||||
projectileSubClasses["bullets"] = ITEM_SUBCLASS_BULLET;
|
||||
|
||||
//tradeSubClasses["cloth"] = ITEM_SUBCLASS_CLOTH;
|
||||
//tradeSubClasses["leather"] = ITEM_SUBCLASS_LEATHER;
|
||||
//tradeSubClasses["metal"] = ITEM_SUBCLASS_METAL_STONE;
|
||||
//tradeSubClasses["stone"] = ITEM_SUBCLASS_METAL_STONE;
|
||||
//tradeSubClasses["ore"] = ITEM_SUBCLASS_METAL_STONE;
|
||||
//tradeSubClasses["meat"] = ITEM_SUBCLASS_MEAT;
|
||||
//tradeSubClasses["herb"] = ITEM_SUBCLASS_HERB;
|
||||
//tradeSubClasses["elemental"] = ITEM_SUBCLASS_ELEMENTAL;
|
||||
//tradeSubClasses["disenchants"] = ITEM_SUBCLASS_ENCHANTING;
|
||||
//tradeSubClasses["enchanting"] = ITEM_SUBCLASS_ENCHANTING;
|
||||
//tradeSubClasses["gems"] = ITEM_SUBCLASS_JEWELCRAFTING;
|
||||
//tradeSubClasses["jewels"] = ITEM_SUBCLASS_JEWELCRAFTING;
|
||||
//tradeSubClasses["jewelcrafting"] = ITEM_SUBCLASS_JEWELCRAFTING;
|
||||
|
||||
slots["head"] = EQUIPMENT_SLOT_HEAD;
|
||||
slots["neck"] = EQUIPMENT_SLOT_NECK;
|
||||
slots["shoulder"] = EQUIPMENT_SLOT_SHOULDERS;
|
||||
slots["shirt"] = EQUIPMENT_SLOT_BODY;
|
||||
slots["chest"] = EQUIPMENT_SLOT_CHEST;
|
||||
slots["waist"] = EQUIPMENT_SLOT_WAIST;
|
||||
slots["legs"] = EQUIPMENT_SLOT_LEGS;
|
||||
slots["feet"] = EQUIPMENT_SLOT_FEET;
|
||||
slots["wrist"] = EQUIPMENT_SLOT_WRISTS;
|
||||
slots["hands"] = EQUIPMENT_SLOT_HANDS;
|
||||
slots["finger 1"] = EQUIPMENT_SLOT_FINGER1;
|
||||
slots["finger 2"] = EQUIPMENT_SLOT_FINGER2;
|
||||
slots["trinket 1"] = EQUIPMENT_SLOT_TRINKET1;
|
||||
slots["trinket 2"] = EQUIPMENT_SLOT_TRINKET2;
|
||||
slots["back"] = EQUIPMENT_SLOT_BACK;
|
||||
slots["main hand"] = EQUIPMENT_SLOT_MAINHAND;
|
||||
slots["off hand"] = EQUIPMENT_SLOT_OFFHAND;
|
||||
slots["ranged"] = EQUIPMENT_SLOT_RANGED;
|
||||
slots["tabard"] = EQUIPMENT_SLOT_TABARD;
|
||||
|
||||
skills["first aid"] = SKILL_FIRST_AID;
|
||||
skills["fishing"] = SKILL_FISHING;
|
||||
skills["cooking"] = SKILL_COOKING;
|
||||
skills["alchemy"] = SKILL_ALCHEMY;
|
||||
skills["enchanting"] = SKILL_ENCHANTING;
|
||||
skills["engineering"] = SKILL_ENGINEERING;
|
||||
skills["leatherworking"] = SKILL_LEATHERWORKING;
|
||||
skills["blacksmithing"] = SKILL_BLACKSMITHING;
|
||||
skills["tailoring"] = SKILL_TAILORING;
|
||||
skills["herbalism"] = SKILL_HERBALISM;
|
||||
skills["mining"] = SKILL_MINING;
|
||||
skills["skinning"] = SKILL_SKINNING;
|
||||
skills["jewelcrafting"] = SKILL_JEWELCRAFTING;
|
||||
|
||||
chats["party"] = CHAT_MSG_PARTY;
|
||||
chats["p"] = CHAT_MSG_PARTY;
|
||||
chats["guild"] = CHAT_MSG_GUILD;
|
||||
chats["g"] = CHAT_MSG_GUILD;
|
||||
chats["raid"] = CHAT_MSG_RAID;
|
||||
chats["r"] = CHAT_MSG_RAID;
|
||||
chats["whisper"] = CHAT_MSG_WHISPER;
|
||||
chats["w"] = CHAT_MSG_WHISPER;
|
||||
|
||||
classes[CLASS_DRUID] = "druid";
|
||||
specs[CLASS_DRUID][0] = "balance";
|
||||
specs[CLASS_DRUID][1] = "feral combat";
|
||||
specs[CLASS_DRUID][2] = "restoration";
|
||||
|
||||
classes[CLASS_HUNTER] = "hunter";
|
||||
specs[CLASS_HUNTER][0] = "beast mastery";
|
||||
specs[CLASS_HUNTER][1] = "marksmanship";
|
||||
specs[CLASS_HUNTER][2] = "survival";
|
||||
|
||||
classes[CLASS_MAGE] = "mage";
|
||||
specs[CLASS_MAGE][0] = "arcane";
|
||||
specs[CLASS_MAGE][1] = "fire";
|
||||
specs[CLASS_MAGE][2] = "frost";
|
||||
|
||||
classes[CLASS_PALADIN] = "paladin";
|
||||
specs[CLASS_PALADIN][0] = "holy";
|
||||
specs[CLASS_PALADIN][1] = "protection";
|
||||
specs[CLASS_PALADIN][2] = "retribution";
|
||||
|
||||
classes[CLASS_PRIEST] = "priest";
|
||||
specs[CLASS_PRIEST][0] = "discipline";
|
||||
specs[CLASS_PRIEST][1] = "holy";
|
||||
specs[CLASS_PRIEST][2] = "shadow";
|
||||
|
||||
classes[CLASS_ROGUE] = "rogue";
|
||||
specs[CLASS_ROGUE][0] = "assasination";
|
||||
specs[CLASS_ROGUE][1] = "combat";
|
||||
specs[CLASS_ROGUE][2] = "subtlety";
|
||||
|
||||
classes[CLASS_SHAMAN] = "shaman";
|
||||
specs[CLASS_SHAMAN][0] = "elemental";
|
||||
specs[CLASS_SHAMAN][1] = "enhancement";
|
||||
specs[CLASS_SHAMAN][2] = "restoration";
|
||||
|
||||
classes[CLASS_WARLOCK] = "warlock";
|
||||
specs[CLASS_WARLOCK][0] = "affliction";
|
||||
specs[CLASS_WARLOCK][1] = "demonology";
|
||||
specs[CLASS_WARLOCK][2] = "destruction";
|
||||
|
||||
classes[CLASS_WARRIOR] = "warrior";
|
||||
specs[CLASS_WARRIOR][0] = "arms";
|
||||
specs[CLASS_WARRIOR][1] = "fury";
|
||||
specs[CLASS_WARRIOR][2] = "protection";
|
||||
|
||||
classes[CLASS_DEATH_KNIGHT] = "dk";
|
||||
specs[CLASS_DEATH_KNIGHT][0] = "blood";
|
||||
specs[CLASS_DEATH_KNIGHT][1] = "frost";
|
||||
specs[CLASS_DEATH_KNIGHT][2] = "unholy";
|
||||
|
||||
races[RACE_DWARF] = "Dwarf";
|
||||
races[RACE_GNOME] = "Gnome";
|
||||
races[RACE_HUMAN] = "Human";
|
||||
races[RACE_NIGHTELF] = "Night Elf";
|
||||
races[RACE_ORC] = "Orc";
|
||||
races[RACE_TAUREN] = "Tauren";
|
||||
races[RACE_TROLL] = "Troll";
|
||||
races[RACE_UNDEAD_PLAYER] = "Undead";
|
||||
races[RACE_BLOODELF] = "Blood Elf";
|
||||
races[RACE_DRAENEI] = "Draenei";
|
||||
}
|
||||
|
||||
std::string const ChatHelper::formatMoney(uint32 copper)
|
||||
{
|
||||
std::ostringstream out;
|
||||
if (!copper)
|
||||
{
|
||||
out << "0";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
uint32 gold = uint32(copper / 10000);
|
||||
copper -= (gold * 10000);
|
||||
uint32 silver = uint32(copper / 100);
|
||||
copper -= (silver * 100);
|
||||
|
||||
bool space = false;
|
||||
if (gold > 0)
|
||||
{
|
||||
out << gold << "g";
|
||||
space = true;
|
||||
}
|
||||
|
||||
if (silver > 0 && gold < 50)
|
||||
{
|
||||
if (space)
|
||||
out << " ";
|
||||
|
||||
out << silver << "s";
|
||||
space = true;
|
||||
}
|
||||
|
||||
if (copper > 0 && gold < 10)
|
||||
{
|
||||
if (space)
|
||||
out << " ";
|
||||
|
||||
out << copper << "c";
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
uint32 ChatHelper::parseMoney(std::string const text)
|
||||
{
|
||||
// if user specified money in ##g##s##c format
|
||||
std::string acum = "";
|
||||
uint32 copper = 0;
|
||||
for (uint8 i = 0; i < text.length(); i++)
|
||||
{
|
||||
if (text[i] == 'g')
|
||||
{
|
||||
copper += (atol(acum.c_str()) * 100 * 100);
|
||||
acum = "";
|
||||
}
|
||||
else if (text[i] == 'c')
|
||||
{
|
||||
copper += atol(acum.c_str());
|
||||
acum = "";
|
||||
}
|
||||
else if (text[i] == 's')
|
||||
{
|
||||
copper += (atol(acum.c_str()) * 100);
|
||||
acum = "";
|
||||
}
|
||||
else if (text[i] == ' ')
|
||||
break;
|
||||
else if (text[i] >= 48 && text[i] <= 57)
|
||||
acum += text[i];
|
||||
else
|
||||
{
|
||||
copper = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return copper;
|
||||
}
|
||||
|
||||
ItemIds ChatHelper::parseItems(std::string const text)
|
||||
{
|
||||
ItemIds itemIds;
|
||||
|
||||
uint8 pos = 0;
|
||||
while (true)
|
||||
{
|
||||
uint32 i = text.find("Hitem:", pos);
|
||||
if (i == -1)
|
||||
break;
|
||||
|
||||
pos = i + 6;
|
||||
uint32 endPos = text.find(':', pos);
|
||||
if (endPos == -1)
|
||||
break;
|
||||
|
||||
std::string const idC = text.substr(pos, endPos - pos);
|
||||
uint32 id = atol(idC.c_str());
|
||||
pos = endPos;
|
||||
if (id)
|
||||
itemIds.insert(id);
|
||||
}
|
||||
|
||||
return itemIds;
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatQuest(Quest const* quest)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "|cFFFFFF00|Hquest:" << quest->GetQuestId() << ':' << quest->GetQuestLevel() << "|h[" << quest->GetTitle() << "]|h|r";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatGameobject(GameObject* go)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "|cFFFFFF00|Hfound:" << go->GetGUID().GetRawValue() << ":" << go->GetEntry() << ":" << "|h[" << go->GetGOInfo()->name << "]|h|r";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatWorldobject(WorldObject* wo)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "|cFFFFFF00|Hfound:" << wo->GetGUID().GetRawValue() << ":" << wo->GetEntry() << ":" << "|h[";
|
||||
out << (wo->ToGameObject() ? ((GameObject*)wo)->GetGOInfo()->name : wo->GetName()) << "]|h|r";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatWorldEntry(int32 entry)
|
||||
{
|
||||
CreatureTemplate const* cInfo = nullptr;
|
||||
GameObjectTemplate const* gInfo = nullptr;
|
||||
|
||||
if (entry > 0)
|
||||
cInfo = sObjectMgr->GetCreatureTemplate(entry);
|
||||
else
|
||||
gInfo = sObjectMgr->GetGameObjectTemplate(entry * -1);
|
||||
|
||||
std::ostringstream out;
|
||||
out << "|cFFFFFF00|Hentry:" << abs(entry) << ":" << "|h[";
|
||||
|
||||
if (entry < 0 && gInfo)
|
||||
out << gInfo->name;
|
||||
else if (entry > 0 && cInfo)
|
||||
out << cInfo->Name;
|
||||
else
|
||||
out << "unknown";
|
||||
|
||||
out << "]|h|r";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatSpell(SpellInfo const* spellInfo)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "|cffffffff|Hspell:" << spellInfo->Id << "|h[" << spellInfo->SpellName[LOCALE_enUS] << "]|h|r";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatItem(ItemTemplate const* proto, uint32 count, uint32 total)
|
||||
{
|
||||
char color[32];
|
||||
sprintf(color, "%x", ItemQualityColors[proto->Quality]);
|
||||
|
||||
std::ostringstream out;
|
||||
out << "|c" << color << "|Hitem:" << proto->ItemId
|
||||
<< ":0:0:0:0:0:0:0" << "|h[" << proto->Name1
|
||||
<< "]|h|r";
|
||||
|
||||
if (count > 1)
|
||||
out << "x" << count;
|
||||
|
||||
if (total > 0)
|
||||
out << " (" << total << ")";
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatQItem(uint32 itemId)
|
||||
{
|
||||
char color[32];
|
||||
sprintf(color, "%x", ItemQualityColors[0]);
|
||||
|
||||
std::ostringstream out;
|
||||
out << "|c" << color << "|Hitem:" << itemId << ":0:0:0:0:0:0:0"
|
||||
<< "|h[item"
|
||||
<< "]|h|r";
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
ChatMsg ChatHelper::parseChat(std::string const text)
|
||||
{
|
||||
if (chats.find(text) != chats.end())
|
||||
return chats[text];
|
||||
|
||||
return CHAT_MSG_SYSTEM;
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatChat(ChatMsg chat)
|
||||
{
|
||||
switch (chat)
|
||||
{
|
||||
case CHAT_MSG_GUILD:
|
||||
return "guild";
|
||||
case CHAT_MSG_PARTY:
|
||||
return "party";
|
||||
case CHAT_MSG_WHISPER:
|
||||
return "whisper";
|
||||
case CHAT_MSG_RAID:
|
||||
return "raid";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
uint32 ChatHelper::parseSpell(std::string const text)
|
||||
{
|
||||
PlayerbotChatHandler handler(botAI->GetBot());
|
||||
return handler.extractSpellId(text);
|
||||
}
|
||||
|
||||
GuidVector ChatHelper::parseGameobjects(std::string const text)
|
||||
{
|
||||
GuidVector gos;
|
||||
// Link format
|
||||
// |cFFFFFF00|Hfound:" << guid << ':' << entry << ':' << "|h[" << gInfo->name << "]|h|r";
|
||||
// |cFFFFFF00|Hfound:9582:1731|h[Copper Vein]|h|r
|
||||
|
||||
uint8 pos = 0;
|
||||
while (true)
|
||||
{
|
||||
// extract GO guid
|
||||
uint32 i = text.find("Hfound:", pos); // base H = 11
|
||||
if (i == -1) // break if error
|
||||
break;
|
||||
|
||||
pos = i + 7; //start of window in text 11 + 7 = 18
|
||||
uint32 endPos = text.find(':', pos); // end of window in text 22
|
||||
if (endPos == -1) //break if error
|
||||
break;
|
||||
|
||||
std::istringstream stream(text.substr(pos, endPos - pos));
|
||||
uint64 guid;
|
||||
stream >> guid;
|
||||
|
||||
// extract GO entry
|
||||
pos = endPos + 1;
|
||||
endPos = text.find(':', pos); // end of window in text
|
||||
if (endPos == -1) //break if error
|
||||
break;
|
||||
|
||||
std::string const entryC = text.substr(pos, endPos - pos); // get std::string const within window i.e entry
|
||||
uint32 entry = atol(entryC.c_str()); // convert ascii to float
|
||||
|
||||
ObjectGuid lootCurrent = ObjectGuid(guid);
|
||||
|
||||
if (guid)
|
||||
gos.push_back(lootCurrent);
|
||||
}
|
||||
|
||||
return gos;
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatQuestObjective(std::string const name, uint32 available, uint32 required)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "|cFFFFFFFF" << name << (available >= required ? "|c0000FF00: " : "|c00FF0000: ")
|
||||
<< available << "/" << required << "|r";
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
uint32 ChatHelper::parseItemQuality(std::string const text)
|
||||
{
|
||||
if (itemQualities.find(text) == itemQualities.end())
|
||||
return MAX_ITEM_QUALITY;
|
||||
|
||||
return itemQualities[text];
|
||||
}
|
||||
|
||||
bool ChatHelper::parseItemClass(std::string const text, uint32* itemClass, uint32* itemSubClass)
|
||||
{
|
||||
if (text == "questitem")
|
||||
{
|
||||
*itemClass = ITEM_CLASS_QUEST;
|
||||
*itemSubClass = ITEM_SUBCLASS_QUEST;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (consumableSubClasses.find(text) != consumableSubClasses.end())
|
||||
{
|
||||
*itemClass = ITEM_CLASS_CONSUMABLE;
|
||||
*itemSubClass = consumableSubClasses[text];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tradeSubClasses.find(text) != tradeSubClasses.end())
|
||||
{
|
||||
*itemClass = ITEM_CLASS_TRADE_GOODS;
|
||||
*itemSubClass = tradeSubClasses[text];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (projectileSubClasses.find(text) != projectileSubClasses.end())
|
||||
{
|
||||
*itemClass = ITEM_CLASS_PROJECTILE;
|
||||
*itemSubClass = projectileSubClasses[text];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 ChatHelper::parseSlot(std::string const text)
|
||||
{
|
||||
if (slots.find(text) != slots.end())
|
||||
return slots[text];
|
||||
|
||||
return EQUIPMENT_SLOT_END;
|
||||
}
|
||||
|
||||
bool ChatHelper::parseable(std::string const text)
|
||||
{
|
||||
return text.find("|H") != std::string::npos || text == "questitem" || text == "ammo" || substrContainsInMap<uint32>(text, consumableSubClasses) ||
|
||||
substrContainsInMap<uint32>(text, tradeSubClasses) || substrContainsInMap<uint32>(text, itemQualities) || substrContainsInMap<uint32>(text, slots) ||
|
||||
substrContainsInMap<ChatMsg>(text, chats) || substrContainsInMap<uint32>(text, skills) || parseMoney(text) > 0;
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatClass(Player* player, int8 spec)
|
||||
{
|
||||
uint8 cls = player->getClass();
|
||||
|
||||
std::ostringstream out;
|
||||
out << specs[cls][spec] << " (";
|
||||
|
||||
std::map<uint8, uint32> tabs = AiFactory::GetPlayerSpecTabs(player);
|
||||
uint32 c0 = tabs[0];
|
||||
uint32 c1 = tabs[1];
|
||||
uint32 c2 = tabs[2];
|
||||
|
||||
out << (c0 ? "|h|cff00ff00" : "") << c0 << "|h|cffffffff/";
|
||||
out << (c1 ? "|h|cff00ff00" : "") << c1 << "|h|cffffffff/";
|
||||
out << (c2 ? "|h|cff00ff00" : "") << c2 << "|h|cffffffff";
|
||||
|
||||
out << ") " << classes[cls];
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatClass(uint8 cls)
|
||||
{
|
||||
return classes[cls];
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatRace(uint8 race)
|
||||
{
|
||||
return races[race];
|
||||
}
|
||||
|
||||
uint32 ChatHelper::parseSkill(std::string const text)
|
||||
{
|
||||
if (skills.find(text) != skills.end())
|
||||
return skills[text];
|
||||
|
||||
return SKILL_NONE;
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatSkill(uint32 skill)
|
||||
{
|
||||
for (std::map<std::string, uint32>::iterator i = skills.begin(); i != skills.end(); ++i)
|
||||
{
|
||||
if (i->second == skill)
|
||||
return i->first;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatBoolean(bool flag)
|
||||
{
|
||||
return flag ? "|cff00ff00ON|r" : "|cffffff00OFF|r";
|
||||
}
|
||||
|
||||
void ChatHelper::eraseAllSubStr(std::string& mainStr, std::string const toErase)
|
||||
{
|
||||
size_t pos = std::string::npos;
|
||||
|
||||
// Search for the substring in std::string const in a loop untill nothing is found
|
||||
while ((pos = mainStr.find(toErase)) != std::string::npos)
|
||||
{
|
||||
// If found then erase it from std::string
|
||||
mainStr.erase(pos, toErase.length());
|
||||
}
|
||||
}
|
||||
77
src/ChatHelper.h
Normal file
77
src/ChatHelper.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_CHATHELPER_H
|
||||
#define _PLAYERBOT_CHATHELPER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "PlayerbotAIAware.h"
|
||||
#include "SharedDefines.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class GameObject;
|
||||
class Quest;
|
||||
class Player;
|
||||
class PlayerbotAI;
|
||||
class SpellInfo;
|
||||
class WorldObject;
|
||||
|
||||
struct ItemTemplate;
|
||||
|
||||
typedef std::set<uint32> ItemIds;
|
||||
typedef std::set<uint32> SpellIds;
|
||||
|
||||
class ChatHelper : public PlayerbotAIAware
|
||||
{
|
||||
public:
|
||||
ChatHelper(PlayerbotAI* botAI);
|
||||
|
||||
static std::string const formatMoney(uint32 copper);
|
||||
static uint32 parseMoney(std::string const text);
|
||||
static ItemIds parseItems(std::string const text);
|
||||
uint32 parseSpell(std::string const text);
|
||||
static std::string const FormatQuest(Quest const* quest);
|
||||
static std::string const FormatItem(ItemTemplate const* proto, uint32 count = 0, uint32 total = 0);
|
||||
static std::string const FormatQItem(uint32 itemId);
|
||||
static std::string const FormatSpell(SpellInfo const* spellInfo);
|
||||
static std::string const FormatGameobject(GameObject* go);
|
||||
static std::string const FormatWorldobject(WorldObject* wo);
|
||||
static std::string const FormatWorldEntry(int32 entry);
|
||||
static std::string const FormatQuestObjective(std::string const name, uint32 available, uint32 required);
|
||||
static GuidVector parseGameobjects(std::string const text);
|
||||
|
||||
static ChatMsg parseChat(std::string const text);
|
||||
static std::string const FormatChat(ChatMsg chat);
|
||||
|
||||
static std::string const FormatClass(Player* player, int8 spec);
|
||||
static std::string const FormatClass(uint8 cls);
|
||||
static std::string const FormatRace(uint8 race);
|
||||
static std::string const FormatSkill(uint32 skill);
|
||||
static std::string const FormatBoolean(bool flag);
|
||||
|
||||
static uint32 parseItemQuality(std::string const text);
|
||||
static bool parseItemClass(std::string const text, uint32* itemClass, uint32* itemSubClass);
|
||||
static uint32 parseSlot(std::string const text);
|
||||
uint32 parseSkill(std::string const text);
|
||||
|
||||
static bool parseable(std::string const text);
|
||||
|
||||
void eraseAllSubStr(std::string& mainStr, std::string const toErase);
|
||||
|
||||
private:
|
||||
static std::map<std::string, uint32> consumableSubClasses;
|
||||
static std::map<std::string, uint32> tradeSubClasses;
|
||||
static std::map<std::string, uint32> itemQualities;
|
||||
static std::map<std::string, uint32> projectileSubClasses;
|
||||
static std::map<std::string, uint32> slots;
|
||||
static std::map<std::string, uint32> skills;
|
||||
static std::map<std::string, ChatMsg> chats;
|
||||
static std::map<uint8, std::string> classes;
|
||||
static std::map<uint8, std::string> races;
|
||||
static std::map<uint8, std::map<uint8, std::string>> specs;
|
||||
};
|
||||
|
||||
#endif
|
||||
171
src/FleeManager.cpp
Normal file
171
src/FleeManager.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "FleeManager.h"
|
||||
#include "Playerbots.h"
|
||||
#include "ServerFacade.h"
|
||||
|
||||
FleeManager::FleeManager(Player* bot, float maxAllowedDistance, float followAngle, bool forceMaxDistance, WorldPosition startPosition) :
|
||||
bot(bot), maxAllowedDistance(maxAllowedDistance), followAngle(followAngle), forceMaxDistance(forceMaxDistance), startPosition(startPosition ? startPosition : WorldPosition(bot))
|
||||
{
|
||||
}
|
||||
|
||||
void FleeManager::calculateDistanceToCreatures(FleePoint *point)
|
||||
{
|
||||
point->minDistance = -1.0f;
|
||||
point->sumDistance = 0.0f;
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los");
|
||||
for (GuidVector::iterator i = units.begin(); i != units.end(); ++i)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(*i);
|
||||
if (!unit)
|
||||
continue;
|
||||
|
||||
float d = sServerFacade->GetDistance2d(unit, point->x, point->y);
|
||||
point->sumDistance += d;
|
||||
if (point->minDistance < 0 || point->minDistance > d)
|
||||
point->minDistance = d;
|
||||
}
|
||||
}
|
||||
|
||||
bool intersectsOri(float angle, std::vector<float>& angles, float angleIncrement)
|
||||
{
|
||||
for (std::vector<float>::iterator i = angles.begin(); i != angles.end(); ++i)
|
||||
{
|
||||
float ori = *i;
|
||||
if (abs(angle - ori) < angleIncrement)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FleeManager::calculatePossibleDestinations(std::vector<FleePoint*> &points)
|
||||
{
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
Unit* target = *botAI->GetAiObjectContext()->GetValue<Unit*>("current target");
|
||||
|
||||
float botPosX = startPosition.getX();
|
||||
float botPosY = startPosition.getY();
|
||||
float botPosZ = startPosition.getZ();
|
||||
|
||||
FleePoint start(botAI, botPosX, botPosY, botPosZ);
|
||||
calculateDistanceToCreatures(&start);
|
||||
|
||||
std::vector<float> enemyOri;
|
||||
GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los");
|
||||
for (GuidVector::iterator i = units.begin(); i != units.end(); ++i)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(*i);
|
||||
if (!unit)
|
||||
continue;
|
||||
|
||||
float ori = bot->GetAngle(unit);
|
||||
enemyOri.push_back(ori);
|
||||
}
|
||||
|
||||
float distIncrement = std::max(sPlayerbotAIConfig->followDistance, (maxAllowedDistance - sPlayerbotAIConfig->tooCloseDistance) / 10.0f);
|
||||
for (float dist = maxAllowedDistance; dist >= sPlayerbotAIConfig->tooCloseDistance ; dist -= distIncrement)
|
||||
{
|
||||
float angleIncrement = std::max(M_PI / 20, M_PI / 4 / (1.0 + dist - sPlayerbotAIConfig->tooCloseDistance));
|
||||
for (float add = 0.0f; add < M_PI / 4 + angleIncrement; add += angleIncrement)
|
||||
{
|
||||
for (float angle = add; angle < add + 2 * static_cast<float>(M_PI) + angleIncrement; angle += static_cast<float>(M_PI) / 4)
|
||||
{
|
||||
if (intersectsOri(angle, enemyOri, angleIncrement))
|
||||
continue;
|
||||
|
||||
float x = botPosX + cos(angle) * maxAllowedDistance, y = botPosY + sin(angle) * maxAllowedDistance, z = botPosZ + CONTACT_DISTANCE;
|
||||
if (forceMaxDistance && sServerFacade->IsDistanceLessThan(sServerFacade->GetDistance2d(bot, x, y), maxAllowedDistance - sPlayerbotAIConfig->tooCloseDistance))
|
||||
continue;
|
||||
|
||||
bot->UpdateAllowedPositionZ(x, y, z);
|
||||
|
||||
Map* map = startPosition.getMap();
|
||||
if (map && map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight()))
|
||||
continue;
|
||||
|
||||
if (!bot->IsWithinLOS(x, y, z) || (target && !target->IsWithinLOS(x, y, z)))
|
||||
continue;
|
||||
|
||||
FleePoint* point = new FleePoint(botAI, x, y, z);
|
||||
calculateDistanceToCreatures(point);
|
||||
|
||||
if (sServerFacade->IsDistanceGreaterOrEqualThan(point->minDistance - start.minDistance, sPlayerbotAIConfig->followDistance))
|
||||
points.push_back(point);
|
||||
else
|
||||
delete point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FleeManager::cleanup(std::vector<FleePoint*> &points)
|
||||
{
|
||||
for (std::vector<FleePoint*>::iterator i = points.begin(); i != points.end(); i++)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
|
||||
points.clear();
|
||||
}
|
||||
|
||||
bool FleeManager::isBetterThan(FleePoint* point, FleePoint* other)
|
||||
{
|
||||
return point->sumDistance - other->sumDistance > 0;
|
||||
}
|
||||
|
||||
FleePoint* FleeManager::selectOptimalDestination(std::vector<FleePoint*> &points)
|
||||
{
|
||||
FleePoint* best = nullptr;
|
||||
for (std::vector<FleePoint*>::iterator i = points.begin(); i != points.end(); i++)
|
||||
{
|
||||
FleePoint* point = *i;
|
||||
if (!best || isBetterThan(point, best))
|
||||
best = point;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
bool FleeManager::CalculateDestination(float* rx, float* ry, float* rz)
|
||||
{
|
||||
std::vector<FleePoint*> points;
|
||||
calculatePossibleDestinations(points);
|
||||
|
||||
FleePoint* point = selectOptimalDestination(points);
|
||||
if (!point)
|
||||
{
|
||||
cleanup(points);
|
||||
return false;
|
||||
}
|
||||
|
||||
*rx = point->x;
|
||||
*ry = point->y;
|
||||
*rz = point->z;
|
||||
|
||||
cleanup(points);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FleeManager::isUseful()
|
||||
{
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los");
|
||||
for (GuidVector::iterator i = units.begin(); i != units.end(); ++i)
|
||||
{
|
||||
Creature* creature = botAI->GetCreature(*i);
|
||||
if (!creature)
|
||||
continue;
|
||||
|
||||
if (startPosition.sqDistance(WorldPosition(creature)) < creature->GetAttackDistance(bot) * creature->GetAttackDistance(bot))
|
||||
return true;
|
||||
|
||||
// float d = sServerFacade->GetDistance2d(unit, bot);
|
||||
// if (sServerFacade->IsDistanceLessThan(d, sPlayerbotAIConfig->aggroDistance)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
54
src/FleeManager.h
Normal file
54
src/FleeManager.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_FLEEMANAGER_H
|
||||
#define _PLAYERBOT_FLEEMANAGER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "TravelMgr.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Player;
|
||||
class PlayerbotAI;
|
||||
|
||||
class FleePoint
|
||||
{
|
||||
public:
|
||||
FleePoint(PlayerbotAI* botAI, float x, float y, float z) : botAI(botAI), sumDistance(0.0f), minDistance(0.0f), x(x), y(y), z(z) { }
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
float sumDistance;
|
||||
float minDistance;
|
||||
|
||||
private:
|
||||
PlayerbotAI* botAI;
|
||||
};
|
||||
|
||||
class FleeManager
|
||||
{
|
||||
public:
|
||||
FleeManager(Player* bot, float maxAllowedDistance, float followAngle, bool forceMaxDistance = false, WorldPosition startPosition = WorldPosition());
|
||||
|
||||
bool CalculateDestination(float* rx, float* ry, float* rz);
|
||||
bool isUseful();
|
||||
|
||||
private:
|
||||
void calculatePossibleDestinations(std::vector<FleePoint*> &points);
|
||||
void calculateDistanceToCreatures(FleePoint *point);
|
||||
void cleanup(std::vector<FleePoint*> &points);
|
||||
FleePoint* selectOptimalDestination(std::vector<FleePoint*> &points);
|
||||
bool isBetterThan(FleePoint* point, FleePoint* other);
|
||||
|
||||
Player* bot;
|
||||
float maxAllowedDistance;
|
||||
float followAngle;
|
||||
bool forceMaxDistance;
|
||||
WorldPosition startPosition;
|
||||
};
|
||||
|
||||
#endif
|
||||
1198
src/GuildTaskMgr.cpp
Normal file
1198
src/GuildTaskMgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
59
src/GuildTaskMgr.h
Normal file
59
src/GuildTaskMgr.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_GUILDTASKMGR_H
|
||||
#define _PLAYERBOT_GUILDTASKMGR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Transaction.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class ChatHandler;
|
||||
class Player;
|
||||
class Unit;
|
||||
|
||||
class GuildTaskMgr
|
||||
{
|
||||
public:
|
||||
GuildTaskMgr() { };
|
||||
virtual ~GuildTaskMgr() { };
|
||||
|
||||
static GuildTaskMgr* instance()
|
||||
{
|
||||
static GuildTaskMgr instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void Update(Player* owner, Player* guildMaster);
|
||||
|
||||
static bool HandleConsoleCommand(ChatHandler* handler, char const* args);
|
||||
bool IsGuildTaskItem(uint32 itemId, uint32 guildId);
|
||||
bool CheckItemTask(uint32 itemId, uint32 obtained, Player* owner, Player* bot, bool byMail = false);
|
||||
void CheckKillTask(Player* owner, Unit* victim);
|
||||
void CheckKillTaskInternal(Player* owner, Unit* victim);
|
||||
bool CheckTaskTransfer(std::string const text, Player* owner, Player* bot);
|
||||
|
||||
private:
|
||||
std::map<uint32, uint32> GetTaskValues(uint32 owner, std::string const type, uint32* validIn = nullptr);
|
||||
uint32 GetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32* validIn = nullptr);
|
||||
uint32 SetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32 value, uint32 validIn);
|
||||
uint32 CreateTask(Player* owner, uint32 guildId);
|
||||
bool SendAdvertisement(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId);
|
||||
bool SendItemAdvertisement(CharacterDatabaseTransaction& trans, uint32 itemId, uint32 owner, uint32 guildId, uint32 validIn);
|
||||
bool SendKillAdvertisement(CharacterDatabaseTransaction& trans, uint32 creatureId, uint32 owner, uint32 guildId, uint32 validIn);
|
||||
bool SendThanks(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId, uint32 payment);
|
||||
bool Reward(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId);
|
||||
bool CreateItemTask(Player* owner, uint32 guildId);
|
||||
bool CreateKillTask(Player* owner, uint32 guildId);
|
||||
uint32 GetMaxItemTaskCount(uint32 itemId);
|
||||
void CleanupAdverts();
|
||||
void RemoveDuplicatedAdverts();
|
||||
void DeleteMail(std::vector<uint32> buffer);
|
||||
void SendCompletionMessage(Player* player, std::string const verb);
|
||||
};
|
||||
|
||||
#define sGuildTaskMgr GuildTaskMgr::instance()
|
||||
|
||||
#endif
|
||||
52
src/Helpers.cpp
Normal file
52
src/Helpers.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "Helpers.h"
|
||||
|
||||
char* strstri(char const* haystack, char const* needle)
|
||||
{
|
||||
if (!*needle)
|
||||
{
|
||||
return (char*)haystack;
|
||||
}
|
||||
|
||||
for (; *haystack; ++haystack)
|
||||
{
|
||||
if (tolower(*haystack) == tolower(*needle))
|
||||
{
|
||||
char const* h = haystack, * n = needle;
|
||||
for (; *h && *n; ++h, ++n)
|
||||
{
|
||||
if (tolower(*h) != tolower(*n))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*n)
|
||||
{
|
||||
return (char*)haystack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string& ltrim(std::string& s)
|
||||
{
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) {return !std::isspace(c); }));
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string& rtrim(std::string& s)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) {return !std::isspace(c); }).base(), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string& trim(std::string& s)
|
||||
{
|
||||
return ltrim(rtrim(s));
|
||||
}
|
||||
50
src/Helpers.h
Normal file
50
src/Helpers.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_HELPERS_H
|
||||
#define _PLAYERBOT_HELPERS_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
|
||||
void split(std::vector<std::string>& dest, std::string const str, char const* delim)
|
||||
{
|
||||
char* pTempStr = strdup(str.c_str());
|
||||
char* pWord = strtok(pTempStr, delim);
|
||||
|
||||
while (pWord != nullptr)
|
||||
{
|
||||
dest.push_back(pWord);
|
||||
pWord = strtok(nullptr, delim);
|
||||
}
|
||||
|
||||
free(pTempStr);
|
||||
}
|
||||
|
||||
std::vector<std::string>& split(std::string const s, char delim, std::vector<std::string>& elems)
|
||||
{
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
|
||||
while (getline(ss, item, delim))
|
||||
{
|
||||
elems.push_back(item);
|
||||
}
|
||||
|
||||
return elems;
|
||||
}
|
||||
|
||||
std::vector<std::string> split(std::string const s, char delim)
|
||||
{
|
||||
std::vector<std::string> elems;
|
||||
return split(s, delim, elems);
|
||||
}
|
||||
|
||||
#endif
|
||||
44
src/LazyCalculatedValue.h
Normal file
44
src/LazyCalculatedValue.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_LAZYCALCULATEDVALUE_H
|
||||
#define _PLAYERBOT_LAZYCALCULATEDVALUE_H
|
||||
|
||||
template <class TValue, class TOwner>
|
||||
class LazyCalculatedValue
|
||||
{
|
||||
public:
|
||||
typedef TValue (TOwner::*Calculator)();
|
||||
|
||||
public:
|
||||
LazyCalculatedValue(TOwner* owner, Calculator calculator) : calculator(calculator), owner(owner)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public:
|
||||
TValue GetValue()
|
||||
{
|
||||
if (!calculated)
|
||||
{
|
||||
value = (owner->*calculator)();
|
||||
calculated = true;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
calculated = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
Calculator calculator;
|
||||
TOwner* owner;
|
||||
bool calculated;
|
||||
TValue value;
|
||||
};
|
||||
|
||||
#endif
|
||||
247
src/LootObjectStack.cpp
Normal file
247
src/LootObjectStack.cpp
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "LootObjectStack.h"
|
||||
#include "LootMgr.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
#define MAX_LOOT_OBJECT_COUNT 10
|
||||
|
||||
LootTarget::LootTarget(ObjectGuid guid) : guid(guid), asOfTime(time(nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
LootTarget::LootTarget(LootTarget const& other)
|
||||
{
|
||||
guid = other.guid;
|
||||
asOfTime = other.asOfTime;
|
||||
}
|
||||
|
||||
LootTarget& LootTarget::operator=(LootTarget const& other)
|
||||
{
|
||||
if ((void*)this == (void*)&other)
|
||||
return *this;
|
||||
|
||||
guid = other.guid;
|
||||
asOfTime = other.asOfTime;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool LootTarget::operator<(LootTarget const& other) const
|
||||
{
|
||||
return guid < other.guid;
|
||||
}
|
||||
|
||||
void LootTargetList::shrink(time_t fromTime)
|
||||
{
|
||||
for (std::set<LootTarget>::iterator i = begin(); i != end(); )
|
||||
{
|
||||
if (i->asOfTime <= fromTime)
|
||||
erase(i++);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
LootObject::LootObject(Player* bot, ObjectGuid guid) : guid(), skillId(SKILL_NONE), reqSkillValue(0), reqItem(0)
|
||||
{
|
||||
Refresh(bot, guid);
|
||||
}
|
||||
|
||||
void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
|
||||
{
|
||||
skillId = SKILL_NONE;
|
||||
reqSkillValue = 0;
|
||||
reqItem = 0;
|
||||
guid.Clear();
|
||||
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
Creature* creature = botAI->GetCreature(lootGUID);
|
||||
if (creature && creature->getDeathState() == CORPSE)
|
||||
{
|
||||
if (creature->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE))
|
||||
guid = lootGUID;
|
||||
|
||||
if (creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE))
|
||||
{
|
||||
skillId = creature->GetCreatureTemplate()->GetRequiredLootSkill();
|
||||
uint32 targetLevel = creature->getLevel();
|
||||
reqSkillValue = targetLevel < 10 ? 1 : targetLevel < 20 ? (targetLevel - 10) * 10 : targetLevel * 5;
|
||||
if (botAI->HasSkill((SkillType) skillId) && bot->GetSkillValue(skillId) >= reqSkillValue)
|
||||
guid = lootGUID;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject* go = botAI->GetGameObject(lootGUID);
|
||||
if (go && go->isSpawned() && go->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
uint32 lockId = go->GetGOInfo()->GetLockId();
|
||||
LockEntry const* lockInfo = sLockStore.LookupEntry(lockId);
|
||||
if (!lockInfo)
|
||||
return;
|
||||
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
{
|
||||
switch (lockInfo->Type[i])
|
||||
{
|
||||
case LOCK_KEY_ITEM:
|
||||
if (lockInfo->Index[i] > 0)
|
||||
{
|
||||
reqItem = lockInfo->Index[i];
|
||||
guid = lootGUID;
|
||||
}
|
||||
break;
|
||||
case LOCK_KEY_SKILL:
|
||||
if (SkillByLockType(LockType(lockInfo->Index[i])) > 0)
|
||||
{
|
||||
skillId = SkillByLockType(LockType(lockInfo->Index[i]));
|
||||
reqSkillValue = std::max((uint32)1, lockInfo->Skill[i]);
|
||||
guid = lootGUID;
|
||||
}
|
||||
break;
|
||||
case LOCK_KEY_NONE:
|
||||
guid = lootGUID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WorldObject* LootObject::GetWorldObject(Player* bot)
|
||||
{
|
||||
Refresh(bot, guid);
|
||||
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
|
||||
Creature* creature = botAI->GetCreature(guid);
|
||||
if (creature && creature->getDeathState() == CORPSE)
|
||||
return creature;
|
||||
|
||||
GameObject* go = botAI->GetGameObject(guid);
|
||||
if (go && go->isSpawned())
|
||||
return go;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LootObject::LootObject(LootObject const& other)
|
||||
{
|
||||
guid = other.guid;
|
||||
skillId = other.skillId;
|
||||
reqSkillValue = other.reqSkillValue;
|
||||
reqItem = other.reqItem;
|
||||
}
|
||||
|
||||
bool LootObject::IsLootPossible(Player* bot)
|
||||
{
|
||||
if (IsEmpty() || !GetWorldObject(bot))
|
||||
return false;
|
||||
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
|
||||
if (reqItem && !bot->HasItemCount(reqItem, 1))
|
||||
return false;
|
||||
|
||||
if (abs(GetWorldObject(bot)->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE)
|
||||
return false;
|
||||
|
||||
Creature* creature = botAI->GetCreature(guid);
|
||||
if (creature && creature->getDeathState() == CORPSE)
|
||||
{
|
||||
if (!creature->loot.hasItemFor(bot) && skillId != SKILL_SKINNING)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skillId == SKILL_NONE)
|
||||
return true;
|
||||
|
||||
if (skillId == SKILL_FISHING)
|
||||
return false;
|
||||
|
||||
if (!botAI->HasSkill((SkillType)skillId))
|
||||
return false;
|
||||
|
||||
if (!reqSkillValue)
|
||||
return true;
|
||||
|
||||
uint32 skillValue = uint32(bot->GetSkillValue(skillId));
|
||||
if (reqSkillValue > skillValue)
|
||||
return false;
|
||||
|
||||
if (skillId == SKILL_MINING && !bot->HasItemCount(2901, 1))
|
||||
return false;
|
||||
|
||||
if (skillId == SKILL_SKINNING && !bot->HasItemCount(7005, 1))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LootObjectStack::Add(ObjectGuid guid)
|
||||
{
|
||||
if (!availableLoot.insert(guid).second)
|
||||
return false;
|
||||
|
||||
if (availableLoot.size() < MAX_LOOT_OBJECT_COUNT)
|
||||
return true;
|
||||
|
||||
std::vector<LootObject> ordered = OrderByDistance();
|
||||
for (size_t i = MAX_LOOT_OBJECT_COUNT; i < ordered.size(); i++)
|
||||
Remove(ordered[i].guid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LootObjectStack::Remove(ObjectGuid guid)
|
||||
{
|
||||
LootTargetList::iterator i = availableLoot.find(guid);
|
||||
if (i != availableLoot.end())
|
||||
availableLoot.erase(i);
|
||||
}
|
||||
|
||||
void LootObjectStack::Clear()
|
||||
{
|
||||
availableLoot.clear();
|
||||
}
|
||||
|
||||
bool LootObjectStack::CanLoot(float maxDistance)
|
||||
{
|
||||
std::vector<LootObject> ordered = OrderByDistance(maxDistance);
|
||||
return !ordered.empty();
|
||||
}
|
||||
|
||||
LootObject LootObjectStack::GetLoot(float maxDistance)
|
||||
{
|
||||
std::vector<LootObject> ordered = OrderByDistance(maxDistance);
|
||||
return ordered.empty() ? LootObject() : *ordered.begin();
|
||||
}
|
||||
|
||||
std::vector<LootObject> LootObjectStack::OrderByDistance(float maxDistance)
|
||||
{
|
||||
availableLoot.shrink(time(nullptr) - 30);
|
||||
|
||||
std::map<float, LootObject> sortedMap;
|
||||
LootTargetList safeCopy(availableLoot);
|
||||
for (LootTargetList::iterator i = safeCopy.begin(); i != safeCopy.end(); i++)
|
||||
{
|
||||
ObjectGuid guid = i->guid;
|
||||
LootObject lootObject(bot, guid);
|
||||
if (!lootObject.IsLootPossible(bot))
|
||||
continue;
|
||||
|
||||
float distance = bot->GetDistance(lootObject.GetWorldObject(bot));
|
||||
if (!maxDistance || distance <= maxDistance)
|
||||
sortedMap[distance] = lootObject;
|
||||
}
|
||||
|
||||
std::vector<LootObject> result;
|
||||
for (std::map<float, LootObject>::iterator i = sortedMap.begin(); i != sortedMap.end(); i++)
|
||||
result.push_back(i->second);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
82
src/LootObjectStack.h
Normal file
82
src/LootObjectStack.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_LOOTOBJECTSTACK_H
|
||||
#define _PLAYERBOT_LOOTOBJECTSTACK_H
|
||||
|
||||
#include "ObjectGuid.h"
|
||||
|
||||
class AiObjectContext;
|
||||
class Player;
|
||||
class WorldObject;
|
||||
|
||||
struct ItemTemplate;
|
||||
|
||||
class LootStrategy
|
||||
{
|
||||
public:
|
||||
LootStrategy() { }
|
||||
virtual ~LootStrategy() { };
|
||||
virtual bool CanLoot(ItemTemplate const* proto, AiObjectContext* context) = 0;
|
||||
virtual std::string const GetName() = 0;
|
||||
};
|
||||
|
||||
class LootObject
|
||||
{
|
||||
public:
|
||||
LootObject() : skillId(0), reqSkillValue(0), reqItem(0) { }
|
||||
LootObject(Player* bot, ObjectGuid guid);
|
||||
LootObject(LootObject const& other);
|
||||
|
||||
bool IsEmpty() { return !guid; }
|
||||
bool IsLootPossible(Player* bot);
|
||||
void Refresh(Player* bot, ObjectGuid guid);
|
||||
WorldObject* GetWorldObject(Player* bot);
|
||||
ObjectGuid guid;
|
||||
|
||||
uint32 skillId;
|
||||
uint32 reqSkillValue;
|
||||
uint32 reqItem;
|
||||
};
|
||||
|
||||
class LootTarget
|
||||
{
|
||||
public:
|
||||
LootTarget(ObjectGuid guid);
|
||||
LootTarget(LootTarget const& other);
|
||||
|
||||
public:
|
||||
LootTarget& operator=(LootTarget const& other);
|
||||
bool operator<(LootTarget const& other) const;
|
||||
|
||||
public:
|
||||
ObjectGuid guid;
|
||||
time_t asOfTime;
|
||||
};
|
||||
|
||||
class LootTargetList : public std::set<LootTarget>
|
||||
{
|
||||
public:
|
||||
void shrink(time_t fromTime);
|
||||
};
|
||||
|
||||
class LootObjectStack
|
||||
{
|
||||
public:
|
||||
LootObjectStack(Player* bot) : bot(bot) { }
|
||||
|
||||
bool Add(ObjectGuid guid);
|
||||
void Remove(ObjectGuid guid);
|
||||
void Clear();
|
||||
bool CanLoot(float maxDistance);
|
||||
LootObject GetLoot(float maxDistance = 0);
|
||||
|
||||
private:
|
||||
std::vector<LootObject> OrderByDistance(float maxDistance = 0);
|
||||
|
||||
Player* bot;
|
||||
LootTargetList availableLoot;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
*/
|
||||
|
||||
// From SC
|
||||
void AddMyPlayerScripts();
|
||||
|
||||
// Add all
|
||||
// cf. the naming convention https://github.com/azerothcore/azerothcore-wotlk/blob/master/doc/changelog/master.md#how-to-upgrade-4
|
||||
// additionally replace all '-' in the module folder name with '_' here
|
||||
void Addskeleton_moduleScripts()
|
||||
{
|
||||
AddMyPlayerScripts();
|
||||
}
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Player.h"
|
||||
#include "Config.h"
|
||||
#include "Chat.h"
|
||||
|
||||
// Add player scripts
|
||||
class MyPlayer : public PlayerScript
|
||||
{
|
||||
public:
|
||||
MyPlayer() : PlayerScript("MyPlayer") { }
|
||||
|
||||
void OnLogin(Player* player) override
|
||||
{
|
||||
if (sConfigMgr->GetOption<bool>("MyModule.Enable", false))
|
||||
{
|
||||
ChatHandler(player->GetSession()).SendSysMessage("Hello World from Skeleton-Module!");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add all scripts in one
|
||||
void AddMyPlayerScripts()
|
||||
{
|
||||
new MyPlayer();
|
||||
}
|
||||
257
src/PerformanceMonitor.cpp
Normal file
257
src/PerformanceMonitor.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "PerformanceMonitor.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
PerformanceMonitorOperation* PerformanceMonitor::start(PerformanceMetric metric, std::string const name, PerformanceStack* stack)
|
||||
{
|
||||
if (!sPlayerbotAIConfig->perfMonEnabled)
|
||||
return nullptr;
|
||||
|
||||
std::string stackName = name;
|
||||
|
||||
if (stack)
|
||||
{
|
||||
if (!stack->empty())
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << stackName << " [";
|
||||
|
||||
for (std::vector<std::string>::reverse_iterator i = stack->rbegin(); i != stack->rend(); ++i)
|
||||
out << *i << (std::next(i) == stack->rend() ? "" : "|");
|
||||
|
||||
out << "]";
|
||||
|
||||
stackName = out.str().c_str();
|
||||
}
|
||||
|
||||
stack->push_back(name);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(lock);
|
||||
PerformanceData* pd = data[metric][stackName];
|
||||
if (!pd)
|
||||
{
|
||||
pd = new PerformanceData();
|
||||
pd->minTime = 0;
|
||||
pd->maxTime = 0;
|
||||
pd->totalTime = 0;
|
||||
pd->count = 0;
|
||||
data[metric][stackName] = pd;
|
||||
}
|
||||
|
||||
return new PerformanceMonitorOperation(pd, name, stack);
|
||||
}
|
||||
|
||||
void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
|
||||
{
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
uint32 total = 0;
|
||||
|
||||
if (!perTick)
|
||||
{
|
||||
for (auto& map : data[PERF_MON_TOTAL])
|
||||
if (map.first.find("PlayerbotAI::UpdateAIInternal") != std::string::npos)
|
||||
total += map.second->totalTime;
|
||||
|
||||
LOG_INFO("playerbots", "--------------------------------------[TOTAL BOT]------------------------------------------------------");
|
||||
LOG_INFO("playerbots", "percentage time | min .. max ( avg of count ) - type : name ");
|
||||
|
||||
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin(); i != data.end(); ++i)
|
||||
{
|
||||
std::map<std::string, PerformanceData*> pdMap = i->second;
|
||||
|
||||
std::string key;
|
||||
switch (i->first)
|
||||
{
|
||||
case PERF_MON_TRIGGER:
|
||||
key = "T";
|
||||
break;
|
||||
case PERF_MON_VALUE:
|
||||
key = "V";
|
||||
break;
|
||||
case PERF_MON_ACTION:
|
||||
key = "A";
|
||||
break;
|
||||
case PERF_MON_RNDBOT:
|
||||
key = "RndBot";
|
||||
break;
|
||||
case PERF_MON_TOTAL:
|
||||
key = "Total";
|
||||
break;
|
||||
default:
|
||||
key = "?";
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
|
||||
for (std::map<std::string, PerformanceData*>::iterator j = pdMap.begin(); j != pdMap.end(); ++j)
|
||||
{
|
||||
if (key == "Total" && j->first.find("PlayerbotAI::UpdateAIInternal") == std::string::npos)
|
||||
continue;
|
||||
|
||||
names.push_back(j->first);
|
||||
}
|
||||
|
||||
std::sort(names.begin(), names.end(), [pdMap](std::string const i, std::string const j)
|
||||
{
|
||||
return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime;
|
||||
});
|
||||
|
||||
for (auto& name : names)
|
||||
{
|
||||
PerformanceData* pd = pdMap[name];
|
||||
float perc = (float)pd->totalTime / (float)total * 100.0f;
|
||||
float secs = (float)pd->totalTime / 1000.0f;
|
||||
float avg = (float)pd->totalTime / (float)pd->count;
|
||||
std::string disName = name;
|
||||
if (!fullStack && disName.find("|") != std::string::npos)
|
||||
disName = disName.substr(0, disName.find("|")) + "]";
|
||||
|
||||
if (avg >= 0.5f || pd->maxTime > 10)
|
||||
{
|
||||
LOG_INFO("playerbots", "%7.3f%% %10.3fs | %6u .. %6u (%9.4f of %10u) - {} : {}"
|
||||
, perc
|
||||
, secs
|
||||
, pd->minTime
|
||||
, pd->maxTime
|
||||
, avg
|
||||
, pd->count
|
||||
, key.c_str()
|
||||
, disName.c_str());
|
||||
}
|
||||
}
|
||||
LOG_INFO("playerbots", " ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float totalCount = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->count;
|
||||
total = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->totalTime;
|
||||
|
||||
LOG_INFO("playerbots", " ");
|
||||
LOG_INFO("playerbots", " ");
|
||||
LOG_INFO("playerbots", "---------------------------------------[PER TICK]------------------------------------------------------");
|
||||
LOG_INFO("playerbots", "percentage time | min .. max ( avg of count ) - type : name ");
|
||||
|
||||
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin(); i != data.end(); ++i)
|
||||
{
|
||||
std::map<std::string, PerformanceData*> pdMap = i->second;
|
||||
|
||||
std::string key;
|
||||
switch (i->first)
|
||||
{
|
||||
case PERF_MON_TRIGGER:
|
||||
key = "T";
|
||||
break;
|
||||
case PERF_MON_VALUE:
|
||||
key = "V";
|
||||
break;
|
||||
case PERF_MON_ACTION:
|
||||
key = "A";
|
||||
break;
|
||||
case PERF_MON_RNDBOT:
|
||||
key = "RndBot";
|
||||
break;
|
||||
case PERF_MON_TOTAL:
|
||||
key = "Total";
|
||||
break;
|
||||
default:
|
||||
key = "?";
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
|
||||
for (std::map<std::string, PerformanceData*>::iterator j = pdMap.begin(); j != pdMap.end(); ++j)
|
||||
{
|
||||
names.push_back(j->first);
|
||||
}
|
||||
|
||||
std::sort(names.begin(), names.end(), [pdMap](std::string const i, std::string const j)
|
||||
{
|
||||
return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime;
|
||||
});
|
||||
|
||||
for (auto& name : names)
|
||||
{
|
||||
PerformanceData* pd = pdMap[name];
|
||||
float perc = (float)pd->totalTime / (float)total * 100.0f;
|
||||
uint32 secs = pd->totalTime / totalCount;
|
||||
float avg = (float)pd->totalTime / (float)pd->count;
|
||||
float amount = (float)pd->count / (float)totalCount;
|
||||
std::string disName = name;
|
||||
if (!fullStack && disName.find("|") != std::string::npos)
|
||||
disName = disName.substr(0, disName.find("|")) + "]";
|
||||
|
||||
if (avg >= 0.5f || pd->maxTime > 10)
|
||||
{
|
||||
LOG_INFO("playerbots", "%7.3f%% %9ums | %6u .. %6u (%9.4f of %10.3f) - {} : {}"
|
||||
, perc
|
||||
, secs
|
||||
, pd->minTime
|
||||
, pd->maxTime
|
||||
, avg
|
||||
, amount
|
||||
, key.c_str()
|
||||
, disName.c_str());
|
||||
}
|
||||
}
|
||||
LOG_INFO("playerbots", " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceMonitor::Reset()
|
||||
{
|
||||
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*> >::iterator i = data.begin(); i != data.end(); ++i)
|
||||
{
|
||||
std::map<std::string, PerformanceData*> pdMap = i->second;
|
||||
for (std::map<std::string, PerformanceData*>::iterator j = pdMap.begin(); j != pdMap.end(); ++j)
|
||||
{
|
||||
PerformanceData* pd = j->second;
|
||||
std::lock_guard<std::mutex> guard(pd->lock);
|
||||
pd->minTime = 0;
|
||||
pd->maxTime = 0;
|
||||
pd->totalTime = 0;
|
||||
pd->count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PerformanceMonitorOperation::PerformanceMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack) : data(data), name(name), stack(stack)
|
||||
{
|
||||
started = (std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now())).time_since_epoch();
|
||||
}
|
||||
|
||||
void PerformanceMonitorOperation::finish()
|
||||
{
|
||||
std::chrono::milliseconds finished = (std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now())).time_since_epoch();
|
||||
uint32 elapsed = (finished - started).count();
|
||||
|
||||
std::lock_guard<std::mutex> guard(data->lock);
|
||||
if (elapsed > 0)
|
||||
{
|
||||
if (!data->minTime || data->minTime > elapsed)
|
||||
data->minTime = elapsed;
|
||||
|
||||
if (!data->maxTime || data->maxTime < elapsed)
|
||||
data->maxTime = elapsed;
|
||||
|
||||
data->totalTime += elapsed;
|
||||
}
|
||||
|
||||
++data->count;
|
||||
|
||||
if (stack)
|
||||
{
|
||||
stack->erase(std::remove(stack->begin(), stack->end(), name), stack->end());
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
72
src/PerformanceMonitor.h
Normal file
72
src/PerformanceMonitor.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PERFORMANCEMONITOR_H
|
||||
#define _PLAYERBOT_PERFORMANCEMONITOR_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<std::string> PerformanceStack;
|
||||
|
||||
struct PerformanceData
|
||||
{
|
||||
uint32 minTime;
|
||||
uint32 maxTime;
|
||||
uint32 totalTime;
|
||||
uint32 count;
|
||||
std::mutex lock;
|
||||
};
|
||||
|
||||
enum PerformanceMetric
|
||||
{
|
||||
PERF_MON_TRIGGER,
|
||||
PERF_MON_VALUE,
|
||||
PERF_MON_ACTION,
|
||||
PERF_MON_RNDBOT,
|
||||
PERF_MON_TOTAL
|
||||
};
|
||||
|
||||
class PerformanceMonitorOperation
|
||||
{
|
||||
public:
|
||||
PerformanceMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack);
|
||||
void finish();
|
||||
|
||||
private:
|
||||
PerformanceData* data;
|
||||
std::string const name;
|
||||
PerformanceStack* stack;
|
||||
std::chrono::milliseconds started;
|
||||
};
|
||||
|
||||
class PerformanceMonitor
|
||||
{
|
||||
public:
|
||||
PerformanceMonitor() { };
|
||||
virtual ~PerformanceMonitor() { };
|
||||
static PerformanceMonitor* instance()
|
||||
{
|
||||
static PerformanceMonitor instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
public:
|
||||
PerformanceMonitorOperation* start(PerformanceMetric metric, std::string const name, PerformanceStack* stack = nullptr);
|
||||
void PrintStats(bool perTick = false, bool fullStack = false);
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
std::map<PerformanceMetric, std::map<std::string, PerformanceData*> > data;
|
||||
std::mutex lock;
|
||||
};
|
||||
|
||||
#define sPerformanceMonitor PerformanceMonitor::instance()
|
||||
|
||||
#endif
|
||||
3408
src/PlayerbotAI.cpp
Normal file
3408
src/PlayerbotAI.cpp
Normal file
File diff suppressed because it is too large
Load Diff
392
src/PlayerbotAI.h
Normal file
392
src/PlayerbotAI.h
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERbotAI_H
|
||||
#define _PLAYERBOT_PLAYERbotAI_H
|
||||
|
||||
#include "Chat.h"
|
||||
#include "ChatHelper.h"
|
||||
#include "ChatFilter.h"
|
||||
#include "Common.h"
|
||||
#include "Event.h"
|
||||
#include "PlayerbotAIBase.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "PlayerbotSecurity.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
|
||||
class AiObjectContext;
|
||||
class Creature;
|
||||
class Engine;
|
||||
class ExternalEventHelper;
|
||||
class Gameobject;
|
||||
class Item;
|
||||
class ObjectGuid;
|
||||
class Player;
|
||||
class PlayerbotMgr;
|
||||
class Spell;
|
||||
class SpellInfo;
|
||||
class Unit;
|
||||
class WorldObject;
|
||||
class WorldPosition;
|
||||
|
||||
struct CreatureData;
|
||||
struct GameObjectData;
|
||||
|
||||
enum StrategyType : uint32;
|
||||
|
||||
enum HealingItemDisplayId
|
||||
{
|
||||
HEALTHSTONE_DISPLAYID = 8026,
|
||||
MAJOR_HEALING_POTION = 24152,
|
||||
WHIPPER_ROOT_TUBER = 21974,
|
||||
NIGHT_DRAGON_BREATH = 21975,
|
||||
LIMITED_INVULNERABILITY_POTION = 24213,
|
||||
GREATER_DREAMLESS_SLEEP_POTION = 17403,
|
||||
SUPERIOR_HEALING_POTION = 15714,
|
||||
CRYSTAL_RESTORE = 2516,
|
||||
DREAMLESS_SLEEP_POTION = 17403,
|
||||
GREATER_HEALING_POTION = 15713,
|
||||
HEALING_POTION = 15712,
|
||||
LESSER_HEALING_POTION = 15711,
|
||||
DISCOLORED_HEALING_POTION = 15736,
|
||||
MINOR_HEALING_POTION = 15710,
|
||||
VOLATILE_HEALING_POTION = 24212,
|
||||
SUPER_HEALING_POTION = 37807,
|
||||
CRYSTAL_HEALING_POTION = 47132,
|
||||
FEL_REGENERATION_POTION = 37864,
|
||||
MAJOR_DREAMLESS_SLEEP_POTION = 37845
|
||||
};
|
||||
|
||||
enum BotState
|
||||
{
|
||||
BOT_STATE_COMBAT = 0,
|
||||
BOT_STATE_NON_COMBAT = 1,
|
||||
BOT_STATE_DEAD = 2,
|
||||
|
||||
BOT_STATE_MAX
|
||||
};
|
||||
|
||||
bool IsAlliance(uint8 race);
|
||||
|
||||
class PlayerbotChatHandler: protected ChatHandler
|
||||
{
|
||||
public:
|
||||
explicit PlayerbotChatHandler(Player* pMasterPlayer);
|
||||
void sysmessage(std::string const str) { SendSysMessage(str.c_str()); }
|
||||
uint32 extractQuestId(std::string const str);
|
||||
uint32 extractSpellId(std::string const str)
|
||||
{
|
||||
char* source = (char*)str.c_str();
|
||||
return extractSpellIdFromLink(source);
|
||||
}
|
||||
};
|
||||
|
||||
class MinValueCalculator
|
||||
{
|
||||
public:
|
||||
MinValueCalculator(float def = 0.0f) : param(nullptr), minValue(def) { }
|
||||
|
||||
void probe(float value, void* p)
|
||||
{
|
||||
if (!param || minValue >= value)
|
||||
{
|
||||
minValue = value;
|
||||
param = p;
|
||||
}
|
||||
}
|
||||
|
||||
void* param;
|
||||
float minValue;
|
||||
};
|
||||
|
||||
enum RoguePoisonDisplayId
|
||||
{
|
||||
DEADLY_POISON_DISPLAYID = 13707,
|
||||
INSTANT_POISON_DISPLAYID = 13710,
|
||||
WOUND_POISON_DISPLAYID = 37278
|
||||
};
|
||||
|
||||
enum SharpeningStoneDisplayId
|
||||
{
|
||||
ROUGH_SHARPENING_DISPLAYID = 24673,
|
||||
COARSE_SHARPENING_DISPLAYID = 24674,
|
||||
HEAVY_SHARPENING_DISPLAYID = 24675,
|
||||
SOLID_SHARPENING_DISPLAYID = 24676,
|
||||
DENSE_SHARPENING_DISPLAYID = 24677,
|
||||
CONSECRATED_SHARPENING_DISPLAYID = 24674, // will not be used because bot can not know if it will face undead targets
|
||||
ELEMENTAL_SHARPENING_DISPLAYID = 21072,
|
||||
FEL_SHARPENING_DISPLAYID = 39192,
|
||||
ADAMANTITE_SHARPENING_DISPLAYID = 39193
|
||||
};
|
||||
|
||||
enum WeightStoneDisplayId
|
||||
{
|
||||
ROUGH_WEIGHTSTONE_DISPLAYID = 24683,
|
||||
COARSE_WEIGHTSTONE_DISPLAYID = 24684,
|
||||
HEAVY_WEIGHTSTONE_DISPLAYID = 24685,
|
||||
SOLID_WEIGHTSTONE_DISPLAYID = 24686,
|
||||
DENSE_WEIGHTSTONE_DISPLAYID = 24687,
|
||||
FEL_WEIGHTSTONE_DISPLAYID = 39548,
|
||||
ADAMANTITE_WEIGHTSTONE_DISPLAYID = 39549
|
||||
};
|
||||
|
||||
enum WizardOilDisplayId
|
||||
{
|
||||
MINOR_WIZARD_OIL = 9731,
|
||||
LESSER_WIZARD_OIL = 47903,
|
||||
BRILLIANT_WIZARD_OIL = 47901,
|
||||
WIZARD_OIL = 47905,
|
||||
SUPERIOR_WIZARD_OIL = 47904,
|
||||
/// Blessed Wizard Oil = 26865 //scourge inv
|
||||
};
|
||||
|
||||
enum ManaOilDisplayId
|
||||
{
|
||||
MINOR_MANA_OIL = 34492,
|
||||
LESSER_MANA_OIL = 47902,
|
||||
BRILLIANT_MANA_OIL = 41488,
|
||||
SUPERIOR_MANA_OIL = 36862
|
||||
};
|
||||
|
||||
enum ShieldWardDisplayId
|
||||
{
|
||||
LESSER_WARD_OFSHIELDING = 38759,
|
||||
GREATER_WARD_OFSHIELDING = 38760
|
||||
};
|
||||
|
||||
enum class BotTypeNumber : uint8
|
||||
{
|
||||
ACTIVITY_TYPE_NUMBER = 1,
|
||||
GROUPER_TYPE_NUMBER = 2,
|
||||
GUILDER_TYPE_NUMBER = 3,
|
||||
};
|
||||
|
||||
enum class GrouperType : uint8
|
||||
{
|
||||
SOLO = 0,
|
||||
MEMBER = 1,
|
||||
LEADER_2 = 2,
|
||||
LEADER_3 = 3,
|
||||
LEADER_4 = 4,
|
||||
LEADER_5 = 5
|
||||
};
|
||||
|
||||
enum class GuilderType : uint8
|
||||
{
|
||||
SOLO = 0,
|
||||
TINY = 30,
|
||||
SMALL = 50,
|
||||
MEDIUM = 70,
|
||||
LARGE = 120,
|
||||
HUGE = 250
|
||||
};
|
||||
|
||||
enum ActivityType
|
||||
{
|
||||
GRIND_ACTIVITY = 1,
|
||||
RPG_ACTIVITY = 2,
|
||||
TRAVEL_ACTIVITY = 3,
|
||||
OUT_OF_PARTY_ACTIVITY = 4,
|
||||
PACKET_ACTIVITY = 5,
|
||||
DETAILED_MOVE_ACTIVITY = 6,
|
||||
PARTY_ACTIVITY = 7,
|
||||
ALL_ACTIVITY = 8,
|
||||
|
||||
MAX_ACTIVITY_TYPE
|
||||
};
|
||||
|
||||
enum BotRoles : uint8
|
||||
{
|
||||
BOT_ROLE_NONE = 0x00,
|
||||
BOT_ROLE_TANK = 0x01,
|
||||
BOT_ROLE_HEALER = 0x02,
|
||||
BOT_ROLE_DPS = 0x04
|
||||
};
|
||||
|
||||
class PacketHandlingHelper
|
||||
{
|
||||
public:
|
||||
void AddHandler(uint16 opcode, std::string const handler);
|
||||
void Handle(ExternalEventHelper &helper);
|
||||
void AddPacket(WorldPacket const& packet);
|
||||
|
||||
private:
|
||||
std::map<uint16, std::string> handlers;
|
||||
std::stack<WorldPacket> queue;
|
||||
};
|
||||
|
||||
class ChatCommandHolder
|
||||
{
|
||||
public:
|
||||
ChatCommandHolder(std::string const command, Player* owner = nullptr, uint32 type = CHAT_MSG_WHISPER, time_t time = 0) : command(command), owner(owner), type(type), time(time) { }
|
||||
ChatCommandHolder(ChatCommandHolder const& other) : command(other.command), owner(other.owner), type(other.type), time(other.time) { }
|
||||
|
||||
std::string const GetCommand() { return command; }
|
||||
Player* GetOwner() { return owner; }
|
||||
uint32 GetType() { return type; }
|
||||
time_t GetTime() { return time; }
|
||||
|
||||
private:
|
||||
std::string const command;
|
||||
Player* owner;
|
||||
uint32 type;
|
||||
time_t time;
|
||||
};
|
||||
|
||||
class PlayerbotAI : public PlayerbotAIBase
|
||||
{
|
||||
public:
|
||||
PlayerbotAI();
|
||||
PlayerbotAI(Player* bot);
|
||||
virtual ~PlayerbotAI();
|
||||
|
||||
void UpdateAI(uint32 elapsed, bool minimal = false) override;
|
||||
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
|
||||
|
||||
std::string const HandleRemoteCommand(std::string const command);
|
||||
void HandleCommand(uint32 type, std::string const text, Player* fromPlayer);
|
||||
void HandleBotOutgoingPacket(WorldPacket const& packet);
|
||||
void HandleMasterIncomingPacket(WorldPacket const& packet);
|
||||
void HandleMasterOutgoingPacket(WorldPacket const& packet);
|
||||
void HandleTeleportAck();
|
||||
void ChangeEngine(BotState type);
|
||||
void DoNextAction(bool minimal = false);
|
||||
virtual bool DoSpecificAction(std::string const name, Event event = Event(), bool silent = false, std::string const qualifier = "");
|
||||
void ChangeStrategy(std::string const name, BotState type);
|
||||
void ClearStrategies(BotState type);
|
||||
std::vector<std::string> GetStrategies(BotState type);
|
||||
bool ContainsStrategy(StrategyType type);
|
||||
bool HasStrategy(std::string const name, BotState type);
|
||||
BotState GetState() { return currentState; };
|
||||
void ResetStrategies(bool load = true);
|
||||
void ReInitCurrentEngine();
|
||||
void Reset(bool full = false);
|
||||
bool IsTank(Player* player);
|
||||
bool IsHeal(Player* player);
|
||||
bool IsRanged(Player* player);
|
||||
Creature* GetCreature(ObjectGuid guid);
|
||||
Unit* GetUnit(ObjectGuid guid);
|
||||
Player* GetPlayer(ObjectGuid guid);
|
||||
static Unit* GetUnit(CreatureData const* creatureData);
|
||||
GameObject* GetGameObject(ObjectGuid guid);
|
||||
static GameObject* GetGameObject(GameObjectData const* gameObjectData);
|
||||
WorldObject* GetWorldObject(ObjectGuid guid);
|
||||
bool TellMaster(std::ostringstream& stream, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
|
||||
bool TellMaster(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
|
||||
bool TellMasterNoFacing(std::ostringstream& stream, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
|
||||
bool TellMasterNoFacing(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
|
||||
bool TellError(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
|
||||
void SpellInterrupted(uint32 spellid);
|
||||
int32 CalculateGlobalCooldown(uint32 spellid);
|
||||
void InterruptSpell();
|
||||
void RemoveAura(std::string const name);
|
||||
void RemoveShapeshift();
|
||||
void WaitForSpellCast(Spell* spell);
|
||||
bool PlaySound(uint32 emote);
|
||||
bool PlayEmote(uint32 emote);
|
||||
void Ping(float x, float y);
|
||||
Item* FindPoison() const;
|
||||
Item* FindBandage() const;
|
||||
Item* FindConsumable(uint32 displayId) const;
|
||||
Item* FindStoneFor(Item* weapon) const;
|
||||
Item* FindOilFor(Item* weapon) const;
|
||||
void ImbueItem(Item* item, uint32 targetFlag, ObjectGuid targetGUID);
|
||||
void ImbueItem(Item* item, uint8 targetInventorySlot);
|
||||
void ImbueItem(Item* item, Unit* target);
|
||||
void ImbueItem(Item* item);
|
||||
void EnchantItemT(uint32 spellid, uint8 slot);
|
||||
uint32 GetBuffedCount(Player* player, std::string const spellname);
|
||||
|
||||
virtual bool CanCastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr);
|
||||
virtual bool CastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr);
|
||||
virtual bool HasAura(std::string const spellName, Unit* player, bool maxStack = false);
|
||||
virtual bool HasAnyAuraOf(Unit* player, ...);
|
||||
|
||||
virtual bool IsInterruptableSpellCasting(Unit* player, std::string const spell);
|
||||
virtual bool HasAuraToDispel(Unit* player, uint32 dispelType);
|
||||
bool CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell = true, Item* itemTarget = nullptr);
|
||||
bool CanCastSpell(uint32 spellid, GameObject* goTarget, uint8 effectMask, bool checkHasSpell = true);
|
||||
bool CanCastSpell(uint32 spellid, float x, float y, float z, uint8 effectMask, bool checkHasSpell = true, Item* itemTarget = nullptr);
|
||||
|
||||
bool HasAura(uint32 spellId, Unit const* player);
|
||||
bool CastSpell(uint32 spellId, Unit* target, Item* itemTarget = nullptr);
|
||||
bool CastSpell(uint32 spellId, float x, float y, float z, Item* itemTarget = nullptr);
|
||||
bool canDispel(SpellInfo const* spellInfo, uint32 dispelType);
|
||||
|
||||
bool CanCastVehicleSpell(uint32 spellid, Unit* target);
|
||||
bool CastVehicleSpell(uint32 spellId, Unit* target);
|
||||
bool CastVehicleSpell(uint32 spellId, float x, float y, float z);
|
||||
bool IsInVehicle(bool canControl = false, bool canCast = false, bool canAttack = false, bool canTurn = false, bool fixed = false);
|
||||
|
||||
uint32 GetEquipGearScore(Player* player, bool withBags, bool withBank);
|
||||
bool HasSkill(SkillType skill);
|
||||
bool IsAllowedCommand(std::string const text);
|
||||
float GetRange(std::string const type);
|
||||
|
||||
Player* GetBot() { return bot; }
|
||||
Player* GetMaster() { return master; }
|
||||
|
||||
//Checks if the bot is really a player. Players always have themselves as master.
|
||||
bool IsRealPlayer() { return master ? (master == bot) : false; }
|
||||
//Bot has a master that is a player.
|
||||
bool HasRealPlayerMaster();
|
||||
//Bot has a master that is activly playing.
|
||||
bool HasActivePlayerMaster();
|
||||
//Get the group leader or the master of the bot.
|
||||
//Checks if the bot is summoned as alt of a player
|
||||
bool IsAlt();
|
||||
Player* GetGroupMaster();
|
||||
//Returns a semi-random (cycling) number that is fixed for each bot.
|
||||
uint32 GetFixedBotNumer(BotTypeNumber typeNumber, uint32 maxNum = 100, float cyclePerMin = 1);
|
||||
GrouperType GetGrouperType();
|
||||
GuilderType GetGuilderType();
|
||||
bool HasPlayerNearby(WorldPosition* pos, float range = sPlayerbotAIConfig->reactDistance);
|
||||
bool HasPlayerNearby(float range = sPlayerbotAIConfig->reactDistance);
|
||||
bool HasManyPlayersNearby(uint32 trigerrValue = 20, float range = sPlayerbotAIConfig->sightDistance);
|
||||
bool AllowActive(ActivityType activityType);
|
||||
bool AllowActivity(ActivityType activityType = ALL_ACTIVITY, bool checkNow = false);
|
||||
|
||||
bool HasCheat(BotCheatMask mask) { return ((uint32)mask & (uint32)cheatMask) != 0 || ((uint32)mask & (uint32)sPlayerbotAIConfig->botCheatMask) != 0; }
|
||||
BotCheatMask GetCheat() { return cheatMask; }
|
||||
void SetCheat(BotCheatMask mask) { cheatMask = mask; }
|
||||
|
||||
void SetMaster(Player* newMaster) { master = newMaster; }
|
||||
AiObjectContext* GetAiObjectContext() { return aiObjectContext; }
|
||||
ChatHelper* GetChatHelper() { return &chatHelper; }
|
||||
bool IsOpposing(Player* player);
|
||||
static bool IsOpposing(uint8 race1, uint8 race2);
|
||||
PlayerbotSecurity* GetSecurity() { return &security; }
|
||||
|
||||
private:
|
||||
void _fillGearScoreData(Player* player, Item* item, std::vector<uint32>* gearScore, uint32& twoHandScore);
|
||||
bool IsTellAllowed(PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
|
||||
|
||||
protected:
|
||||
Player* bot;
|
||||
Player* master;
|
||||
uint32 accountId;
|
||||
AiObjectContext* aiObjectContext;
|
||||
Engine* currentEngine;
|
||||
Engine* engines[BOT_STATE_MAX];
|
||||
BotState currentState;
|
||||
ChatHelper chatHelper;
|
||||
std::queue<ChatCommandHolder> chatCommands;
|
||||
PacketHandlingHelper botOutgoingPacketHandlers;
|
||||
PacketHandlingHelper masterIncomingPacketHandlers;
|
||||
PacketHandlingHelper masterOutgoingPacketHandlers;
|
||||
CompositeChatFilter chatFilter;
|
||||
PlayerbotSecurity security;
|
||||
std::map<std::string, time_t> whispers;
|
||||
std::pair<ChatMsg, time_t> currentChat;
|
||||
static std::set<std::string> unsecuredCommands;
|
||||
bool allowActive[MAX_ACTIVITY_TYPE];
|
||||
time_t allowActiveCheckTimer[MAX_ACTIVITY_TYPE];
|
||||
bool inCombat = false;
|
||||
BotCheatMask cheatMask = BotCheatMask::none;
|
||||
};
|
||||
|
||||
#endif
|
||||
19
src/PlayerbotAIAware.h
Normal file
19
src/PlayerbotAIAware.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERbotAIAWARE_H
|
||||
#define _PLAYERBOT_PLAYERbotAIAWARE_H
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class PlayerbotAIAware
|
||||
{
|
||||
public:
|
||||
PlayerbotAIAware(PlayerbotAI* botAI) : botAI(botAI) { }
|
||||
|
||||
protected:
|
||||
PlayerbotAI* botAI;
|
||||
};
|
||||
|
||||
#endif
|
||||
67
src/PlayerbotAIBase.cpp
Normal file
67
src/PlayerbotAIBase.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "PlayerbotAIBase.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
PlayerbotAIBase::PlayerbotAIBase(bool isBotAI) : nextAICheckDelay(0), _isBotAI(isBotAI)
|
||||
{
|
||||
}
|
||||
|
||||
void PlayerbotAIBase::UpdateAI(uint32 elapsed, bool minimal)
|
||||
{
|
||||
if (nextAICheckDelay > elapsed)
|
||||
nextAICheckDelay -= elapsed;
|
||||
else
|
||||
nextAICheckDelay = 0;
|
||||
|
||||
if (!CanUpdateAI())
|
||||
return;
|
||||
|
||||
UpdateAIInternal(elapsed, minimal);
|
||||
YieldThread();
|
||||
}
|
||||
|
||||
void PlayerbotAIBase::SetNextCheckDelay(uint32 const delay)
|
||||
{
|
||||
if (nextAICheckDelay < delay)
|
||||
LOG_DEBUG("playerbots", "Setting lesser delay {} -> {}", nextAICheckDelay, delay);
|
||||
|
||||
nextAICheckDelay = delay;
|
||||
|
||||
if (nextAICheckDelay > sPlayerbotAIConfig->globalCoolDown)
|
||||
LOG_DEBUG("playerbots", "std::set next check delay: {}", nextAICheckDelay);
|
||||
}
|
||||
|
||||
void PlayerbotAIBase::IncreaseNextCheckDelay(uint32 delay)
|
||||
{
|
||||
nextAICheckDelay += delay;
|
||||
|
||||
if (nextAICheckDelay > sPlayerbotAIConfig->globalCoolDown)
|
||||
LOG_DEBUG("playerbots", "increase next check delay: {}", nextAICheckDelay);
|
||||
}
|
||||
|
||||
bool PlayerbotAIBase::CanUpdateAI()
|
||||
{
|
||||
return nextAICheckDelay < 100;
|
||||
}
|
||||
|
||||
void PlayerbotAIBase::YieldThread(bool delay)
|
||||
{
|
||||
if (nextAICheckDelay < sPlayerbotAIConfig->reactDelay)
|
||||
nextAICheckDelay = sPlayerbotAIConfig->reactDelay;
|
||||
|
||||
if (delay && nextAICheckDelay <= sPlayerbotAIConfig->reactDelay * 5)
|
||||
nextAICheckDelay = sPlayerbotAIConfig->reactDelay * 5;
|
||||
}
|
||||
|
||||
bool PlayerbotAIBase::IsActive()
|
||||
{
|
||||
return nextAICheckDelay < sPlayerbotAIConfig->maxWaitForMove;
|
||||
}
|
||||
|
||||
bool PlayerbotAIBase::IsBotAI() const
|
||||
{
|
||||
return _isBotAI;
|
||||
}
|
||||
31
src/PlayerbotAIBase.h
Normal file
31
src/PlayerbotAIBase.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERBOTAIBASE_H
|
||||
#define _PLAYERBOT_PLAYERBOTAIBASE_H
|
||||
|
||||
#include "Define.h"
|
||||
|
||||
class PlayerbotAIBase
|
||||
{
|
||||
public:
|
||||
PlayerbotAIBase(bool isBotAI);
|
||||
|
||||
bool CanUpdateAI();
|
||||
void SetNextCheckDelay(uint32 const delay);
|
||||
void IncreaseNextCheckDelay(uint32 delay);
|
||||
void YieldThread(bool delay = false);
|
||||
virtual void UpdateAI(uint32 elapsed, bool minimal = false);
|
||||
virtual void UpdateAIInternal(uint32 elapsed, bool minimal = false) = 0;
|
||||
bool IsActive();
|
||||
bool IsBotAI() const;
|
||||
|
||||
protected:
|
||||
uint32 nextAICheckDelay;
|
||||
|
||||
private:
|
||||
bool _isBotAI;
|
||||
};
|
||||
|
||||
#endif
|
||||
481
src/PlayerbotAIConfig.cpp
Normal file
481
src/PlayerbotAIConfig.cpp
Normal file
@ -0,0 +1,481 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Config.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PlayerbotFactory.h"
|
||||
#include "RandomItemMgr.h"
|
||||
#include "RandomPlayerbotFactory.h"
|
||||
#include "TalentSpec.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class T>
|
||||
void LoadList(std::string const value, T& list)
|
||||
{
|
||||
std::vector<std::string> ids = split(value, ',');
|
||||
for (std::vector<std::string>::iterator i = ids.begin(); i != ids.end(); i++)
|
||||
{
|
||||
uint32 id = atoi((*i).c_str());
|
||||
if (!id)
|
||||
continue;
|
||||
|
||||
list.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void LoadListString(std::string const value, T& list)
|
||||
{
|
||||
std::vector<std::string> strings = split(value, ',');
|
||||
for (std::vector<std::string>::iterator i = strings.begin(); i != strings.end(); i++)
|
||||
{
|
||||
std::string const string = *i;
|
||||
if (string.empty())
|
||||
continue;
|
||||
|
||||
list.push_back(string);
|
||||
}
|
||||
}
|
||||
|
||||
bool PlayerbotAIConfig::Initialize()
|
||||
{
|
||||
LOG_INFO("server.loading", "Initializing AI Playerbots by ike3, based on the original Playerbots by blueboy");
|
||||
|
||||
enabled = sConfigMgr->GetBoolDefault("AiPlayerbot.Enabled", true);
|
||||
if (!enabled)
|
||||
{
|
||||
LOG_INFO("server.loading", "AI Playerbots is Disabled in aiplayerbot.conf");
|
||||
return false;
|
||||
}
|
||||
|
||||
globalCoolDown = sConfigMgr->GetIntDefault("AiPlayerbot.GlobalCooldown", 1500);
|
||||
maxWaitForMove = sConfigMgr->GetIntDefault("AiPlayerbot.MaxWaitForMove", 5000);
|
||||
expireActionTime = sConfigMgr->GetIntDefault("AiPlayerbot.ExpireActionTime", 5000);
|
||||
dispelAuraDuration = sConfigMgr->GetIntDefault("AiPlayerbot.DispelAuraDuration", 7000);
|
||||
reactDelay = sConfigMgr->GetIntDefault("AiPlayerbot.ReactDelay", 500);
|
||||
passiveDelay = sConfigMgr->GetIntDefault("AiPlayerbot.PassiveDelay", 10000);
|
||||
repeatDelay = sConfigMgr->GetIntDefault("AiPlayerbot.RepeatDelay", 5000);
|
||||
errorDelay = sConfigMgr->GetIntDefault("AiPlayerbot.ErrorDelay", 5000);
|
||||
rpgDelay = sConfigMgr->GetIntDefault("AiPlayerbot.RpgDelay", 10000);
|
||||
sitDelay = sConfigMgr->GetIntDefault("AiPlayerbot.SitDelay", 30000);
|
||||
returnDelay = sConfigMgr->GetIntDefault("AiPlayerbot.ReturnDelay", 7000);
|
||||
lootDelay = sConfigMgr->GetIntDefault("AiPlayerbot.LootDelay", 1000);
|
||||
|
||||
farDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.FarDistance", 20.0f);
|
||||
sightDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.SightDistance", 75.0f);
|
||||
spellDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.SpellDistance", 22.0f);
|
||||
shootDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.ShootDistance", 25.0f);
|
||||
healDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.HealDistance", 20.0f);
|
||||
lootDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.LootDistance", 15.0f);
|
||||
fleeDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.FleeDistance", 7.5f);
|
||||
aggroDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.AggroDistance", 22.0f);
|
||||
tooCloseDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.TooCloseDistance", 5.0f);
|
||||
meleeDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.MeleeDistance", 1.5f);
|
||||
followDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.FollowDistance", 1.5f);
|
||||
whisperDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.WhisperDistance", 6000.0f);
|
||||
contactDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.ContactDistance", 0.5f);
|
||||
aoeRadius = sConfigMgr->GetFloatDefault("AiPlayerbot.AoeRadius", 5.0f);
|
||||
rpgDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.RpgDistance", 200.0f);
|
||||
grindDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.GrindDistance", 75.0f);
|
||||
reactDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.ReactDistance", 150.0f);
|
||||
|
||||
criticalHealth = sConfigMgr->GetIntDefault("AiPlayerbot.CriticalHealth", 20);
|
||||
lowHealth = sConfigMgr->GetIntDefault("AiPlayerbot.LowHealth", 45);
|
||||
mediumHealth = sConfigMgr->GetIntDefault("AiPlayerbot.MediumHealth", 65);
|
||||
almostFullHealth = sConfigMgr->GetIntDefault("AiPlayerbot.AlmostFullHealth", 85);
|
||||
lowMana = sConfigMgr->GetIntDefault("AiPlayerbot.LowMana", 15);
|
||||
mediumMana = sConfigMgr->GetIntDefault("AiPlayerbot.MediumMana", 40);
|
||||
|
||||
randomGearLoweringChance = sConfigMgr->GetFloatDefault("AiPlayerbot.RandomGearLoweringChance", 0.15f);
|
||||
randomBotMaxLevelChance = sConfigMgr->GetFloatDefault("AiPlayerbot.RandomBotMaxLevelChance", 0.15f);
|
||||
randomBotRpgChance = sConfigMgr->GetFloatDefault("AiPlayerbot.RandomBotRpgChance", 0.20f);
|
||||
|
||||
iterationsPerTick = sConfigMgr->GetIntDefault("AiPlayerbot.IterationsPerTick", 100);
|
||||
|
||||
allowGuildBots = sConfigMgr->GetBoolDefault("AiPlayerbot.AllowGuildBots", true);
|
||||
|
||||
randomBotMapsAsString = sConfigMgr->GetStringDefault("AiPlayerbot.RandomBotMaps", "0,1,530,571");
|
||||
LoadList<std::vector<uint32>>(randomBotMapsAsString, randomBotMaps);
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault("AiPlayerbot.RandomBotQuestItems", "6948,5175,5176,5177,5178,16309,12382,13704,11000"), randomBotQuestItems);
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault("AiPlayerbot.RandomBotSpellIds", "1"), randomBotSpellIds);
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault("AiPlayerbot.PvpProhibitedZoneIds", "2255,656,2361,2362,2363,976,35,2268,3425,392,541,1446,3828,3712,3738,3565,3539,3623,4152,3988,4658,4284,4418,4436,4275,4323"), pvpProhibitedZoneIds);
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault("AiPlayerbot.RandomBotQuestIds", "7848,3802,5505,6502,7761"), randomBotQuestIds);
|
||||
|
||||
botAutologin = sConfigMgr->GetBoolDefault("AiPlayerbot.BotAutologin", false);
|
||||
randomBotAutologin = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotAutologin", true);
|
||||
minRandomBots = sConfigMgr->GetIntDefault("AiPlayerbot.MinRandomBots", 50);
|
||||
maxRandomBots = sConfigMgr->GetIntDefault("AiPlayerbot.MaxRandomBots", 200);
|
||||
randomBotUpdateInterval = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotUpdateInterval", MINUTE);
|
||||
randomBotCountChangeMinInterval = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE);
|
||||
randomBotCountChangeMaxInterval = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotCountChangeMaxInterval", 2 * HOUR);
|
||||
minRandomBotInWorldTime = sConfigMgr->GetIntDefault("AiPlayerbot.MinRandomBotInWorldTime", 2 * HOUR);
|
||||
maxRandomBotInWorldTime = sConfigMgr->GetIntDefault("AiPlayerbot.MaxRandomBotInWorldTime", 12 * HOUR);
|
||||
minRandomBotRandomizeTime = sConfigMgr->GetIntDefault("AiPlayerbot.MinRandomBotRandomizeTime", 2 * HOUR);
|
||||
maxRandomBotRandomizeTime = sConfigMgr->GetIntDefault("AiPlayerbot.MaxRandomRandomizeTime", 14 * 24 * HOUR);
|
||||
minRandomBotChangeStrategyTime = sConfigMgr->GetIntDefault("AiPlayerbot.MinRandomBotChangeStrategyTime", 30 * MINUTE);
|
||||
maxRandomBotChangeStrategyTime = sConfigMgr->GetIntDefault("AiPlayerbot.MaxRandomBotChangeStrategyTime", 2 * HOUR);
|
||||
minRandomBotReviveTime = sConfigMgr->GetIntDefault("AiPlayerbot.MinRandomBotReviveTime", MINUTE);
|
||||
maxRandomBotReviveTime = sConfigMgr->GetIntDefault("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE);
|
||||
randomBotTeleportDistance = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotTeleportDistance", 100);
|
||||
randomBotsPerInterval = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotsPerInterval", MINUTE);
|
||||
minRandomBotsPriceChangeInterval = sConfigMgr->GetIntDefault("AiPlayerbot.MinRandomBotsPriceChangeInterval", 2 * HOUR);
|
||||
maxRandomBotsPriceChangeInterval = sConfigMgr->GetIntDefault("AiPlayerbot.MaxRandomBotsPriceChangeInterval", 48 * HOUR);
|
||||
randomBotJoinLfg = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotJoinLfg", true);
|
||||
randomBotJoinBG = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotJoinBG", true);
|
||||
logInGroupOnly = sConfigMgr->GetBoolDefault("AiPlayerbot.LogInGroupOnly", true);
|
||||
logValuesPerTick = sConfigMgr->GetBoolDefault("AiPlayerbot.LogValuesPerTick", false);
|
||||
fleeingEnabled = sConfigMgr->GetBoolDefault("AiPlayerbot.FleeingEnabled", true);
|
||||
summonAtInnkeepersEnabled = sConfigMgr->GetBoolDefault("AiPlayerbot.SummonAtInnkeepersEnabled", true);
|
||||
randomBotMinLevel = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotMinLevel", 1);
|
||||
randomBotMaxLevel = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotMaxLevel", 80);
|
||||
randomBotLoginAtStartup = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotLoginAtStartup", true);
|
||||
randomBotTeleLevel = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotTeleLevel", 5);
|
||||
openGoSpell = sConfigMgr->GetIntDefault("AiPlayerbot.OpenGoSpell", 6477);
|
||||
|
||||
randomChangeMultiplier = sConfigMgr->GetFloatDefault("AiPlayerbot.RandomChangeMultiplier", 1.0);
|
||||
|
||||
randomBotCombatStrategies = sConfigMgr->GetStringDefault("AiPlayerbot.RandomBotCombatStrategies", "-threat");
|
||||
randomBotNonCombatStrategies = sConfigMgr->GetStringDefault("AiPlayerbot.RandomBotNonCombatStrategies", "");
|
||||
combatStrategies = sConfigMgr->GetStringDefault("AiPlayerbot.CombatStrategies", "+custom::say");
|
||||
nonCombatStrategies = sConfigMgr->GetStringDefault("AiPlayerbot.NonCombatStrategies", "+custom::say,+return");
|
||||
|
||||
commandPrefix = sConfigMgr->GetStringDefault("AiPlayerbot.CommandPrefix", "");
|
||||
commandSeparator = sConfigMgr->GetStringDefault("AiPlayerbot.CommandSeparator", "\\\\");
|
||||
|
||||
commandServerPort = sConfigMgr->GetIntDefault("AiPlayerbot.CommandServerPort", 8888);
|
||||
perfMonEnabled = sConfigMgr->GetBoolDefault("AiPlayerbot.PerfMonEnabled", false);
|
||||
|
||||
LOG_INFO("server.loading", "---------------------------------------");
|
||||
LOG_INFO("server.loading", " Loading TalentSpecs ");
|
||||
LOG_INFO("server.loading", "---------------------------------------");
|
||||
|
||||
for (uint32 cls = 1; cls < MAX_CLASSES; ++cls)
|
||||
{
|
||||
classSpecs[cls] = ClassSpecs(1 << (cls - 1));
|
||||
|
||||
for (uint32 spec = 0; spec < MAX_LEVEL; ++spec)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "AiPlayerbot.PremadeSpecName." << cls << "." << spec;
|
||||
|
||||
std::string const specName = sConfigMgr->GetStringDefault(os.str().c_str(), "", false);
|
||||
if (!specName.empty())
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "AiPlayerbot.PremadeSpecProb." << cls << "." << spec;
|
||||
uint32 probability = sConfigMgr->GetIntDefault(os.str().c_str(), 100, false);
|
||||
|
||||
TalentPath talentPath(spec, specName, probability);
|
||||
|
||||
for (uint32 level = 10; level <= 80; level++)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "AiPlayerbot.PremadeSpecLink." << cls << "." << spec << "." << level;
|
||||
|
||||
std::string specLink = sConfigMgr->GetStringDefault(os.str().c_str(), "", false);
|
||||
specLink = specLink.substr(0, specLink.find("#", 0));;
|
||||
specLink = specLink.substr(0, specLink.find(" ", 0));;
|
||||
|
||||
if (!specLink.empty())
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
// Ignore bad specs.
|
||||
if (!classSpecs[cls].baseSpec.CheckTalentLink(specLink, &out))
|
||||
{
|
||||
LOG_ERROR("playerbots", "Error with premade spec link: {}", specLink.c_str());
|
||||
LOG_ERROR("playerbots", "{}", out.str().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
TalentSpec linkSpec(&classSpecs[cls].baseSpec, specLink);
|
||||
|
||||
if (!linkSpec.CheckTalents(level, &out))
|
||||
{
|
||||
LOG_ERROR("playerbots", "Error with premade spec: {}", specLink.c_str());
|
||||
LOG_ERROR("playerbots", "{}", out.str().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
talentPath.talentSpec.push_back(linkSpec);
|
||||
}
|
||||
}
|
||||
|
||||
// Only add paths that have atleast 1 spec.
|
||||
if (talentPath.talentSpec.size() > 0)
|
||||
classSpecs[cls].talentPath.push_back(talentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
botCheats.clear();
|
||||
LoadListString<std::vector<std::string>>(sConfigMgr->GetStringDefault("AiPlayerbot.BotCheats", "taxi"), botCheats);
|
||||
|
||||
botCheatMask = 0;
|
||||
|
||||
if (std::find(botCheats.begin(), botCheats.end(), "taxi") != botCheats.end())
|
||||
botCheatMask |= (uint32)BotCheatMask::taxi;
|
||||
if (std::find(botCheats.begin(), botCheats.end(), "gold") != botCheats.end())
|
||||
botCheatMask |= (uint32)BotCheatMask::gold;
|
||||
if (std::find(botCheats.begin(), botCheats.end(), "health") != botCheats.end())
|
||||
botCheatMask |= (uint32)BotCheatMask::health;
|
||||
if (std::find(botCheats.begin(), botCheats.end(), "mana") != botCheats.end())
|
||||
botCheatMask |= (uint32)BotCheatMask::mana;
|
||||
if (std::find(botCheats.begin(), botCheats.end(), "power") != botCheats.end())
|
||||
botCheatMask |= (uint32)BotCheatMask::power;
|
||||
|
||||
LoadListString<std::vector<std::string>>(sConfigMgr->GetStringDefault("AiPlayerbot.AllowedLogFiles", ""), allowedLogFiles);
|
||||
|
||||
worldBuffs.clear();
|
||||
|
||||
for (uint32 factionId = 0; factionId < 3; factionId++)
|
||||
{
|
||||
for (uint32 classId = 0; classId < MAX_CLASSES; classId++)
|
||||
{
|
||||
for (uint32 minLevel = 0; minLevel < MAX_LEVEL; minLevel++)
|
||||
{
|
||||
for (uint32 maxLevel = 0; maxLevel < MAX_LEVEL; maxLevel++)
|
||||
{
|
||||
loadWorldBuf(factionId, classId, minLevel, maxLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
randomBotAccountPrefix = sConfigMgr->GetStringDefault("AiPlayerbot.RandomBotAccountPrefix", "rndbot");
|
||||
randomBotAccountCount = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotAccountCount", 200);
|
||||
deleteRandomBotAccounts = sConfigMgr->GetBoolDefault("AiPlayerbot.DeleteRandomBotAccounts", false);
|
||||
randomBotGuildCount = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotGuildCount", 20);
|
||||
deleteRandomBotGuilds = sConfigMgr->GetBoolDefault("AiPlayerbot.DeleteRandomBotGuilds", false);
|
||||
|
||||
guildTaskEnabled = sConfigMgr->GetBoolDefault("AiPlayerbot.EnableGuildTasks", true);
|
||||
minGuildTaskChangeTime = sConfigMgr->GetIntDefault("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600);
|
||||
maxGuildTaskChangeTime = sConfigMgr->GetIntDefault("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600);
|
||||
minGuildTaskAdvertisementTime = sConfigMgr->GetIntDefault("AiPlayerbot.MinGuildTaskAdvertisementTime", 300);
|
||||
maxGuildTaskAdvertisementTime = sConfigMgr->GetIntDefault("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600);
|
||||
minGuildTaskRewardTime = sConfigMgr->GetIntDefault("AiPlayerbot.MinGuildTaskRewardTime", 300);
|
||||
maxGuildTaskRewardTime = sConfigMgr->GetIntDefault("AiPlayerbot.MaxGuildTaskRewardTime", 3600);
|
||||
guildTaskAdvertCleanupTime = sConfigMgr->GetIntDefault("AiPlayerbot.GuildTaskAdvertCleanupTime", 300);
|
||||
guildTaskKillTaskDistance = sConfigMgr->GetIntDefault("AiPlayerbot.GuildTaskKillTaskDistance", 2000);
|
||||
targetPosRecalcDistance = sConfigMgr->GetFloatDefault("AiPlayerbot.TargetPosRecalcDistance", 0.1f);
|
||||
|
||||
// cosmetics (by lidocain)
|
||||
randomBotShowCloak = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotShowCloak", true);
|
||||
randomBotShowHelmet = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotShowHelmet", true);
|
||||
|
||||
// SPP switches
|
||||
enableGreet = sConfigMgr->GetBoolDefault("AiPlayerbot.EnableGreet", true);
|
||||
disableRandomLevels = sConfigMgr->GetBoolDefault("AiPlayerbot.DisableRandomLevels", false);
|
||||
randomBotRandomPassword = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotRandomPassword", true);
|
||||
playerbotsXPrate = sConfigMgr->GetIntDefault("AiPlayerbot.KillXPRate", 1);
|
||||
botActiveAlone = sConfigMgr->GetIntDefault("AiPlayerbot.BotActiveAlone", 10);
|
||||
randombotsWalkingRPG = sConfigMgr->GetBoolDefault("AiPlayerbot.RandombotsWalkingRPG", false);
|
||||
randombotsWalkingRPGInDoors = sConfigMgr->GetBoolDefault("AiPlayerbot.RandombotsWalkingRPG.InDoors", false);
|
||||
minEnchantingBotLevel = sConfigMgr->GetIntDefault("AiPlayerbot.MinEnchantingBotLevel", 60);
|
||||
randombotStartingLevel = sConfigMgr->GetIntDefault("AiPlayerbot.RandombotStartingLevel", 5);
|
||||
gearscorecheck = sConfigMgr->GetBoolDefault("AiPlayerbot.GearScoreCheck", false);
|
||||
randomBotPreQuests = sConfigMgr->GetBoolDefault("AiPlayerbot.PreQuests", true);
|
||||
|
||||
// SPP automation
|
||||
autoPickReward = sConfigMgr->GetStringDefault("AiPlayerbot.AutoPickReward", "yes");
|
||||
autoEquipUpgradeLoot = sConfigMgr->GetBoolDefault("AiPlayerbot.AutoEquipUpgradeLoot", true);
|
||||
syncQuestWithPlayer = sConfigMgr->GetBoolDefault("AiPlayerbot.SyncQuestWithPlayer", false);
|
||||
syncQuestForPlayer = sConfigMgr->GetBoolDefault("AiPlayerbot.SyncQuestForPlayer", false);
|
||||
autoTrainSpells = sConfigMgr->GetStringDefault("AiPlayerbot.AutoTrainSpells", "yes");
|
||||
autoPickTalents = sConfigMgr->GetStringDefault("AiPlayerbot.AutoPickTalents", "full");
|
||||
autoLearnTrainerSpells = sConfigMgr->GetBoolDefault("AiPlayerbot.AutoLearnTrainerSpells", false);
|
||||
autoLearnQuestSpells = sConfigMgr->GetBoolDefault("AiPlayerbot.AutoLearnQuestSpells", false);
|
||||
autoDoQuests = sConfigMgr->GetBoolDefault("AiPlayerbot.AutoDoQuests", false);
|
||||
syncLevelWithPlayers = sConfigMgr->GetBoolDefault("AiPlayerbot.SyncLevelWithPlayers", false);
|
||||
randomBotSayWithoutMaster = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotSayWithoutMaster", false);
|
||||
randomBotGroupNearby = sConfigMgr->GetBoolDefault("AiPlayerbot.RandomBotGroupNearby", true);
|
||||
|
||||
// arena
|
||||
randomBotArenaTeamCount = sConfigMgr->GetIntDefault("AiPlayerbot.RandomBotArenaTeamCount", 20);
|
||||
deleteRandomBotArenaTeams = sConfigMgr->GetBoolDefault("AiPlayerbot.DeleteRandomBotArenaTeams", false);
|
||||
|
||||
selfBotLevel = sConfigMgr->GetIntDefault("AiPlayerbot.SelfBotLevel", 1);
|
||||
|
||||
RandomPlayerbotFactory::CreateRandomBots();
|
||||
PlayerbotFactory::Init();
|
||||
sRandomItemMgr->Init();
|
||||
sRandomItemMgr->InitAfterAhBot();
|
||||
|
||||
if (!sPlayerbotAIConfig->autoDoQuests)
|
||||
{
|
||||
LOG_INFO("server.loading", "Loading Quest Detail Data...");
|
||||
sTravelMgr->LoadQuestTravelTable();
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->randomBotJoinBG)
|
||||
sRandomPlayerbotMgr->LoadBattleMastersCache();
|
||||
|
||||
LOG_INFO("server.loading", "---------------------------------------");
|
||||
LOG_INFO("server.loading", " AI Playerbots initialized ");
|
||||
LOG_INFO("server.loading", "---------------------------------------");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlayerbotAIConfig::IsInRandomAccountList(uint32 id)
|
||||
{
|
||||
return find(randomBotAccounts.begin(), randomBotAccounts.end(), id) != randomBotAccounts.end();
|
||||
}
|
||||
|
||||
bool PlayerbotAIConfig::IsInRandomQuestItemList(uint32 id)
|
||||
{
|
||||
return find(randomBotQuestItems.begin(), randomBotQuestItems.end(), id) != randomBotQuestItems.end();
|
||||
}
|
||||
|
||||
bool PlayerbotAIConfig::IsInPvpProhibitedZone(uint32 id)
|
||||
{
|
||||
return find(pvpProhibitedZoneIds.begin(), pvpProhibitedZoneIds.end(), id) != pvpProhibitedZoneIds.end();
|
||||
}
|
||||
|
||||
std::string const PlayerbotAIConfig::GetTimestampStr()
|
||||
{
|
||||
time_t t = time(nullptr);
|
||||
tm* aTm = localtime(&t);
|
||||
// YYYY year
|
||||
// MM month (2 digits 01-12)
|
||||
// DD day (2 digits 01-31)
|
||||
// HH hour (2 digits 00-23)
|
||||
// MM minutes (2 digits 00-59)
|
||||
// SS seconds (2 digits 00-59)
|
||||
char buf[20];
|
||||
snprintf(buf, 20, "%04d-%02d-%02d %02d-%02d-%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
bool PlayerbotAIConfig::openLog(std::string const fileName, char const* mode)
|
||||
{
|
||||
if (!hasLog(fileName))
|
||||
return false;
|
||||
|
||||
auto logFileIt = logFiles.find(fileName);
|
||||
if (logFileIt == logFiles.end())
|
||||
{
|
||||
logFiles.insert(std::make_pair(fileName, std::make_pair(nullptr, false)));
|
||||
logFileIt = logFiles.find(fileName);
|
||||
}
|
||||
|
||||
FILE* file = logFileIt->second.first;
|
||||
bool fileOpen = logFileIt->second.second;
|
||||
|
||||
if (fileOpen) //close log file
|
||||
fclose(file);
|
||||
|
||||
std::string m_logsDir = sConfigMgr->GetOption<std::string>("LogsDir", "", false);
|
||||
if (!m_logsDir.empty())
|
||||
{
|
||||
if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
|
||||
m_logsDir.append("/");
|
||||
}
|
||||
|
||||
|
||||
file = fopen((m_logsDir + fileName).c_str(), mode);
|
||||
fileOpen = true;
|
||||
|
||||
logFileIt->second.first = file;
|
||||
logFileIt->second.second = fileOpen;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerbotAIConfig::log(std::string const fileName, char const* str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> guard(m_logMtx);
|
||||
|
||||
if (!isLogOpen(fileName) && !openLog(fileName, "a"))
|
||||
return;
|
||||
|
||||
FILE* file = logFiles.find(fileName)->second.first;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vfprintf(file, str, ap);
|
||||
fprintf(file, "\n");
|
||||
va_end(ap);
|
||||
fflush(file);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32 minLevel1, uint32 maxLevel1)
|
||||
{
|
||||
std::vector<uint32> buffs;
|
||||
|
||||
std::ostringstream os;
|
||||
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << classId1 << "." << minLevel1 << "." << maxLevel1;
|
||||
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault(os.str().c_str(), "", false), buffs);
|
||||
|
||||
for (auto buff : buffs)
|
||||
{
|
||||
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 };
|
||||
worldBuffs.push_back(wb);
|
||||
}
|
||||
|
||||
if (maxLevel1 == 0)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << classId1 << "." << minLevel1;
|
||||
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault(os.str().c_str(), "", false), buffs);
|
||||
|
||||
for (auto buff : buffs)
|
||||
{
|
||||
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 };
|
||||
worldBuffs.push_back(wb);
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLevel1 == 0 && minLevel1 == 0)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << factionId1 << "." << classId1;
|
||||
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault(os.str().c_str(), "", false), buffs);
|
||||
|
||||
for (auto buff : buffs)
|
||||
{
|
||||
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 };
|
||||
worldBuffs.push_back(wb);
|
||||
}
|
||||
}
|
||||
|
||||
if (classId1 == 0 && maxLevel1 == 0 && minLevel1 == 0)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "AiPlayerbot.WorldBuff." << factionId1;
|
||||
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault(os.str().c_str(), "", false), buffs);
|
||||
|
||||
for (auto buff : buffs)
|
||||
{
|
||||
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 };
|
||||
worldBuffs.push_back(wb);
|
||||
}
|
||||
}
|
||||
|
||||
if (factionId1 == 0 && classId1 == 0 && maxLevel1 == 0 && minLevel1 == 0)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "AiPlayerbot.WorldBuff";
|
||||
|
||||
LoadList<std::vector<uint32>>(sConfigMgr->GetStringDefault(os.str().c_str(), "", false), buffs);
|
||||
|
||||
for (auto buff : buffs)
|
||||
{
|
||||
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 };
|
||||
worldBuffs.push_back(wb);
|
||||
}
|
||||
}
|
||||
}
|
||||
172
src/PlayerbotAIConfig.h
Normal file
172
src/PlayerbotAIConfig.h
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERbotAICONFIG_H
|
||||
#define _PLAYERBOT_PLAYERbotAICONFIG_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TalentSpec.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
enum class BotCheatMask : uint32
|
||||
{
|
||||
none = 0,
|
||||
taxi = 1,
|
||||
gold = 2,
|
||||
health = 4,
|
||||
mana = 8,
|
||||
power = 16,
|
||||
maxMask = 32
|
||||
};
|
||||
|
||||
class PlayerbotAIConfig
|
||||
{
|
||||
public:
|
||||
PlayerbotAIConfig() { };
|
||||
static PlayerbotAIConfig* instance()
|
||||
{
|
||||
static PlayerbotAIConfig instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
bool Initialize();
|
||||
bool IsInRandomAccountList(uint32 id);
|
||||
bool IsInRandomQuestItemList(uint32 id);
|
||||
bool IsInPvpProhibitedZone(uint32 id);
|
||||
|
||||
bool enabled;
|
||||
bool allowGuildBots;
|
||||
uint32 globalCoolDown, reactDelay, maxWaitForMove, expireActionTime, dispelAuraDuration, passiveDelay, repeatDelay,
|
||||
errorDelay, rpgDelay, sitDelay, returnDelay, lootDelay;
|
||||
float sightDistance, spellDistance, reactDistance, grindDistance, lootDistance, shootDistance,
|
||||
fleeDistance, tooCloseDistance, meleeDistance, followDistance, whisperDistance, contactDistance,
|
||||
aoeRadius, rpgDistance, targetPosRecalcDistance, farDistance, healDistance, aggroDistance;
|
||||
uint32 criticalHealth, lowHealth, mediumHealth, almostFullHealth;
|
||||
uint32 lowMana, mediumMana;
|
||||
|
||||
uint32 openGoSpell;
|
||||
bool randomBotAutologin;
|
||||
bool botAutologin;
|
||||
std::string randomBotMapsAsString;
|
||||
std::vector<uint32> randomBotMaps;
|
||||
std::vector<uint32> randomBotQuestItems;
|
||||
std::vector<uint32> randomBotAccounts;
|
||||
std::vector<uint32> randomBotSpellIds;
|
||||
std::vector<uint32> randomBotQuestIds;
|
||||
uint32 randomBotTeleportDistance;
|
||||
float randomGearLoweringChance;
|
||||
float randomBotMaxLevelChance;
|
||||
float randomBotRpgChance;
|
||||
uint32 minRandomBots, maxRandomBots;
|
||||
uint32 randomBotUpdateInterval, randomBotCountChangeMinInterval, randomBotCountChangeMaxInterval;
|
||||
uint32 minRandomBotInWorldTime, maxRandomBotInWorldTime;
|
||||
uint32 minRandomBotRandomizeTime, maxRandomBotRandomizeTime;
|
||||
uint32 minRandomBotChangeStrategyTime, maxRandomBotChangeStrategyTime;
|
||||
uint32 minRandomBotReviveTime, maxRandomBotReviveTime;
|
||||
uint32 minRandomBotPvpTime, maxRandomBotPvpTime;
|
||||
uint32 randomBotsPerInterval;
|
||||
uint32 minRandomBotsPriceChangeInterval, maxRandomBotsPriceChangeInterval;
|
||||
bool randomBotJoinLfg;
|
||||
bool randomBotJoinBG;
|
||||
bool randomBotLoginAtStartup;
|
||||
uint32 randomBotTeleLevel;
|
||||
bool logInGroupOnly, logValuesPerTick;
|
||||
bool fleeingEnabled;
|
||||
bool summonAtInnkeepersEnabled;
|
||||
std::string combatStrategies, nonCombatStrategies;
|
||||
std::string randomBotCombatStrategies, randomBotNonCombatStrategies;
|
||||
uint32 randomBotMinLevel, randomBotMaxLevel;
|
||||
float randomChangeMultiplier;
|
||||
uint32 specProbability[MAX_CLASSES][10];
|
||||
std::string premadeLevelSpec[MAX_CLASSES][10][91]; //lvl 10 - 100
|
||||
ClassSpecs classSpecs[MAX_CLASSES];
|
||||
std::string commandPrefix, commandSeparator;
|
||||
std::string randomBotAccountPrefix;
|
||||
uint32 randomBotAccountCount;
|
||||
bool randomBotRandomPassword;
|
||||
bool deleteRandomBotAccounts;
|
||||
uint32 randomBotGuildCount;
|
||||
bool deleteRandomBotGuilds;
|
||||
std::vector<uint32> randomBotGuilds;
|
||||
std::vector<uint32> pvpProhibitedZoneIds;
|
||||
|
||||
bool randombotsWalkingRPG;
|
||||
bool randombotsWalkingRPGInDoors;
|
||||
uint32 minEnchantingBotLevel;
|
||||
uint32 randombotStartingLevel;
|
||||
bool gearscorecheck;
|
||||
bool randomBotPreQuests;
|
||||
|
||||
bool guildTaskEnabled;
|
||||
uint32 minGuildTaskChangeTime, maxGuildTaskChangeTime;
|
||||
uint32 minGuildTaskAdvertisementTime, maxGuildTaskAdvertisementTime;
|
||||
uint32 minGuildTaskRewardTime, maxGuildTaskRewardTime;
|
||||
uint32 guildTaskAdvertCleanupTime;
|
||||
uint32 guildTaskKillTaskDistance;
|
||||
|
||||
uint32 iterationsPerTick;
|
||||
|
||||
std::mutex m_logMtx;
|
||||
std::vector<std::string> allowedLogFiles;
|
||||
std::unordered_map<std::string, std::pair<FILE*, bool>> logFiles;
|
||||
|
||||
std::vector<std::string> botCheats;
|
||||
uint32 botCheatMask = 0;
|
||||
|
||||
struct worldBuff
|
||||
{
|
||||
uint32 spellId;
|
||||
uint32 factionId = 0;
|
||||
uint32 classId = 0;
|
||||
uint32 minLevel = 0;
|
||||
uint32 maxLevel = 0;
|
||||
};
|
||||
|
||||
std::vector<worldBuff> worldBuffs;
|
||||
|
||||
uint32 commandServerPort;
|
||||
bool perfMonEnabled;
|
||||
|
||||
bool enableGreet;
|
||||
bool randomBotShowHelmet;
|
||||
bool randomBotShowCloak;
|
||||
bool disableRandomLevels;
|
||||
uint32 playerbotsXPrate;
|
||||
uint32 botActiveAlone;
|
||||
|
||||
std::string autoPickReward;
|
||||
bool autoEquipUpgradeLoot;
|
||||
bool syncQuestWithPlayer;
|
||||
bool syncQuestForPlayer;
|
||||
std::string autoTrainSpells;
|
||||
std::string autoPickTalents;
|
||||
bool autoLearnTrainerSpells;
|
||||
bool autoDoQuests;
|
||||
bool syncLevelWithPlayers;
|
||||
bool autoLearnQuestSpells;
|
||||
bool randomBotSayWithoutMaster;
|
||||
bool randomBotGroupNearby;
|
||||
uint32 tweakValue; //Debugging config
|
||||
|
||||
uint32 randomBotArenaTeamCount;
|
||||
bool deleteRandomBotArenaTeams;
|
||||
std::vector<uint32> randomBotArenaTeams;
|
||||
|
||||
uint32 selfBotLevel;
|
||||
|
||||
std::string const GetTimestampStr();
|
||||
bool hasLog(std::string const fileName) { return std::find(allowedLogFiles.begin(), allowedLogFiles.end(), fileName) != allowedLogFiles.end(); };
|
||||
bool openLog(std::string const fileName, char const* mode = "a");
|
||||
bool isLogOpen(std::string const fileName) { auto it = logFiles.find(fileName); return it != logFiles.end() && it->second.second; }
|
||||
void log(std::string const fileName, const char* str, ...);
|
||||
|
||||
void loadWorldBuf(uint32 factionId, uint32 classId, uint32 minLevel, uint32 maxLevel);
|
||||
|
||||
};
|
||||
|
||||
#define sPlayerbotAIConfig PlayerbotAIConfig::instance()
|
||||
|
||||
#endif
|
||||
99
src/PlayerbotCommandServer.cpp
Normal file
99
src/PlayerbotCommandServer.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "PlayerbotCommandServer.h"
|
||||
#include "IoContext.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
typedef boost::shared_ptr<tcp::socket> socket_ptr;
|
||||
|
||||
bool ReadLine(socket_ptr sock, std::string* buffer, std::string* line)
|
||||
{
|
||||
// Do the real reading from fd until buffer has '\n'.
|
||||
std::string::iterator pos;
|
||||
while ((pos = find(buffer->begin(), buffer->end(), '\n')) == buffer->end())
|
||||
{
|
||||
char buf[1025];
|
||||
boost::system::error_code error;
|
||||
size_t n = sock->read_some(boost::asio::buffer(buf), error);
|
||||
if (n == -1 || error == boost::asio::error::eof)
|
||||
return false;
|
||||
else if (error)
|
||||
throw boost::system::system_error(error); // Some other error.
|
||||
|
||||
buf[n] = 0;
|
||||
*buffer += buf;
|
||||
}
|
||||
|
||||
*line = std::string(buffer->begin(), pos);
|
||||
*buffer = std::string(pos + 1, buffer->end());
|
||||
return true;
|
||||
}
|
||||
|
||||
void session(socket_ptr sock)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string buffer, request;
|
||||
while (ReadLine(sock, &buffer, &request))
|
||||
{
|
||||
std::string const response = sRandomPlayerbotMgr->HandleRemoteCommand(request) + "\n";
|
||||
boost::asio::write(*sock, boost::asio::buffer(response.c_str(), response.size()));
|
||||
request = "";
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG_ERROR("playerbots", "{}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void server(Acore::Asio::IoContext& io_service, short port)
|
||||
{
|
||||
tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
|
||||
for (;;)
|
||||
{
|
||||
socket_ptr sock(new tcp::socket(io_service));
|
||||
a.accept(*sock);
|
||||
boost::thread t(boost::bind(session, sock));
|
||||
}
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
if (!sPlayerbotAIConfig->commandServerPort)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream s;
|
||||
s << "Starting Playerbots Command Server on port " << sPlayerbotAIConfig->commandServerPort;
|
||||
LOG_INFO("playerbots", "{}", s.str().c_str());
|
||||
|
||||
try
|
||||
{
|
||||
Acore::Asio::IoContext io_service;
|
||||
server(io_service, sPlayerbotAIConfig->commandServerPort);
|
||||
}
|
||||
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG_ERROR("playerbots", "{}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerbotCommandServer::Start()
|
||||
{
|
||||
std::thread serverThread(Run);
|
||||
serverThread.detach();
|
||||
}
|
||||
24
src/PlayerbotCommandServer.h
Normal file
24
src/PlayerbotCommandServer.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERBOTCOMMANDSERVER_H
|
||||
#define _PLAYERBOT_PLAYERBOTCOMMANDSERVER_H
|
||||
|
||||
class PlayerbotCommandServer
|
||||
{
|
||||
public:
|
||||
PlayerbotCommandServer() { }
|
||||
virtual ~PlayerbotCommandServer() { }
|
||||
static PlayerbotCommandServer* instance()
|
||||
{
|
||||
static PlayerbotCommandServer instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void Start();
|
||||
};
|
||||
|
||||
#define sPlayerbotCommandServer PlayerbotCommandServer::instance()
|
||||
|
||||
#endif
|
||||
88
src/PlayerbotDbStore.cpp
Normal file
88
src/PlayerbotDbStore.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "PlayerbotDbStore.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void PlayerbotDbStore::Load(PlayerbotAI* botAI)
|
||||
{
|
||||
ObjectGuid::LowType guid = botAI->GetBot()->GetGUID().GetCounter();
|
||||
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_DB_STORE);
|
||||
stmt->SetData(0, guid);
|
||||
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
|
||||
{
|
||||
botAI->ClearStrategies(BOT_STATE_COMBAT);
|
||||
botAI->ClearStrategies(BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("+chat", BOT_STATE_COMBAT);
|
||||
botAI->ChangeStrategy("+chat", BOT_STATE_NON_COMBAT);
|
||||
|
||||
std::vector<std::string> values;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
std::string const key = fields[0].Get<std::string>();
|
||||
std::string const value = fields[1].Get<std::string>();
|
||||
|
||||
if (key == "value")
|
||||
values.push_back(value);
|
||||
else if (key == "co")
|
||||
botAI->ChangeStrategy(value, BOT_STATE_COMBAT);
|
||||
else if (key == "nc")
|
||||
botAI->ChangeStrategy(value, BOT_STATE_NON_COMBAT);
|
||||
else if (key == "dead")
|
||||
botAI->ChangeStrategy(value, BOT_STATE_DEAD);
|
||||
}
|
||||
while (result->NextRow());
|
||||
|
||||
botAI->GetAiObjectContext()->Load(values);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerbotDbStore::Save(PlayerbotAI* botAI)
|
||||
{
|
||||
ObjectGuid::LowType guid = botAI->GetBot()->GetGUID().GetCounter();
|
||||
|
||||
Reset(botAI);
|
||||
|
||||
std::vector<std::string> data = botAI->GetAiObjectContext()->Save();
|
||||
for (std::vector<std::string>::iterator i = data.begin(); i != data.end(); ++i)
|
||||
{
|
||||
SaveValue(guid, "value", *i);
|
||||
}
|
||||
|
||||
SaveValue(guid, "co", FormatStrategies("co", botAI->GetStrategies(BOT_STATE_COMBAT)));
|
||||
SaveValue(guid, "nc", FormatStrategies("nc", botAI->GetStrategies(BOT_STATE_NON_COMBAT)));
|
||||
SaveValue(guid, "dead", FormatStrategies("dead", botAI->GetStrategies(BOT_STATE_DEAD)));
|
||||
}
|
||||
|
||||
std::string const PlayerbotDbStore::FormatStrategies(std::string const type, std::vector<std::string> strategies)
|
||||
{
|
||||
std::ostringstream out;
|
||||
for (std::vector<std::string>::iterator i = strategies.begin(); i != strategies.end(); ++i)
|
||||
out << "+" << (*i).c_str() << ",";
|
||||
|
||||
std::string const res = out.str();
|
||||
return res.substr(0, res.size() - 1);
|
||||
}
|
||||
|
||||
void PlayerbotDbStore::Reset(PlayerbotAI* botAI)
|
||||
{
|
||||
ObjectGuid::LowType guid = botAI->GetBot()->GetGUID().GetCounter();
|
||||
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_CUSTOM_STRATEGY);
|
||||
stmt->SetData(0, guid);
|
||||
PlayerbotsDatabase.Execute(stmt);
|
||||
}
|
||||
|
||||
void PlayerbotDbStore::SaveValue(uint32 guid, std::string const key, std::string const value)
|
||||
{
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_INS_DB_STORE);
|
||||
stmt->SetData(0, guid);
|
||||
stmt->SetData(1, key);
|
||||
stmt->SetData(2, value);
|
||||
PlayerbotsDatabase.Execute(stmt);
|
||||
}
|
||||
36
src/PlayerbotDbStore.h
Normal file
36
src/PlayerbotDbStore.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERBOTDBSTORE_H
|
||||
#define _PLAYERBOT_PLAYERBOTDBSTORE_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class PlayerbotDbStore
|
||||
{
|
||||
public:
|
||||
PlayerbotDbStore() { }
|
||||
virtual ~PlayerbotDbStore() { }
|
||||
static PlayerbotDbStore* instance()
|
||||
{
|
||||
static PlayerbotDbStore instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void Save(PlayerbotAI* botAI);
|
||||
void Load(PlayerbotAI* botAI);
|
||||
void Reset(PlayerbotAI* botAI);
|
||||
|
||||
private:
|
||||
void SaveValue(uint32 guid, std::string const key, std::string const value);
|
||||
std::string const FormatStrategies(std::string const type, std::vector<std::string> strategies);
|
||||
};
|
||||
|
||||
#define sPlayerbotDbStore PlayerbotDbStore::instance()
|
||||
|
||||
#endif
|
||||
2667
src/PlayerbotFactory.cpp
Normal file
2667
src/PlayerbotFactory.cpp
Normal file
File diff suppressed because it is too large
Load Diff
176
src/PlayerbotFactory.h
Normal file
176
src/PlayerbotFactory.h
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERBOTFACTORY_H
|
||||
#define _PLAYERBOT_PLAYERBOTFACTORY_H
|
||||
|
||||
#include "InventoryAction.h"
|
||||
|
||||
class Item;
|
||||
class Player;
|
||||
|
||||
struct ItemTemplate;
|
||||
|
||||
struct EnchantTemplate
|
||||
{
|
||||
uint8 ClassId;
|
||||
uint8 SpecId;
|
||||
uint32 SpellId;
|
||||
uint8 SlotId;
|
||||
};
|
||||
|
||||
typedef std::vector<EnchantTemplate> EnchantContainer;
|
||||
|
||||
//TODO: more spec/role
|
||||
/* classid+talenttree
|
||||
enum spec : uint8
|
||||
{
|
||||
WARRIOR ARMS = 10,
|
||||
WARRIOR FURY = 11,
|
||||
WARRIOR PROT = 12,
|
||||
ROLE_HEALER = 1,
|
||||
ROLE_MDPS = 2,
|
||||
ROLE_CDPS = 3,
|
||||
};
|
||||
*/
|
||||
|
||||
/*enum roles : uint8
|
||||
{
|
||||
ROLE_TANK = 0,
|
||||
ROLE_HEALER = 1,
|
||||
ROLE_MDPS = 2,
|
||||
ROLE_CDPS = 3
|
||||
};*/
|
||||
|
||||
enum PriorizedConsumables
|
||||
{
|
||||
CONSUM_ID_ROUGH_WEIGHTSTONE = 3239,
|
||||
CONSUM_ID_COARSE_WEIGHTSTONE = 3239,
|
||||
CONSUM_ID_HEAVY_WEIGHTSTONE = 3241,
|
||||
CONSUM_ID_SOLID_WEIGHTSTONE = 7965,
|
||||
CONSUM_ID_DENSE_WEIGHTSTONE = 12643,
|
||||
CONSUM_ID_FEL_WEIGHTSTONE = 28420,
|
||||
CONSUM_ID_ADAMANTITE_WEIGHTSTONE = 28421,
|
||||
CONSUM_ID_ROUGH_SHARPENING_STONE = 2862,
|
||||
CONSUM_ID_COARSE_SHARPENING_STONE = 2863,
|
||||
CONSUM_ID_HEAVY_SHARPENING_STONE = 2871,
|
||||
CONSUM_ID_SOL_SHARPENING_STONE = 7964,
|
||||
CONSUM_ID_DENSE_SHARPENING_STONE = 12404,
|
||||
CONSUM_ID_ELEMENTAL_SHARPENING_STONE = 18262,
|
||||
CONSUM_ID_CONSECRATED_SHARPENING_STONE = 23122,
|
||||
CONSUM_ID_FEL_SHARPENING_STONE = 23528,
|
||||
CONSUM_ID_ADAMANTITE_SHARPENING_STONE = 23529,
|
||||
CONSUM_ID_LINEN_BANDAGE = 1251,
|
||||
CONSUM_ID_HEAVY_LINEN_BANDAGE = 2581,
|
||||
CONSUM_ID_WOOL_BANDAGE = 3530,
|
||||
CONSUM_ID_HEAVY_WOOL_BANDAGE = 3531,
|
||||
CONSUM_ID_SILK_BANDAGE = 6450,
|
||||
CONSUM_ID_HEAVY_SILK_BANDAGE = 6451,
|
||||
CONSUM_ID_MAGEWEAVE_BANDAGE = 8544,
|
||||
CONSUM_ID_HEAVY_MAGEWEAVE_BANDAGE = 8545,
|
||||
CONSUM_ID_RUNECLOTH_BANDAGE = 14529,
|
||||
CONSUM_ID_HEAVY_RUNECLOTH_BANDAGE = 14530,
|
||||
CONSUM_ID_NETHERWEAVE_BANDAGE = 21990,
|
||||
CONSUM_ID_HEAVY_NETHERWEAVE_BANDAGE = 21991,
|
||||
CONSUM_ID_BRILLIANT_MANA_OIL = 20748,
|
||||
CONSUM_ID_MINOR_MANA_OIL = 20745,
|
||||
CONSUM_ID_SUPERIOR_MANA_OIL = 22521,
|
||||
CONSUM_ID_LESSER_MANA_OIL = 20747,
|
||||
CONSUM_ID_BRILLIANT_WIZARD_OIL = 20749,
|
||||
CONSUM_ID_MINOR_WIZARD_OIL = 20744,
|
||||
CONSUM_ID_SUPERIOR_WIZARD_OIL = 22522,
|
||||
CONSUM_ID_WIZARD_OIL = 20750,
|
||||
CONSUM_ID_LESSER_WIZARD_OIL = 20746,
|
||||
CONSUM_ID_INSTANT_POISON = 6947,
|
||||
CONSUM_ID_INSTANT_POISON_II = 6949,
|
||||
CONSUM_ID_INSTANT_POISON_III = 6950,
|
||||
CONSUM_ID_INSTANT_POISON_IV = 8926,
|
||||
CONSUM_ID_INSTANT_POISON_V = 8927,
|
||||
CONSUM_ID_INSTANT_POISON_VI = 8928,
|
||||
CONSUM_ID_INSTANT_POISON_VII = 21927,
|
||||
CONSUM_ID_DEADLY_POISON = 2892,
|
||||
CONSUM_ID_DEADLY_POISON_II = 2893,
|
||||
CONSUM_ID_DEADLY_POISON_III = 8984,
|
||||
CONSUM_ID_DEADLY_POISON_IV = 8985,
|
||||
CONSUM_ID_DEADLY_POISON_V = 20844,
|
||||
CONSUM_ID_DEADLY_POISON_VI = 22053,
|
||||
CONSUM_ID_DEADLY_POISON_VII = 22054
|
||||
};
|
||||
|
||||
#define MAX_CONSUM_ID 28
|
||||
|
||||
class PlayerbotFactory : public InventoryAction
|
||||
{
|
||||
public:
|
||||
PlayerbotFactory(Player* bot, uint32 level, uint32 itemQuality = 0);
|
||||
|
||||
static ObjectGuid GetRandomBot();
|
||||
static void Init();
|
||||
void Refresh();
|
||||
void Randomize(bool incremental);
|
||||
static std::list<uint32> classQuestIds;
|
||||
void InitSkills();
|
||||
|
||||
static uint32 tradeSkills[];
|
||||
|
||||
private:
|
||||
void Prepare();
|
||||
void InitSecondEquipmentSet();
|
||||
void InitEquipment(bool incremental);
|
||||
void InitEquipmentNew(bool incremental);
|
||||
bool CanEquipItem(ItemTemplate const* proto, uint32 desiredQuality);
|
||||
bool CanEquipUnseenItem(uint8 slot, uint16& dest, uint32 item);
|
||||
void InitTradeSkills();
|
||||
void UpdateTradeSkills();
|
||||
void SetRandomSkill(uint16 id);
|
||||
void InitSpells();
|
||||
void ClearSpells();
|
||||
void ClearSkills();
|
||||
void InitAvailableSpells();
|
||||
void InitSpecialSpells();
|
||||
void InitTalentsTree(bool incremental);
|
||||
void InitTalents(uint32 specNo);
|
||||
void InitQuests(std::list<uint32>& questMap);
|
||||
void InitPet();
|
||||
void ClearInventory();
|
||||
void ClearAllItems();
|
||||
void ResetQuests();
|
||||
void InitAmmo();
|
||||
void InitMounts();
|
||||
void InitPotions();
|
||||
void InitFood();
|
||||
void InitReagents();
|
||||
bool CanEquipArmor(ItemTemplate const* proto);
|
||||
bool CanEquipWeapon(ItemTemplate const* proto);
|
||||
void EnchantItem(Item* item);
|
||||
void AddItemStats(uint32 mod, uint8& sp, uint8& ap, uint8& tank);
|
||||
bool CheckItemStats(uint8 sp, uint8 ap, uint8 tank);
|
||||
void CancelAuras();
|
||||
bool IsDesiredReplacement(Item* item);
|
||||
void InitBags();
|
||||
void InitInventory();
|
||||
void InitInventoryTrade();
|
||||
void InitInventoryEquip();
|
||||
void InitInventorySkill();
|
||||
Item* StoreItem(uint32 itemId, uint32 count);
|
||||
void InitGuild();
|
||||
void InitArenaTeam();
|
||||
void InitImmersive();
|
||||
void AddConsumables();
|
||||
static void AddPrevQuests(uint32 questId, std::list<uint32>& questIds);
|
||||
void LoadEnchantContainer();
|
||||
void ApplyEnchantTemplate();
|
||||
void ApplyEnchantTemplate(uint8 spec);
|
||||
EnchantContainer::const_iterator GetEnchantContainerBegin() { return m_EnchantContainer.begin(); }
|
||||
EnchantContainer::const_iterator GetEnchantContainerEnd() { return m_EnchantContainer.end(); }
|
||||
|
||||
uint32 level;
|
||||
uint32 itemQuality;
|
||||
static std::list<uint32> specialQuestIds;
|
||||
|
||||
protected:
|
||||
EnchantContainer m_EnchantContainer;
|
||||
};
|
||||
|
||||
#endif
|
||||
1070
src/PlayerbotMgr.cpp
Normal file
1070
src/PlayerbotMgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
111
src/PlayerbotMgr.h
Normal file
111
src/PlayerbotMgr.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERBOTMGR_H
|
||||
#define _PLAYERBOT_PLAYERBOTMGR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "QueryHolder.h"
|
||||
#include "QueryResult.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerbotAIBase.h"
|
||||
|
||||
class ChatHandler;
|
||||
class PlayerbotAI;
|
||||
class PlayerbotLoginQueryHolder;
|
||||
class WorldPacket;
|
||||
|
||||
typedef std::map<ObjectGuid, Player*> PlayerBotMap;
|
||||
typedef std::map<std::string, std::set<std::string> > PlayerBotErrorMap;
|
||||
|
||||
class PlayerbotHolder : public PlayerbotAIBase
|
||||
{
|
||||
public:
|
||||
PlayerbotHolder();
|
||||
virtual ~PlayerbotHolder() { };
|
||||
|
||||
void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId);
|
||||
void HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder);
|
||||
|
||||
void LogoutPlayerBot(ObjectGuid guid);
|
||||
void DisablePlayerBot(ObjectGuid guid);
|
||||
Player* GetPlayerBot(ObjectGuid guid) const;
|
||||
Player* GetPlayerBot(ObjectGuid::LowType lowGuid) const;
|
||||
PlayerBotMap::const_iterator GetPlayerBotsBegin() const { return playerBots.begin(); }
|
||||
PlayerBotMap::const_iterator GetPlayerBotsEnd() const { return playerBots.end(); }
|
||||
|
||||
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override { };
|
||||
void UpdateSessions();
|
||||
void HandleBotPackets(WorldSession* session);
|
||||
|
||||
void LogoutAllBots();
|
||||
void OnBotLogin(Player* const bot);
|
||||
|
||||
std::vector<std::string> HandlePlayerbotCommand(char const* args, Player* master = nullptr);
|
||||
std::string const ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid, bool admin, uint32 masterAccountId, uint32 masterGuildId);
|
||||
uint32 GetAccountId(std::string const name);
|
||||
uint32 GetAccountId(ObjectGuid guid);
|
||||
std::string const ListBots(Player* master);
|
||||
|
||||
protected:
|
||||
virtual void OnBotLoginInternal(Player* const bot) = 0;
|
||||
|
||||
PlayerBotMap playerBots;
|
||||
};
|
||||
|
||||
class PlayerbotMgr : public PlayerbotHolder
|
||||
{
|
||||
public:
|
||||
PlayerbotMgr(Player* const master);
|
||||
virtual ~PlayerbotMgr();
|
||||
|
||||
static bool HandlePlayerbotMgrCommand(ChatHandler* handler, char const* args);
|
||||
void HandleMasterIncomingPacket(WorldPacket const& packet);
|
||||
void HandleMasterOutgoingPacket(WorldPacket const& packet);
|
||||
void HandleCommand(uint32 type, std::string const text);
|
||||
void OnPlayerLogin(Player* player);
|
||||
void CancelLogout();
|
||||
|
||||
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
|
||||
void TellError(std::string const botName, std::string const text);
|
||||
|
||||
Player* GetMaster() const { return master; };
|
||||
|
||||
void SaveToDB();
|
||||
|
||||
protected:
|
||||
void OnBotLoginInternal(Player* const bot) override;
|
||||
void CheckTellErrors(uint32 elapsed);
|
||||
|
||||
private:
|
||||
Player* const master;
|
||||
PlayerBotErrorMap errors;
|
||||
time_t lastErrorTell;
|
||||
};
|
||||
|
||||
class PlayerbotsMgr
|
||||
{
|
||||
public:
|
||||
PlayerbotsMgr() { }
|
||||
~PlayerbotsMgr() { }
|
||||
|
||||
static PlayerbotsMgr* instance()
|
||||
{
|
||||
static PlayerbotsMgr instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void AddPlayerbotData(Player* player, bool isBotAI);
|
||||
void RemovePlayerBotData(ObjectGuid const& guid);
|
||||
|
||||
PlayerbotAI* GetPlayerbotAI(Player* player);
|
||||
PlayerbotMgr* GetPlayerbotMgr(Player* player);
|
||||
|
||||
private:
|
||||
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsMap;
|
||||
};
|
||||
|
||||
#define sPlayerbotsMgr PlayerbotsMgr::instance()
|
||||
|
||||
#endif
|
||||
265
src/PlayerbotSecurity.cpp
Normal file
265
src/PlayerbotSecurity.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "PlayerbotSecurity.h"
|
||||
#include "LFGMgr.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
PlayerbotSecurity::PlayerbotSecurity(Player* const bot) : bot(bot)
|
||||
{
|
||||
if (bot)
|
||||
account = sCharacterCache->GetCharacterAccountIdByGuid(bot->GetGUID());
|
||||
}
|
||||
|
||||
PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* reason, bool ignoreGroup)
|
||||
{
|
||||
if (from->GetSession()->GetSecurity() >= SEC_GAMEMASTER)
|
||||
return PLAYERBOT_SECURITY_ALLOW_ALL;
|
||||
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
if (botAI->IsOpposing(from))
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_OPPOSING;
|
||||
|
||||
return PLAYERBOT_SECURITY_DENY_ALL;
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->IsInRandomAccountList(account))
|
||||
{
|
||||
if (botAI->IsOpposing(from))
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_OPPOSING;
|
||||
|
||||
return PLAYERBOT_SECURITY_DENY_ALL;
|
||||
}
|
||||
|
||||
if (sLFGMgr->GetState(bot->GetGUID()) != lfg::LFG_STATE_NONE)
|
||||
{
|
||||
if (!bot->GetGuildId() || bot->GetGuildId() != from->GetGuildId())
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_LFG;
|
||||
|
||||
return PLAYERBOT_SECURITY_TALK;
|
||||
}
|
||||
}
|
||||
|
||||
Group* group = from->GetGroup();
|
||||
if (group)
|
||||
{
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
{
|
||||
Player* player = gref->GetSource();
|
||||
if (player == bot && !ignoreGroup)
|
||||
return PLAYERBOT_SECURITY_ALLOW_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((int32)bot->getLevel() - (int8)from->getLevel() > 30)
|
||||
{
|
||||
if (!bot->GetGuildId() || bot->GetGuildId() != from->GetGuildId())
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_LOW_LEVEL;
|
||||
|
||||
return PLAYERBOT_SECURITY_TALK;
|
||||
}
|
||||
}
|
||||
|
||||
int32 botGS = (int32)botAI->GetEquipGearScore(bot, false, false);
|
||||
int32 fromGS = (int32)botAI->GetEquipGearScore(from, false, false);
|
||||
if (sPlayerbotAIConfig->gearscorecheck)
|
||||
{
|
||||
if (botGS && bot->getLevel() > 15 && botGS > fromGS &&
|
||||
static_cast<float>(100 * (botGS - fromGS) / botGS) >= static_cast<float>(12 * sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) / from->getLevel()))
|
||||
{
|
||||
if (reason) *reason = PLAYERBOT_DENY_GEARSCORE;
|
||||
return PLAYERBOT_SECURITY_TALK;
|
||||
}
|
||||
}
|
||||
|
||||
if (bot->InBattlegroundQueue())
|
||||
{
|
||||
if (!bot->GetGuildId() || bot->GetGuildId() != from->GetGuildId())
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_BG;
|
||||
|
||||
return PLAYERBOT_SECURITY_TALK;
|
||||
}
|
||||
}
|
||||
|
||||
/*if (bot->isDead())
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_DEAD;
|
||||
|
||||
return PLAYERBOT_SECURITY_TALK;
|
||||
}*/
|
||||
|
||||
group = bot->GetGroup();
|
||||
if (!group)
|
||||
{
|
||||
/*if (bot->GetMapId() != from->GetMapId() || bot->GetDistance(from) > sPlayerbotAIConfig->whisperDistance)
|
||||
{
|
||||
if (!bot->GetGuildId() || bot->GetGuildId() != from->GetGuildId())
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_FAR;
|
||||
|
||||
return PLAYERBOT_SECURITY_TALK;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_INVITE;
|
||||
|
||||
return PLAYERBOT_SECURITY_INVITE;
|
||||
}
|
||||
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
{
|
||||
Player* player = gref->GetSource();
|
||||
if (player == from)
|
||||
return PLAYERBOT_SECURITY_ALLOW_ALL;
|
||||
}
|
||||
|
||||
if (group->IsFull())
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_FULL_GROUP;
|
||||
|
||||
return PLAYERBOT_SECURITY_TALK;
|
||||
}
|
||||
|
||||
if (group->GetLeaderGUID() != bot->GetGUID())
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_NOT_LEADER;
|
||||
|
||||
return PLAYERBOT_SECURITY_TALK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_IS_LEADER;
|
||||
|
||||
return PLAYERBOT_SECURITY_INVITE;
|
||||
}
|
||||
|
||||
if (reason)
|
||||
*reason = PLAYERBOT_DENY_INVITE;
|
||||
|
||||
return PLAYERBOT_SECURITY_INVITE;
|
||||
}
|
||||
|
||||
return PLAYERBOT_SECURITY_ALLOW_ALL;
|
||||
}
|
||||
|
||||
bool PlayerbotSecurity::CheckLevelFor(PlayerbotSecurityLevel level, bool silent, Player* from, bool ignoreGroup)
|
||||
{
|
||||
DenyReason reason = PLAYERBOT_DENY_NONE;
|
||||
PlayerbotSecurityLevel realLevel = LevelFor(from, &reason, ignoreGroup);
|
||||
if (realLevel >= level)
|
||||
return true;
|
||||
|
||||
PlayerbotAI* fromBotAI = GET_PLAYERBOT_AI(from);
|
||||
if (silent || (fromBotAI && !fromBotAI->IsRealPlayer()))
|
||||
return false;
|
||||
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
Player* master = botAI->GetMaster();
|
||||
if (master && botAI && botAI->IsOpposing(master) && master->GetSession()->GetSecurity() < SEC_GAMEMASTER)
|
||||
return false;
|
||||
|
||||
std::ostringstream out;
|
||||
switch (realLevel)
|
||||
{
|
||||
case PLAYERBOT_SECURITY_DENY_ALL:
|
||||
out << "I'm kind of busy now";
|
||||
break;
|
||||
case PLAYERBOT_SECURITY_TALK:
|
||||
switch (reason)
|
||||
{
|
||||
case PLAYERBOT_DENY_NONE:
|
||||
out << "I'll do it later";
|
||||
break;
|
||||
case PLAYERBOT_DENY_LOW_LEVEL:
|
||||
out << "You are too low level: |cffff0000" << (uint32)from->getLevel() << "|cffffffff/|cff00ff00" << (uint32)bot->getLevel();
|
||||
break;
|
||||
case PLAYERBOT_DENY_GEARSCORE:
|
||||
{
|
||||
int botGS = (int)botAI->GetEquipGearScore(bot, false, false);
|
||||
int fromGS = (int)botAI->GetEquipGearScore(from, false, false);
|
||||
int diff = (100 * (botGS - fromGS) / botGS);
|
||||
int req = 12 * sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) / from->getLevel();
|
||||
out << "Your gearscore is too low: |cffff0000" << fromGS << "|cffffffff/|cff00ff00" << botGS << " |cffff0000" << diff << "%|cffffffff/|cff00ff00" << req << "%";
|
||||
}
|
||||
break;
|
||||
case PLAYERBOT_DENY_NOT_YOURS:
|
||||
out << "I have a master already";
|
||||
break;
|
||||
case PLAYERBOT_DENY_IS_BOT:
|
||||
out << "You are a bot";
|
||||
break;
|
||||
case PLAYERBOT_DENY_OPPOSING:
|
||||
out << "You are the enemy";
|
||||
break;
|
||||
case PLAYERBOT_DENY_DEAD:
|
||||
out << "I'm dead. Will do it later";
|
||||
break;
|
||||
case PLAYERBOT_DENY_INVITE:
|
||||
out << "Invite me to your group first";
|
||||
break;
|
||||
case PLAYERBOT_DENY_FAR:
|
||||
{
|
||||
out << "You must be closer to invite me to your group. I am in ";
|
||||
|
||||
if (AreaTableEntry const* entry = sAreaTableStore.LookupEntry(bot->GetAreaId()))
|
||||
{
|
||||
out << " |cffffffff(|cffff0000" << entry->area_name[0] << "|cffffffff)";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PLAYERBOT_DENY_FULL_GROUP:
|
||||
out << "I am in a full group. Will do it later";
|
||||
break;
|
||||
case PLAYERBOT_DENY_IS_LEADER:
|
||||
out << "I am currently leading a group. I can invite you if you want.";
|
||||
break;
|
||||
case PLAYERBOT_DENY_NOT_LEADER:
|
||||
out << "I am in a group with " << botAI->GetGroupMaster()->GetName() << ". You can ask him for invite.";
|
||||
break;
|
||||
case PLAYERBOT_DENY_BG:
|
||||
out << "I am in a queue for BG. Will do it later";
|
||||
break;
|
||||
case PLAYERBOT_DENY_LFG:
|
||||
out << "I am in a queue for dungeon. Will do it later";
|
||||
break;
|
||||
default:
|
||||
out << "I can't do that";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PLAYERBOT_SECURITY_INVITE:
|
||||
out << "Invite me to your group first";
|
||||
break;
|
||||
default:
|
||||
out << "I can't do that";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string const text = out.str();
|
||||
ObjectGuid guid = from->GetGUID();
|
||||
time_t lastSaid = whispers[guid][text];
|
||||
if (!lastSaid || (time(nullptr) - lastSaid) >= sPlayerbotAIConfig->repeatDelay / 1000)
|
||||
{
|
||||
whispers[guid][text] = time(nullptr);
|
||||
bot->Whisper(text, LANG_UNIVERSAL, from);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
55
src/PlayerbotSecurity.h
Normal file
55
src/PlayerbotSecurity.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERBOTSECURITY_H
|
||||
#define _PLAYERBOT_PLAYERBOTSECURITY_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "ObjectGuid.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class Player;
|
||||
|
||||
enum PlayerbotSecurityLevel : uint32
|
||||
{
|
||||
PLAYERBOT_SECURITY_DENY_ALL = 0,
|
||||
PLAYERBOT_SECURITY_TALK = 1,
|
||||
PLAYERBOT_SECURITY_INVITE = 2,
|
||||
PLAYERBOT_SECURITY_ALLOW_ALL = 3
|
||||
};
|
||||
|
||||
enum DenyReason
|
||||
{
|
||||
PLAYERBOT_DENY_NONE,
|
||||
PLAYERBOT_DENY_LOW_LEVEL,
|
||||
PLAYERBOT_DENY_GEARSCORE,
|
||||
PLAYERBOT_DENY_NOT_YOURS,
|
||||
PLAYERBOT_DENY_IS_BOT,
|
||||
PLAYERBOT_DENY_OPPOSING,
|
||||
PLAYERBOT_DENY_DEAD,
|
||||
PLAYERBOT_DENY_FAR,
|
||||
PLAYERBOT_DENY_INVITE,
|
||||
PLAYERBOT_DENY_FULL_GROUP,
|
||||
PLAYERBOT_DENY_NOT_LEADER,
|
||||
PLAYERBOT_DENY_IS_LEADER,
|
||||
PLAYERBOT_DENY_BG,
|
||||
PLAYERBOT_DENY_LFG
|
||||
};
|
||||
|
||||
class PlayerbotSecurity
|
||||
{
|
||||
public:
|
||||
PlayerbotSecurity(Player* const bot);
|
||||
|
||||
PlayerbotSecurityLevel LevelFor(Player* from, DenyReason* reason = nullptr, bool ignoreGroup = false);
|
||||
bool CheckLevelFor(PlayerbotSecurityLevel level, bool silent, Player* from, bool ignoreGroup = false);
|
||||
|
||||
private:
|
||||
Player* const bot;
|
||||
uint32 account;
|
||||
std::map<ObjectGuid, std::map<std::string, time_t> > whispers;
|
||||
};
|
||||
|
||||
#endif
|
||||
49
src/PlayerbotTextMgr.cpp
Normal file
49
src/PlayerbotTextMgr.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "PlayerbotTextMgr.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
void replaceAll(std::string& str, std::string const from, std::string const to);
|
||||
|
||||
void PlayerbotTextMgr::LoadTemplates()
|
||||
{
|
||||
LOG_INFO("playerbots", "Loading playerbots texts...");
|
||||
|
||||
uint32 count = 0;
|
||||
if (PreparedQueryResult result = PlayerbotsDatabase.Query(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_TEXT)))
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
std::string const key = fields[0].Get<std::string>();
|
||||
std::string const text = fields[1].Get<std::string>();
|
||||
templates[key].push_back(text);
|
||||
++count;
|
||||
}
|
||||
while (result->NextRow());
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "{} playerbots texts loaded", count);
|
||||
}
|
||||
|
||||
std::string const PlayerbotTextMgr::Format(std::string const key, std::map<std::string, std::string> placeholders)
|
||||
{
|
||||
if (templates.empty())
|
||||
LoadTemplates();
|
||||
|
||||
std::vector<std::string>& list = templates[key];
|
||||
if (list.empty())
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Unknown text: " << key;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string str = list[urand(0, list.size() - 1)];
|
||||
for (std::map<std::string, std::string>::iterator i = placeholders.begin(); i != placeholders.end(); ++i)
|
||||
replaceAll(str, i->first, i->second);
|
||||
|
||||
return str;
|
||||
}
|
||||
34
src/PlayerbotTextMgr.h
Normal file
34
src/PlayerbotTextMgr.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PLAYERBOTTEXTMGR_H
|
||||
#define _PLAYERBOT_PLAYERBOTTEXTMGR_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class PlayerbotTextMgr
|
||||
{
|
||||
public:
|
||||
PlayerbotTextMgr() { };
|
||||
virtual ~PlayerbotTextMgr() { };
|
||||
static PlayerbotTextMgr* instance()
|
||||
{
|
||||
static PlayerbotTextMgr instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
std::string const Format(std::string const key, std::map<std::string, std::string> placeholders);
|
||||
|
||||
private:
|
||||
void LoadTemplates();
|
||||
|
||||
std::map<std::string, std::vector<std::string>> templates;
|
||||
};
|
||||
|
||||
#define sPlayerbotTextMgr PlayerbotTextMgr::instance()
|
||||
|
||||
#endif
|
||||
336
src/Playerbots.cpp
Normal file
336
src/Playerbots.cpp
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cs_playerbots.h"
|
||||
#include "Channel.h"
|
||||
#include "Config.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseLoader.h"
|
||||
#include "GuildTaskMgr.h"
|
||||
#include "Metric.h"
|
||||
#include "Playerbots.h"
|
||||
#include "RandomPlayerbotMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
|
||||
class PlayerbotsDatabaseScript : public DatabaseScript
|
||||
{
|
||||
public:
|
||||
PlayerbotsDatabaseScript() : DatabaseScript("PlayerbotsDatabaseScript") { }
|
||||
|
||||
bool OnDatabasesLoading() override
|
||||
{
|
||||
DatabaseLoader playerbotLoader("server.playerbots");
|
||||
playerbotLoader.SetUpdateFlags(sConfigMgr->GetOption<bool>("Playerbots.Updates.EnableDatabases", true) ? DatabaseLoader::DATABASE_PLAYERBOTS : 0);
|
||||
playerbotLoader.AddDatabase(PlayerbotsDatabase, "Playerbots");
|
||||
|
||||
return playerbotLoader.Load();
|
||||
}
|
||||
|
||||
void OnDatabasesKeepAlive() override
|
||||
{
|
||||
PlayerbotsDatabase.KeepAlive();
|
||||
}
|
||||
|
||||
void OnDatabasesClosing() override
|
||||
{
|
||||
PlayerbotsDatabase.Close();
|
||||
}
|
||||
|
||||
void OnDatabaseWarnAboutSyncQueries(bool apply) override
|
||||
{
|
||||
PlayerbotsDatabase.WarnAboutSyncQueries(apply);
|
||||
}
|
||||
|
||||
void OnDatabaseSelectIndexLogout(Player* player, uint32& statementIndex, uint32& statementParam) override
|
||||
{
|
||||
statementIndex = CHAR_UPD_CHAR_ONLINE;
|
||||
statementParam = player->GetGUID().GetCounter();
|
||||
}
|
||||
|
||||
void OnDatabaseGetDBRevision(std::string& revision) override
|
||||
{
|
||||
if (QueryResult resultPlayerbot = PlayerbotsDatabase.Query("SELECT date FROM version_db_playerbots ORDER BY date DESC LIMIT 1"))
|
||||
{
|
||||
Field* fields = resultPlayerbot->Fetch();
|
||||
revision = fields[0].Get<std::string>();
|
||||
}
|
||||
|
||||
if (revision.empty())
|
||||
{
|
||||
revision = "Unknown Playerbots Database Revision";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class PlayerbotsMetricScript : public MetricScript
|
||||
{
|
||||
public:
|
||||
PlayerbotsMetricScript() : MetricScript("PlayerbotsMetricScript") { }
|
||||
|
||||
void OnMetricLogging() override
|
||||
{
|
||||
if (sMetric->IsEnabled())
|
||||
{
|
||||
sMetric->LogValue("db_queue_playerbots", uint64(PlayerbotsDatabase.QueueSize()), {});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class PlayerbotsPlayerScript : public PlayerScript
|
||||
{
|
||||
public:
|
||||
PlayerbotsPlayerScript() : PlayerScript("PlayerbotsPlayerScript") { }
|
||||
|
||||
void OnLogin(Player* player) override
|
||||
{
|
||||
if (!player->GetSession()->IsBot())
|
||||
{
|
||||
sPlayerbotsMgr->AddPlayerbotData(player, false);
|
||||
sRandomPlayerbotMgr->OnPlayerLogin(player);
|
||||
}
|
||||
}
|
||||
|
||||
void OnAfterUpdate(Player* player, uint32 diff) override
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
{
|
||||
botAI->UpdateAI(diff);
|
||||
}
|
||||
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
playerbotMgr->UpdateAI(diff);
|
||||
}
|
||||
}
|
||||
|
||||
bool CanPlayerUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Player* receiver) override
|
||||
{
|
||||
if (type == CHAT_MSG_WHISPER)
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(receiver))
|
||||
{
|
||||
botAI->HandleCommand(type, msg, player);
|
||||
player->ResetSpeakTimers();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Group* group) override
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
if (Player* member = itr->GetSource())
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(member))
|
||||
{
|
||||
botAI->HandleCommand(type, msg, player);
|
||||
player->ResetSpeakTimers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg) override
|
||||
{
|
||||
if (type == CHAT_MSG_GUILD)
|
||||
{
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin(); it != playerbotMgr->GetPlayerBotsEnd(); ++it)
|
||||
{
|
||||
if (Player* const bot = it->second)
|
||||
{
|
||||
if (bot->GetGuildId() == player->GetGuildId())
|
||||
{
|
||||
GET_PLAYERBOT_AI(bot)->HandleCommand(type, msg, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override
|
||||
{
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
if (channel->GetFlags() & 0x18)
|
||||
{
|
||||
playerbotMgr->HandleCommand(type, msg);
|
||||
}
|
||||
}
|
||||
|
||||
sRandomPlayerbotMgr->HandleCommand(type, msg, player);
|
||||
}
|
||||
};
|
||||
|
||||
class PlayerbotsMiscScript : public MiscScript
|
||||
{
|
||||
public:
|
||||
PlayerbotsMiscScript() : MiscScript("PlayerbotsMiscScript") { }
|
||||
|
||||
void OnDestructPlayer(Player* player) override
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
{
|
||||
delete botAI;
|
||||
}
|
||||
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
delete playerbotMgr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class PlayerbotsServerScript : public ServerScript
|
||||
{
|
||||
public:
|
||||
PlayerbotsServerScript() : ServerScript("PlayerbotsServerScript") { }
|
||||
|
||||
void OnPacketReceived(WorldSession* session, WorldPacket const& packet) override
|
||||
{
|
||||
if (Player* player = session->GetPlayer())
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
playerbotMgr->HandleMasterIncomingPacket(packet);
|
||||
}
|
||||
};
|
||||
|
||||
class PlayerbotsWorldScript : public WorldScript
|
||||
{
|
||||
public:
|
||||
PlayerbotsWorldScript() : WorldScript("PlayerbotsWorldScript") { }
|
||||
|
||||
void OnBeforeWorldInitialized() override
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
LOG_INFO("server.loading", " ");
|
||||
LOG_INFO("server.loading", "Load Playerbots Config...");
|
||||
|
||||
sPlayerbotAIConfig->Initialize();
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded playerbots config in {} ms", GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
};
|
||||
|
||||
class PlayerbotsScript : public PlayerbotScript
|
||||
{
|
||||
public:
|
||||
PlayerbotsScript() : PlayerbotScript("PlayerbotsScript") { }
|
||||
|
||||
bool OnPlayerbotCheckLFGQueue(lfg::Lfg5Guids const& guidsList) override
|
||||
{
|
||||
bool nonBotFound = false;
|
||||
for (ObjectGuid const& guid : guidsList.guids)
|
||||
{
|
||||
Player* player = ObjectAccessor::FindPlayer(guid);
|
||||
if (guid.IsGroup() || (player && !GET_PLAYERBOT_AI(player)))
|
||||
{
|
||||
nonBotFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nonBotFound;
|
||||
}
|
||||
|
||||
void OnPlayerbotCheckKillTask(Player* player, Unit* victim) override
|
||||
{
|
||||
if (player)
|
||||
sGuildTaskMgr->CheckKillTask(player, victim);
|
||||
}
|
||||
|
||||
void OnPlayerbotCheckPetitionAccount(Player* player, bool& found) override
|
||||
{
|
||||
if (found && GET_PLAYERBOT_AI(player))
|
||||
found = false;
|
||||
}
|
||||
|
||||
bool OnPlayerbotCheckUpdatesToSend(Player* player) override
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
return botAI->IsRealPlayer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnPlayerbotPacketSent(Player* player, WorldPacket const* packet) override
|
||||
{
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
{
|
||||
botAI->HandleBotOutgoingPacket(*packet);
|
||||
}
|
||||
else if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
playerbotMgr->HandleMasterOutgoingPacket(*packet);
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlayerbotUpdate(uint32 diff) override
|
||||
{
|
||||
sRandomPlayerbotMgr->UpdateAI(diff);
|
||||
sRandomPlayerbotMgr->UpdateSessions();
|
||||
}
|
||||
|
||||
void OnPlayerbotUpdateSessions(Player* player) override
|
||||
{
|
||||
if (player)
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
playerbotMgr->UpdateSessions();
|
||||
}
|
||||
|
||||
void OnPlayerbotLogout(Player* player) override
|
||||
{
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);
|
||||
if (!botAI || botAI->IsRealPlayer())
|
||||
{
|
||||
playerbotMgr->LogoutAllBots();
|
||||
}
|
||||
}
|
||||
|
||||
sRandomPlayerbotMgr->OnPlayerLogout(player);
|
||||
}
|
||||
|
||||
void OnPlayerbotLogoutBots() override
|
||||
{
|
||||
sRandomPlayerbotMgr->LogoutAllBots();
|
||||
}
|
||||
};
|
||||
|
||||
void AddPlayerbotsScripts()
|
||||
{
|
||||
new PlayerbotsDatabaseScript();
|
||||
new PlayerbotsMetricScript();
|
||||
new PlayerbotsPlayerScript();
|
||||
new PlayerbotsMiscScript();
|
||||
new PlayerbotsServerScript();
|
||||
new PlayerbotsWorldScript();
|
||||
new PlayerbotsScript();
|
||||
|
||||
AddSC_playerbots_commandscript();
|
||||
}
|
||||
47
src/Playerbots.h
Normal file
47
src/Playerbots.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_H
|
||||
#define _PLAYERBOT_H
|
||||
|
||||
#include "AiObjectContext.h"
|
||||
#include "Group.h"
|
||||
#include "Pet.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "PlayerbotMgr.h"
|
||||
#include "RandomPlayerbotMgr.h"
|
||||
#include "SharedValueContext.h"
|
||||
#include "Spell.h"
|
||||
#include "TravelNode.h"
|
||||
|
||||
std::vector<std::string> split(std::string const s, char delim);
|
||||
void split(std::vector<std::string>& dest, std::string const str, char const* delim);
|
||||
#ifndef WIN32
|
||||
int strcmpi(char const* s1, char const* s2);
|
||||
#endif
|
||||
|
||||
#define CAST_ANGLE_IN_FRONT (2.f * static_cast<float>(M_PI) / 3.f)
|
||||
#define EMOTE_ANGLE_IN_FRONT (2.f * static_cast<float>(M_PI) / 6.f)
|
||||
|
||||
#define GET_PLAYERBOT_AI(object) sPlayerbotsMgr->GetPlayerbotAI(object)
|
||||
#define GET_PLAYERBOT_MGR(object) sPlayerbotsMgr->GetPlayerbotMgr(object)
|
||||
|
||||
#define AI_VALUE(type, name) context->GetValue<type>(name)->Get()
|
||||
#define AI_VALUE2(type, name, param) context->GetValue<type>(name, param)->Get()
|
||||
|
||||
#define AI_VALUE_LAZY(type, name) context->GetValue<type>(name)->LazyGet()
|
||||
#define AI_VALUE2_LAZY(type, name, param) context->GetValue<type>(name, param)->LazyGet()
|
||||
|
||||
#define SET_AI_VALUE(type, name, value) context->GetValue<type>(name)->Set(value)
|
||||
#define SET_AI_VALUE2(type, name, param, value) context->GetValue<type>(name, param)->Set(value)
|
||||
#define RESET_AI_VALUE(type, name) context->GetValue<type>(name)->Reset()
|
||||
#define RESET_AI_VALUE2(type, name, param) context->GetValue<type>(name, param)->Reset()
|
||||
|
||||
#define PAI_VALUE(type, name) sPlayerbotsMgr->GetPlayerbotAI(player)->GetAiObjectContext()->GetValue<type>(name)->Get()
|
||||
#define PAI_VALUE2(type, name, param) sPlayerbotsMgr->GetPlayerbotAI(player)->GetAiObjectContext()->GetValue<type>(name, param)->Get()
|
||||
#define GAI_VALUE(type, name) sSharedValueContext->getGlobalValue<type>(name)->Get()
|
||||
#define GAI_VALUE2(type, name, param) sSharedValueContext->getGlobalValue<type>(name, param)->Get()
|
||||
|
||||
#endif
|
||||
2720
src/RandomItemMgr.cpp
Normal file
2720
src/RandomItemMgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
204
src/RandomItemMgr.h
Normal file
204
src/RandomItemMgr.h
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_RANDOMITEMMGR_H
|
||||
#define _PLAYERBOT_RANDOMITEMMGR_H
|
||||
|
||||
#include "AiFactory.h"
|
||||
#include "Common.h"
|
||||
#include "ItemTemplate.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class ChatHandler;
|
||||
|
||||
struct ItemTemplate;
|
||||
|
||||
enum EquipmentSlots : uint32;
|
||||
|
||||
enum RandomItemType
|
||||
{
|
||||
RANDOM_ITEM_GUILD_TASK,
|
||||
RANDOM_ITEM_GUILD_TASK_REWARD_EQUIP_BLUE,
|
||||
RANDOM_ITEM_GUILD_TASK_REWARD_EQUIP_GREEN,
|
||||
RANDOM_ITEM_GUILD_TASK_REWARD_TRADE,
|
||||
RANDOM_ITEM_GUILD_TASK_REWARD_TRADE_RARE
|
||||
};
|
||||
|
||||
#define MAX_STAT_SCALES 32
|
||||
|
||||
enum ItemSource
|
||||
{
|
||||
ITEM_SOURCE_NONE,
|
||||
ITEM_SOURCE_DROP,
|
||||
ITEM_SOURCE_VENDOR,
|
||||
ITEM_SOURCE_QUEST,
|
||||
ITEM_SOURCE_CRAFT,
|
||||
ITEM_SOURCE_PVP
|
||||
};
|
||||
|
||||
struct WeightScaleInfo
|
||||
{
|
||||
uint32 id;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct WeightScaleStat
|
||||
{
|
||||
std::string stat;
|
||||
uint32 weight;
|
||||
};
|
||||
|
||||
struct StatWeight
|
||||
{
|
||||
uint32 id;
|
||||
uint32 weight;
|
||||
};
|
||||
|
||||
struct ItemInfoEntry
|
||||
{
|
||||
ItemInfoEntry() : minLevel(0), source(0), sourceId(0), team(0), repRank(0), repFaction(0), quality(0), slot(0), itemId(0)
|
||||
{
|
||||
for (uint8 i = 1; i <= MAX_STAT_SCALES; ++i)
|
||||
{
|
||||
weights[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<uint32, uint32> weights;
|
||||
uint32 minLevel;
|
||||
uint32 source;
|
||||
uint32 sourceId;
|
||||
uint32 team;
|
||||
uint32 repRank;
|
||||
uint32 repFaction;
|
||||
uint32 quality;
|
||||
uint32 slot;
|
||||
uint32 itemId;
|
||||
};
|
||||
|
||||
typedef std::vector<WeightScaleStat> WeightScaleStats;
|
||||
//typedef std::map<WeightScaleInfo, WeightScaleStats> WeightScaleList;
|
||||
|
||||
struct WeightScale
|
||||
{
|
||||
WeightScaleInfo info;
|
||||
WeightScaleStats stats;
|
||||
};
|
||||
|
||||
//typedef map<uint32, WeightScale> WeightScales;
|
||||
|
||||
class RandomItemPredicate
|
||||
{
|
||||
public:
|
||||
virtual ~RandomItemPredicate() { };
|
||||
|
||||
virtual bool Apply(ItemTemplate const* proto) = 0;
|
||||
};
|
||||
|
||||
typedef std::vector<uint32> RandomItemList;
|
||||
typedef std::map<RandomItemType, RandomItemList> RandomItemCache;
|
||||
|
||||
class BotEquipKey
|
||||
{
|
||||
public:
|
||||
BotEquipKey() : level(0), clazz(0), slot(0), quality(0), key(GetKey()) { }
|
||||
BotEquipKey(uint32 level, uint8 clazz, uint8 slot, uint32 quality) : level(level), clazz(clazz), slot(slot), quality(quality), key(GetKey()) { }
|
||||
BotEquipKey(BotEquipKey const& other) : level(other.level), clazz(other.clazz), slot(other.slot), quality(other.quality), key(GetKey()) { }
|
||||
|
||||
bool operator<(BotEquipKey const& other) const
|
||||
{
|
||||
return other.key < this->key;
|
||||
}
|
||||
|
||||
uint32 level;
|
||||
uint8 clazz;
|
||||
uint8 slot;
|
||||
uint32 quality;
|
||||
uint64 key;
|
||||
|
||||
private:
|
||||
uint64 GetKey();
|
||||
};
|
||||
|
||||
typedef std::map<BotEquipKey, RandomItemList> BotEquipCache;
|
||||
|
||||
class RandomItemMgr
|
||||
{
|
||||
public:
|
||||
RandomItemMgr();
|
||||
virtual ~RandomItemMgr();
|
||||
static RandomItemMgr* instance()
|
||||
{
|
||||
static RandomItemMgr instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
public:
|
||||
void Init();
|
||||
void InitAfterAhBot();
|
||||
static bool HandleConsoleCommand(ChatHandler* handler, char const* args);
|
||||
RandomItemList Query(uint32 level, RandomItemType type, RandomItemPredicate* predicate);
|
||||
RandomItemList Query(uint32 level, uint8 clazz, uint8 slot, uint32 quality);
|
||||
uint32 GetUpgrade(Player* player, std::string spec, uint8 slot, uint32 quality, uint32 itemId);
|
||||
std::vector<uint32> GetUpgradeList(Player* player, std::string spec, uint8 slot, uint32 quality, uint32 itemId, uint32 amount = 1);
|
||||
bool HasStatWeight(uint32 itemId);
|
||||
uint32 GetMinLevelFromCache(uint32 itemId);
|
||||
uint32 GetStatWeight(Player* player, uint32 itemId);
|
||||
uint32 GetLiveStatWeight(Player* player, uint32 itemId);
|
||||
uint32 GetRandomItem(uint32 level, RandomItemType type, RandomItemPredicate* predicate = nullptr);
|
||||
uint32 GetAmmo(uint32 level, uint32 subClass);
|
||||
uint32 GetRandomPotion(uint32 level, uint32 effect);
|
||||
uint32 GetRandomFood(uint32 level, uint32 category);
|
||||
uint32 GetFood(uint32 level, uint32 category);
|
||||
uint32 GetRandomTrade(uint32 level);
|
||||
uint32 CalculateStatWeight(uint8 playerclass, uint8 spec, ItemTemplate const* proto);
|
||||
uint32 CalculateSingleStatWeight(uint8 playerclass, uint8 spec, std::string stat, uint32 value);
|
||||
bool CanEquipArmor(uint8 clazz, uint32 level, ItemTemplate const* proto);
|
||||
bool ShouldEquipArmorForSpec(uint8 playerclass, uint8 spec, ItemTemplate const* proto);
|
||||
bool CanEquipWeapon(uint8 clazz, ItemTemplate const* proto);
|
||||
bool ShouldEquipWeaponForSpec(uint8 playerclass, uint8 spec, ItemTemplate const* proto);
|
||||
float GetItemRarity(uint32 itemId);
|
||||
uint32 GetQuestIdForItem(uint32 itemId);
|
||||
std::vector<uint32> GetQuestIdsForItem(uint32 itemId);
|
||||
|
||||
static bool IsUsedBySkill(ItemTemplate const* proto, uint32 skillId);
|
||||
|
||||
private:
|
||||
void BuildRandomItemCache();
|
||||
void BuildEquipCache();
|
||||
void BuildItemInfoCache();
|
||||
void BuildAmmoCache();
|
||||
void BuildFoodCache();
|
||||
void BuildPotionCache();
|
||||
void BuildTradeCache();
|
||||
void BuildRarityCache();
|
||||
bool CanEquipItem(BotEquipKey key, ItemTemplate const* proto);
|
||||
bool CanEquipItemNew(ItemTemplate const* proto);
|
||||
void AddItemStats(uint32 mod, uint8& sp, uint8& ap, uint8& tank);
|
||||
bool CheckItemStats(uint8 clazz, uint8 sp, uint8 ap, uint8 tank);
|
||||
|
||||
private:
|
||||
std::map<uint32, RandomItemCache> randomItemCache;
|
||||
std::map<RandomItemType, RandomItemPredicate*> predicates;
|
||||
BotEquipCache equipCache;
|
||||
std::map<EquipmentSlots, std::set<InventoryType>> viableSlots;
|
||||
std::map<uint32, std::map<uint32, uint32> > ammoCache;
|
||||
std::map<uint32, std::map<uint32, std::vector<uint32> > > potionCache;
|
||||
std::map<uint32, std::map<uint32, std::vector<uint32> > > foodCache;
|
||||
std::map<uint32, std::vector<uint32> > tradeCache;
|
||||
std::map<uint32, float> rarityCache;
|
||||
std::map<uint8, WeightScale> m_weightScales[MAX_CLASSES];
|
||||
std::map<std::string, uint32 > weightStatLink;
|
||||
std::map<std::string, uint32 > weightRatingLink;
|
||||
std::map<uint32, ItemInfoEntry> itemInfoCache;
|
||||
|
||||
static std::set<uint32> itemCache;
|
||||
};
|
||||
|
||||
#define sRandomItemMgr RandomItemMgr::instance()
|
||||
|
||||
#endif
|
||||
731
src/RandomPlayerbotFactory.cpp
Normal file
731
src/RandomPlayerbotFactory.cpp
Normal file
@ -0,0 +1,731 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "RandomPlayerbotFactory.h"
|
||||
#include "ArenaTeamMgr.h"
|
||||
#include "AccountMgr.h"
|
||||
#include "GuildMgr.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PlayerbotFactory.h"
|
||||
#include "SocialMgr.h"
|
||||
|
||||
std::map<uint8, std::vector<uint8>> RandomPlayerbotFactory::availableRaces;
|
||||
|
||||
RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(accountId)
|
||||
{
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_HUMAN);
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_NIGHTELF);
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_GNOME);
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_DWARF);
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_ORC);
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_UNDEAD_PLAYER);
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_TAUREN);
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_TROLL);
|
||||
availableRaces[CLASS_WARRIOR].push_back(RACE_DRAENEI);
|
||||
|
||||
availableRaces[CLASS_PALADIN].push_back(RACE_HUMAN);
|
||||
availableRaces[CLASS_PALADIN].push_back(RACE_DWARF);
|
||||
availableRaces[CLASS_PALADIN].push_back(RACE_DRAENEI);
|
||||
availableRaces[CLASS_PALADIN].push_back(RACE_BLOODELF);
|
||||
|
||||
availableRaces[CLASS_ROGUE].push_back(RACE_HUMAN);
|
||||
availableRaces[CLASS_ROGUE].push_back(RACE_DWARF);
|
||||
availableRaces[CLASS_ROGUE].push_back(RACE_NIGHTELF);
|
||||
availableRaces[CLASS_ROGUE].push_back(RACE_GNOME);
|
||||
availableRaces[CLASS_ROGUE].push_back(RACE_ORC);
|
||||
availableRaces[CLASS_ROGUE].push_back(RACE_TROLL);
|
||||
availableRaces[CLASS_ROGUE].push_back(RACE_BLOODELF);
|
||||
|
||||
availableRaces[CLASS_PRIEST].push_back(RACE_HUMAN);
|
||||
availableRaces[CLASS_PRIEST].push_back(RACE_DWARF);
|
||||
availableRaces[CLASS_PRIEST].push_back(RACE_NIGHTELF);
|
||||
availableRaces[CLASS_PRIEST].push_back(RACE_TROLL);
|
||||
availableRaces[CLASS_PRIEST].push_back(RACE_UNDEAD_PLAYER);
|
||||
availableRaces[CLASS_PRIEST].push_back(RACE_DRAENEI);
|
||||
availableRaces[CLASS_PRIEST].push_back(RACE_BLOODELF);
|
||||
|
||||
availableRaces[CLASS_MAGE].push_back(RACE_HUMAN);
|
||||
availableRaces[CLASS_MAGE].push_back(RACE_GNOME);
|
||||
availableRaces[CLASS_MAGE].push_back(RACE_UNDEAD_PLAYER);
|
||||
availableRaces[CLASS_MAGE].push_back(RACE_TROLL);
|
||||
availableRaces[CLASS_MAGE].push_back(RACE_DRAENEI);
|
||||
availableRaces[CLASS_MAGE].push_back(RACE_BLOODELF);
|
||||
|
||||
availableRaces[CLASS_WARLOCK].push_back(RACE_HUMAN);
|
||||
availableRaces[CLASS_WARLOCK].push_back(RACE_GNOME);
|
||||
availableRaces[CLASS_WARLOCK].push_back(RACE_UNDEAD_PLAYER);
|
||||
availableRaces[CLASS_WARLOCK].push_back(RACE_ORC);
|
||||
availableRaces[CLASS_WARLOCK].push_back(RACE_BLOODELF);
|
||||
|
||||
availableRaces[CLASS_SHAMAN].push_back(RACE_ORC);
|
||||
availableRaces[CLASS_SHAMAN].push_back(RACE_TAUREN);
|
||||
availableRaces[CLASS_SHAMAN].push_back(RACE_TROLL);
|
||||
availableRaces[CLASS_SHAMAN].push_back(RACE_DRAENEI);
|
||||
|
||||
availableRaces[CLASS_HUNTER].push_back(RACE_DWARF);
|
||||
availableRaces[CLASS_HUNTER].push_back(RACE_NIGHTELF);
|
||||
availableRaces[CLASS_HUNTER].push_back(RACE_ORC);
|
||||
availableRaces[CLASS_HUNTER].push_back(RACE_TAUREN);
|
||||
availableRaces[CLASS_HUNTER].push_back(RACE_TROLL);
|
||||
availableRaces[CLASS_HUNTER].push_back(RACE_DRAENEI);
|
||||
availableRaces[CLASS_HUNTER].push_back(RACE_BLOODELF);
|
||||
|
||||
availableRaces[CLASS_DRUID].push_back(RACE_NIGHTELF);
|
||||
availableRaces[CLASS_DRUID].push_back(RACE_TAUREN);
|
||||
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_NIGHTELF);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_TAUREN);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_HUMAN);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_ORC);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_UNDEAD_PLAYER);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_TROLL);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_BLOODELF);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_DRAENEI);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_GNOME);
|
||||
availableRaces[CLASS_DEATH_KNIGHT].push_back(RACE_DWARF);
|
||||
}
|
||||
|
||||
Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map<uint8, std::vector<std::string>> names)
|
||||
{
|
||||
LOG_DEBUG("playerbots", "Creating new random bot for class {}", cls);
|
||||
|
||||
uint8 gender = rand() % 2 ? GENDER_MALE : GENDER_FEMALE;
|
||||
|
||||
uint8 race = availableRaces[cls][urand(0, availableRaces[cls].size() - 1)];
|
||||
|
||||
std::string name;
|
||||
if (names.empty())
|
||||
name = CreateRandomBotName(gender);
|
||||
else
|
||||
{
|
||||
if (names[gender].empty())
|
||||
return nullptr;
|
||||
|
||||
uint32 i = urand(0, names[gender].size() - 1);
|
||||
name = names[gender][i];
|
||||
std::swap(names[gender][i], names[gender].back());
|
||||
names[gender].pop_back();
|
||||
}
|
||||
|
||||
if (name.empty())
|
||||
return nullptr;
|
||||
|
||||
std::vector<uint8> skinColors, facialHairTypes;
|
||||
std::vector<std::pair<uint8,uint8>> faces, hairs;
|
||||
for (CharSectionsEntry const* charSection : sCharSectionsStore)
|
||||
{
|
||||
if (charSection->Race != race || charSection->Gender != gender)
|
||||
continue;
|
||||
|
||||
switch (charSection->GenType)
|
||||
{
|
||||
case SECTION_TYPE_SKIN:
|
||||
skinColors.push_back(charSection->Color);
|
||||
break;
|
||||
case SECTION_TYPE_FACE:
|
||||
faces.push_back(std::pair<uint8, uint8>(charSection->Type, charSection->Color));
|
||||
break;
|
||||
case SECTION_TYPE_FACIAL_HAIR:
|
||||
facialHairTypes.push_back(charSection->Type);
|
||||
break;
|
||||
case SECTION_TYPE_HAIR:
|
||||
hairs.push_back(std::pair<uint8, uint8>(charSection->Type, charSection->Color));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 skinColor = skinColors[urand(0, skinColors.size() - 1)];
|
||||
std::pair<uint8, uint8> face = faces[urand(0, faces.size() - 1)];
|
||||
std::pair<uint8, uint8> hair = hairs[urand(0, hairs.size() - 1)];
|
||||
|
||||
bool excludeCheck = (race == RACE_TAUREN) || (race == RACE_DRAENEI) || (gender == GENDER_FEMALE && race != RACE_NIGHTELF && race != RACE_UNDEAD_PLAYER);
|
||||
uint8 facialHair = excludeCheck ? 0 : facialHairTypes[urand(0, facialHairTypes.size() - 1)];
|
||||
|
||||
std::unique_ptr<CharacterCreateInfo> characterInfo = std::make_unique<CharacterCreateInfo>(name, race, cls, gender, face.second, face.first, hair.first, hair.second, facialHair);
|
||||
|
||||
Player* player = new Player(session);
|
||||
player->GetMotionMaster()->Initialize();
|
||||
if (!player->Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), characterInfo.get()))
|
||||
{
|
||||
player->CleanupsBeforeDelete();
|
||||
delete player;
|
||||
|
||||
LOG_ERROR("playerbots", "Unable to create random bot for account {} - name: \"{}\"; race: {}; class: {}", accountId, name.c_str(), race, cls);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
player->setCinematic(2);
|
||||
player->SetAtLoginFlag(AT_LOGIN_NONE);
|
||||
|
||||
LOG_DEBUG("playerbots", "Random bot created for account {} - name: \"{}\"; race: {}; class: {}", accountId, name.c_str(), race, cls);
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
std::string const RandomPlayerbotFactory::CreateRandomBotName(uint8 gender)
|
||||
{
|
||||
std::string botName = "";
|
||||
|
||||
QueryResult result = CharacterDatabase.Query("SELECT MAX(name_id) FROM playerbots_names");
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random bots");
|
||||
return std::move(botName);
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
uint32 maxId = fields[0].Get<uint32>();
|
||||
|
||||
result = CharacterDatabase.Query("SELECT n.name FROM playerbots_names n "
|
||||
"LEFT OUTER JOIN characters e ON e.name = n.name WHERE e.guid IS NULL AND n.gender = {} ORDER BY RAND() LIMIT 1", gender);
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random bots");
|
||||
return std::move(botName);
|
||||
}
|
||||
|
||||
fields = result->Fetch();
|
||||
botName = fields[0].Get<std::string>();
|
||||
|
||||
return std::move(botName);
|
||||
}
|
||||
|
||||
void RandomPlayerbotFactory::CreateRandomBots()
|
||||
{
|
||||
// check if scheduled for delete
|
||||
bool delAccs = false;
|
||||
bool delFriends = false;
|
||||
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_VALUE);
|
||||
stmt->SetData(0, "bot_delete");
|
||||
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
|
||||
{
|
||||
delAccs = true;
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
uint32 deleteType = fields[0].Get<uint32>();
|
||||
|
||||
if (deleteType > 1)
|
||||
delFriends = true;
|
||||
|
||||
PlayerbotsDatabase.Execute("DELETE FROM playerbots_random_bots WHERE event = 'bot_delete'");
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->deleteRandomBotAccounts || delAccs)
|
||||
{
|
||||
std::vector<uint32> botAccounts;
|
||||
std::vector<uint32> botFriends;
|
||||
|
||||
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
|
||||
std::string const accountName = out.str();
|
||||
|
||||
if (uint32 accountId = AccountMgr::GetId(accountName))
|
||||
botAccounts.push_back(accountId);
|
||||
}
|
||||
|
||||
if (!delFriends)
|
||||
LOG_INFO("playerbots", "Deleting random bot characters without friends/guild...");
|
||||
else
|
||||
LOG_INFO("playerbots", "Deleting all random bot characters...");
|
||||
|
||||
// load list of friends
|
||||
if (!delFriends)
|
||||
{
|
||||
QueryResult result = CharacterDatabase.Query("SELECT friend FROM character_social WHERE flags={}", SOCIAL_FLAG_FRIEND);
|
||||
if (result)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 guidlow = fields[0].Get<uint32>();
|
||||
botFriends.push_back(guidlow);
|
||||
|
||||
} while (result->NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::future<void>> dels;
|
||||
QueryResult results = LoginDatabase.Query("SELECT id FROM account WHERE username LIKE ''{}'%%'", sPlayerbotAIConfig->randomBotAccountPrefix.c_str());
|
||||
if (results)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = results->Fetch();
|
||||
uint32 accId = fields[0].Get<uint32>();
|
||||
|
||||
if (!delFriends)
|
||||
{
|
||||
// existing characters list
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID);
|
||||
stmt->SetData(0, accId);
|
||||
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 guidlow = fields[0].Get<uint32>();
|
||||
ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>(guidlow);
|
||||
|
||||
// if bot is someone's friend - don't delete it
|
||||
if ((find(botFriends.begin(), botFriends.end(), guidlow) != botFriends.end()) && !delFriends)
|
||||
continue;
|
||||
// if bot is in someone's guild - don't delete it
|
||||
uint32 guildId = sCharacterCache->GetCharacterGuildIdByGuid(guid);
|
||||
if (guildId && !delFriends)
|
||||
{
|
||||
Guild* guild = sGuildMgr->GetGuildById(guildId);
|
||||
uint32 accountId = sRandomPlayerbotMgr->GetAccountId(guild->GetLeaderGUID());
|
||||
|
||||
if (find(botAccounts.begin(), botAccounts.end(), accountId) == botAccounts.end())
|
||||
continue;
|
||||
}
|
||||
|
||||
Player::DeleteFromDB(guidlow, accId, false, true); // no need to update realm characters
|
||||
} while (result->NextRow());
|
||||
}
|
||||
}
|
||||
else
|
||||
dels.push_back(std::async([accId]
|
||||
{
|
||||
AccountMgr::DeleteAccount(accId);
|
||||
}));
|
||||
|
||||
} while (results->NextRow());
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < dels.size(); i++)
|
||||
{
|
||||
dels[i].wait();
|
||||
}
|
||||
|
||||
PlayerbotsDatabase.Execute(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_RANDOM_BOTS));
|
||||
|
||||
LOG_INFO("playerbots", "Random bot characters deleted");
|
||||
}
|
||||
|
||||
uint32 totalAccCount = sPlayerbotAIConfig->randomBotAccountCount;
|
||||
|
||||
LOG_INFO("server.loading", "Creating random bot accounts...");
|
||||
|
||||
std::vector<std::future<void>> account_creations;
|
||||
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
|
||||
std::string const accountName = out.str();
|
||||
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME);
|
||||
stmt->SetData(0, accountName);
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
if (result)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string password = "";
|
||||
if (sPlayerbotAIConfig->randomBotRandomPassword)
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
password += (char) urand('!', 'z');
|
||||
}
|
||||
}
|
||||
else
|
||||
password = accountName;
|
||||
|
||||
account_creations.push_back(std::async([accountName, password]
|
||||
{
|
||||
AccountMgr::CreateAccount(accountName, password);
|
||||
}));
|
||||
|
||||
LOG_DEBUG("playerbots", "Account {} created for random bots", accountName.c_str());
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < account_creations.size(); i++)
|
||||
{
|
||||
account_creations[i].wait();
|
||||
}
|
||||
|
||||
//LoginDatabase.Execute("UPDATE account SET expansion = {} WHERE username LIKE ''{}'%%'", EXPANSION_WRATH_OF_THE_LICH_KING, sPlayerbotAIConfig->randomBotAccountPrefix.c_str());
|
||||
|
||||
LOG_INFO("server.loading", "Loading available names...");
|
||||
std::unordered_map<uint8,std::vector<std::string>> names;
|
||||
QueryResult result = CharacterDatabase.Query("SELECT n.gender, n.name FROM playerbots_names n LEFT OUTER JOIN characters e ON e.name = n.name WHERE e.guid IS NULL");
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("server.loading", "No more names left for random bots");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint8 gender = fields[0].Get<uint8>();
|
||||
std::string const bname = fields[1].Get<std::string>();
|
||||
names[gender].push_back(bname);
|
||||
} while (result->NextRow());
|
||||
|
||||
LOG_INFO("playerbots", "Creating random bot characters...");
|
||||
uint32 totalRandomBotChars = 0;
|
||||
uint32 totalCharCount = sPlayerbotAIConfig->randomBotAccountCount * 10;
|
||||
|
||||
std::vector<std::pair<Player*, uint32>> playerBots;
|
||||
std::vector<WorldSession*> sessionBots;
|
||||
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
|
||||
std::string const accountName = out.str();
|
||||
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME);
|
||||
stmt->SetData(0, accountName);
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
if (!result)
|
||||
continue;
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
uint32 accountId = fields[0].Get<uint32>();
|
||||
|
||||
sPlayerbotAIConfig->randomBotAccounts.push_back(accountId);
|
||||
|
||||
uint32 count = AccountMgr::GetCharactersCount(accountId);
|
||||
if (count >= 10)
|
||||
{
|
||||
totalRandomBotChars += count;
|
||||
continue;
|
||||
}
|
||||
|
||||
RandomPlayerbotFactory factory(accountId);
|
||||
|
||||
WorldSession* session = new WorldSession(accountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), LOCALE_enUS, 0, false, false, 0, true);
|
||||
sessionBots.push_back(session);
|
||||
|
||||
for (uint8 cls = CLASS_WARRIOR; cls < MAX_CLASSES - count; ++cls)
|
||||
{
|
||||
if (cls != 10)
|
||||
if (Player* playerBot = factory.CreateRandomBot(session, cls, names))
|
||||
playerBots.emplace_back(playerBot, accountId);
|
||||
}
|
||||
|
||||
totalRandomBotChars += AccountMgr::GetCharactersCount(accountId);
|
||||
}
|
||||
|
||||
std::vector<std::future<void>> bot_creations;
|
||||
for (auto const& itr : playerBots)
|
||||
{
|
||||
Player* player = itr.first;
|
||||
uint32 accountId = itr.second;
|
||||
bot_creations.push_back(std::async([player, accountId]
|
||||
{
|
||||
player->SaveToDB(true, false);
|
||||
sCharacterCache->AddCharacterCacheEntry(player->GetGUID(), accountId, player->GetName(), player->getGender(), player->getRace(), player->getClass(), player->getLevel());
|
||||
player->CleanupsBeforeDelete();
|
||||
delete player;
|
||||
}));
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < bot_creations.size(); i++)
|
||||
{
|
||||
bot_creations[i].wait();
|
||||
}
|
||||
|
||||
for (WorldSession* session : sessionBots)
|
||||
delete session;
|
||||
|
||||
LOG_INFO("server.loading", "{} random bot accounts with {} characters available", sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars);
|
||||
}
|
||||
|
||||
void RandomPlayerbotFactory::CreateRandomGuilds()
|
||||
{
|
||||
std::vector<uint32> randomBots;
|
||||
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT);
|
||||
stmt->SetData(0, "add");
|
||||
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 bot = fields[0].Get<uint32>();
|
||||
randomBots.push_back(bot);
|
||||
}
|
||||
while (result->NextRow());
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->deleteRandomBotGuilds)
|
||||
{
|
||||
LOG_INFO("playerbots", "Deleting random bot guilds...");
|
||||
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
|
||||
{
|
||||
if (Guild* guild = sGuildMgr->GetGuildByLeader(ObjectGuid::Create<HighGuid::Player>(*i)))
|
||||
guild->Disband();
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Random bot guilds deleted");
|
||||
}
|
||||
|
||||
uint32 guildNumber = 0;
|
||||
GuidVector availableLeaders;
|
||||
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
|
||||
{
|
||||
ObjectGuid leader = ObjectGuid::Create<HighGuid::Player>(*i);
|
||||
if (Guild* guild = sGuildMgr->GetGuildByLeader(leader))
|
||||
{
|
||||
++guildNumber;
|
||||
sPlayerbotAIConfig->randomBotGuilds.push_back(guild->GetId());
|
||||
}
|
||||
else
|
||||
{
|
||||
Player* player = ObjectAccessor::FindPlayer(leader);
|
||||
if (player && !player->GetGuildId())
|
||||
availableLeaders.push_back(leader);
|
||||
}
|
||||
}
|
||||
|
||||
for (; guildNumber < sPlayerbotAIConfig->randomBotGuildCount; ++guildNumber)
|
||||
{
|
||||
std::string const guildName = CreateRandomGuildName();
|
||||
if (guildName.empty())
|
||||
continue;
|
||||
|
||||
if (availableLeaders.empty())
|
||||
{
|
||||
LOG_ERROR("playerbots", "No leaders for random guilds available");
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 index = urand(0, availableLeaders.size() - 1);
|
||||
ObjectGuid leader = availableLeaders[index];
|
||||
Player* player = ObjectAccessor::FindPlayer(leader);
|
||||
if (!player)
|
||||
{
|
||||
LOG_ERROR("playerbots", "Cannot find player for leader {}", player->GetName().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
Guild* guild = new Guild();
|
||||
if (!guild->Create(player, guildName))
|
||||
{
|
||||
LOG_ERROR("playerbots", "Error creating guild {}", guildName.c_str());
|
||||
delete guild;
|
||||
continue;
|
||||
}
|
||||
|
||||
sGuildMgr->AddGuild(guild);
|
||||
|
||||
// create random emblem
|
||||
uint32 st, cl, br, bc, bg;
|
||||
bg = urand(0, 51);
|
||||
bc = urand(0, 17);
|
||||
cl = urand(0, 17);
|
||||
br = urand(0, 7);
|
||||
st = urand(0, 180);
|
||||
EmblemInfo emblemInfo(st, cl, br, bc, bg);
|
||||
guild->HandleSetEmblem(emblemInfo);
|
||||
|
||||
sPlayerbotAIConfig->randomBotGuilds.push_back(guild->GetId());
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "{} random bot guilds available", guildNumber);
|
||||
}
|
||||
|
||||
std::string const RandomPlayerbotFactory::CreateRandomGuildName()
|
||||
{
|
||||
std::string guildName = "";
|
||||
|
||||
QueryResult result = CharacterDatabase.Query("SELECT MAX(name_id) FROM playerbots_guild_names");
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random guilds");
|
||||
return std::move(guildName);
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
uint32 maxId = fields[0].Get<uint32>();
|
||||
|
||||
uint32 id = urand(0, maxId);
|
||||
result = CharacterDatabase.Query("SELECT n.name FROM playerbots_guild_names n "
|
||||
"LEFT OUTER JOIN guild e ON e.name = n.name WHERE e.guildid IS NULL AND n.name_id >= {} LIMIT 1", id);
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random guilds");
|
||||
return std::move(guildName);
|
||||
}
|
||||
|
||||
fields = result->Fetch();
|
||||
guildName = fields[0].Get<std::string>();
|
||||
|
||||
return std::move(guildName);
|
||||
}
|
||||
|
||||
void RandomPlayerbotFactory::CreateRandomArenaTeams()
|
||||
{
|
||||
std::vector<uint32> randomBots;
|
||||
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BOT);
|
||||
stmt->SetData(0, "add");
|
||||
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 bot = fields[0].Get<uint32>();
|
||||
randomBots.push_back(bot);
|
||||
}
|
||||
while (result->NextRow());
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->deleteRandomBotArenaTeams)
|
||||
{
|
||||
LOG_INFO("playerbots", "Deleting random bot arena teams...");
|
||||
|
||||
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
|
||||
{
|
||||
ObjectGuid captain = ObjectGuid::Create<HighGuid::Player>(*i);
|
||||
ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain);
|
||||
if (arenateam)
|
||||
//sObjectMgr->RemoveArenaTeam(arenateam->GetId());
|
||||
arenateam->Disband(nullptr);
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Random bot arena teams deleted");
|
||||
}
|
||||
|
||||
uint32 arenaTeamNumber = 0;
|
||||
GuidVector availableCaptains;
|
||||
for (std::vector<uint32>::iterator i = randomBots.begin(); i != randomBots.end(); ++i)
|
||||
{
|
||||
ObjectGuid captain = ObjectGuid::Create<HighGuid::Player>(*i);
|
||||
ArenaTeam* arenateam = sArenaTeamMgr->GetArenaTeamByCaptain(captain);
|
||||
if (arenateam)
|
||||
{
|
||||
++arenaTeamNumber;
|
||||
sPlayerbotAIConfig->randomBotArenaTeams.push_back(arenateam->GetId());
|
||||
}
|
||||
else
|
||||
{
|
||||
Player* player = ObjectAccessor::FindConnectedPlayer(captain);
|
||||
|
||||
if (!arenateam && player && player->getLevel() >= 70)
|
||||
availableCaptains.push_back(captain);
|
||||
}
|
||||
}
|
||||
|
||||
for (; arenaTeamNumber < sPlayerbotAIConfig->randomBotArenaTeamCount; ++arenaTeamNumber)
|
||||
{
|
||||
std::string const arenaTeamName = CreateRandomArenaTeamName();
|
||||
if (arenaTeamName.empty())
|
||||
continue;
|
||||
|
||||
if (availableCaptains.empty())
|
||||
{
|
||||
LOG_ERROR("playerbots", "No captains for random arena teams available");
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 index = urand(0, availableCaptains.size() - 1);
|
||||
ObjectGuid captain = availableCaptains[index];
|
||||
Player* player = ObjectAccessor::FindConnectedPlayer(captain);
|
||||
if (!player)
|
||||
{
|
||||
LOG_ERROR("playerbots", "Cannot find player for captain {}", captain.ToString().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->getLevel() < 70)
|
||||
{
|
||||
LOG_ERROR("playerbots", "Bot {} must be level 70 to create an arena team", captain.ToString().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
QueryResult results = CharacterDatabase.Query("SELECT `type` FROM playerbots_arena_team_names WHERE name = '{}'", arenaTeamName.c_str());
|
||||
if (!results)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No valid types for arena teams");
|
||||
return;
|
||||
}
|
||||
|
||||
Field* fields = results->Fetch();
|
||||
uint8 slot = fields[0].Get<uint8>();
|
||||
|
||||
ArenaType type;
|
||||
switch (slot)
|
||||
{
|
||||
case 2:
|
||||
type = ARENA_TYPE_2v2;
|
||||
break;
|
||||
case 3:
|
||||
type = ARENA_TYPE_3v3;
|
||||
break;
|
||||
case 5:
|
||||
type = ARENA_TYPE_5v5;
|
||||
break;
|
||||
}
|
||||
|
||||
ArenaTeam* arenateam = new ArenaTeam();
|
||||
if (!arenateam->Create(player->GetGUID(), type, arenaTeamName, 0, 0, 0, 0, 0))
|
||||
{
|
||||
LOG_ERROR("playerbots", "Error creating arena team {}", arenaTeamName.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
arenateam->SetCaptain(player->GetGUID());
|
||||
|
||||
// set random rating
|
||||
arenateam->SetRatingForAll(urand(1500, 2700));
|
||||
|
||||
// set random emblem
|
||||
uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
uint32 emblemStyle = urand(0, 5);
|
||||
uint32 emblemColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
uint32 borderStyle = urand(0, 5);
|
||||
uint32 borderColor = urand(0xFF000000, 0xFFFFFFFF);
|
||||
arenateam->SetEmblem(backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor);
|
||||
|
||||
// set random kills (wip)
|
||||
//arenateam->SetStats(STAT_TYPE_GAMES_WEEK, urand(0, 30));
|
||||
//arenateam->SetStats(STAT_TYPE_WINS_WEEK, urand(0, arenateam->GetStats().games_week));
|
||||
//arenateam->SetStats(STAT_TYPE_GAMES_SEASON, urand(arenateam->GetStats().games_week, arenateam->GetStats().games_week * 5));
|
||||
//arenateam->SetStats(STAT_TYPE_WINS_SEASON, urand(arenateam->GetStats().wins_week, arenateam->GetStats().games
|
||||
arenateam->SaveToDB();
|
||||
|
||||
sArenaTeamMgr->AddArenaTeam(arenateam);
|
||||
sPlayerbotAIConfig->randomBotArenaTeams.push_back(arenateam->GetId());
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "{} random bot arena teams available", arenaTeamNumber);
|
||||
}
|
||||
|
||||
std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName()
|
||||
{
|
||||
std::string arenaTeamName = "";
|
||||
|
||||
QueryResult result = CharacterDatabase.Query("SELECT MAX(name_id) FROM playerbots_arena_team_names");
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random arena teams");
|
||||
return std::move(arenaTeamName);
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
uint32 maxId = fields[0].Get<uint32>();
|
||||
|
||||
uint32 id = urand(0, maxId);
|
||||
result = CharacterDatabase.Query("SELECT n.name FROM playerbots_arena_team_names n LEFT OUTER JOIN arena_team e ON e.name = n.name "
|
||||
"WHERE e.arenateamid IS NULL AND n.name_id >= {} LIMIT 1", id);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
LOG_ERROR("playerbots", "No more names left for random arena teams");
|
||||
return std::move(arenaTeamName);
|
||||
}
|
||||
|
||||
fields = result->Fetch();
|
||||
arenaTeamName = fields[0].Get<std::string>();
|
||||
|
||||
return std::move(arenaTeamName);
|
||||
}
|
||||
36
src/RandomPlayerbotFactory.h
Normal file
36
src/RandomPlayerbotFactory.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_RANDOMPLAYERBOTFACTORY_H
|
||||
#define _PLAYERBOT_RANDOMPLAYERBOTFACTORY_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
class Player;
|
||||
class WorldSession;
|
||||
|
||||
class RandomPlayerbotFactory
|
||||
{
|
||||
public:
|
||||
RandomPlayerbotFactory(uint32 accountId);
|
||||
virtual ~RandomPlayerbotFactory() { }
|
||||
|
||||
Player* CreateRandomBot(WorldSession* session, uint8 cls, std::unordered_map<uint8, std::vector<std::string>> names);
|
||||
static void CreateRandomBots();
|
||||
static void CreateRandomGuilds();
|
||||
static void CreateRandomArenaTeams();
|
||||
static std::string const CreateRandomGuildName();
|
||||
|
||||
private:
|
||||
std::string const CreateRandomBotName(uint8 gender);
|
||||
static std::string const CreateRandomArenaTeamName();
|
||||
|
||||
uint32 accountId;
|
||||
static std::map<uint8, std::vector<uint8>> availableRaces;
|
||||
};
|
||||
|
||||
#endif
|
||||
2242
src/RandomPlayerbotMgr.cpp
Normal file
2242
src/RandomPlayerbotMgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
134
src/RandomPlayerbotMgr.h
Normal file
134
src/RandomPlayerbotMgr.h
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_RANDOMPLAYERBOTMGR_H
|
||||
#define _PLAYERBOT_RANDOMPLAYERBOTMGR_H
|
||||
|
||||
#include "PlayerbotMgr.h"
|
||||
|
||||
class ChatHandler;
|
||||
class PerformanceMonitorOperation;
|
||||
class WorldLocation;
|
||||
|
||||
class CachedEvent
|
||||
{
|
||||
public:
|
||||
CachedEvent() : value(0), lastChangeTime(0), validIn(0), data("") { }
|
||||
CachedEvent(const CachedEvent& other) : value(other.value), lastChangeTime(other.lastChangeTime), validIn(other.validIn), data(other.data) { }
|
||||
CachedEvent(uint32 value, uint32 lastChangeTime, uint32 validIn, std::string const data = "") : value(value), lastChangeTime(lastChangeTime), validIn(validIn), data(data) { }
|
||||
|
||||
bool IsEmpty() { return !lastChangeTime; }
|
||||
|
||||
public:
|
||||
uint32 value;
|
||||
uint32 lastChangeTime;
|
||||
uint32 validIn;
|
||||
std::string data;
|
||||
};
|
||||
|
||||
class RandomPlayerbotMgr : public PlayerbotHolder
|
||||
{
|
||||
public:
|
||||
RandomPlayerbotMgr();
|
||||
virtual ~RandomPlayerbotMgr();
|
||||
static RandomPlayerbotMgr* instance()
|
||||
{
|
||||
static RandomPlayerbotMgr instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void LogPlayerLocation();
|
||||
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
|
||||
|
||||
public:
|
||||
uint32 activeBots = 0;
|
||||
static bool HandlePlayerbotConsoleCommand(ChatHandler* handler, char const* args);
|
||||
bool IsRandomBot(Player* bot);
|
||||
bool IsRandomBot(ObjectGuid::LowType bot);
|
||||
void Randomize(Player* bot);
|
||||
void RandomizeFirst(Player* bot);
|
||||
void IncreaseLevel(Player* bot);
|
||||
void ScheduleTeleport(uint32 bot, uint32 time = 0);
|
||||
void ScheduleChangeStrategy(uint32 bot, uint32 time = 0);
|
||||
void HandleCommand(uint32 type, std::string const text, Player* fromPlayer);
|
||||
std::string const HandleRemoteCommand(std::string const request);
|
||||
void OnPlayerLogout(Player* player);
|
||||
void OnPlayerLogin(Player* player);
|
||||
void OnPlayerLoginError(uint32 bot);
|
||||
Player* GetRandomPlayer();
|
||||
std::vector<Player*> GetPlayers() { return players; };
|
||||
PlayerBotMap GetAllBots() { return playerBots; };
|
||||
void PrintStats();
|
||||
double GetBuyMultiplier(Player* bot);
|
||||
double GetSellMultiplier(Player* bot);
|
||||
void AddTradeDiscount(Player* bot, Player* master, int32 value);
|
||||
void SetTradeDiscount(Player* bot, Player* master, uint32 value);
|
||||
uint32 GetTradeDiscount(Player* bot, Player* master);
|
||||
void Refresh(Player* bot);
|
||||
void RandomTeleportForLevel(Player* bot);
|
||||
void RandomTeleportForRpg(Player* bot);
|
||||
uint32 GetMaxAllowedBotCount();
|
||||
bool ProcessBot(Player* player);
|
||||
void Revive(Player* player);
|
||||
void ChangeStrategy(Player* player);
|
||||
uint32 GetValue(Player* bot, std::string const type);
|
||||
uint32 GetValue(uint32 bot, std::string const type);
|
||||
std::string const GetData(uint32 bot, std::string const type);
|
||||
void SetValue(uint32 bot, std::string const type, uint32 value, std::string const data = "");
|
||||
void SetValue(Player* bot, std::string const type, uint32 value, std::string const data = "");
|
||||
void Remove(Player* bot);
|
||||
ObjectGuid const GetBattleMasterGUID(Player* bot, BattlegroundTypeId bgTypeId);
|
||||
CreatureData const* GetCreatureDataByEntry(uint32 entry);
|
||||
void LoadBattleMastersCache();
|
||||
std::map<uint32, std::map<uint32, std::map<TeamId, bool>>> NeedBots;
|
||||
std::map<uint32, std::map<uint32, std::map<TeamId, uint32>>> BgBots;
|
||||
std::map<uint32, std::map<uint32, std::map<TeamId, uint32>>> VisualBots;
|
||||
std::map<uint32, std::map<uint32, std::map<TeamId, uint32>>> BgPlayers;
|
||||
std::map<uint32, std::map<uint32, std::map<TeamId, std::map<TeamId, uint32>>>> ArenaBots;
|
||||
std::map<uint32, std::map<uint32, std::map<uint32, uint32>>> Rating;
|
||||
std::map<uint32, std::map<uint32, std::map<uint32, uint32>>> Supporters;
|
||||
std::map<TeamId, std::vector<uint32>> LfgDungeons;
|
||||
void CheckBgQueue();
|
||||
void CheckLfgQueue();
|
||||
void CheckPlayers();
|
||||
|
||||
std::map<TeamId, std::map<BattlegroundTypeId, std::vector<uint32>>> getBattleMastersCache() { return BattleMastersCache; }
|
||||
|
||||
protected:
|
||||
void OnBotLoginInternal(Player* const bot) override;
|
||||
|
||||
private:
|
||||
uint32 GetEventValue(uint32 bot, std::string const event);
|
||||
std::string const GetEventData(uint32 bot, std::string const event);
|
||||
uint32 SetEventValue(uint32 bot, std::string const event, uint32 value, uint32 validIn, std::string const data = "");
|
||||
std::list<uint32> GetBots();
|
||||
std::vector<uint32> GetBgBots(uint32 bracket);
|
||||
time_t BgCheckTimer;
|
||||
time_t LfgCheckTimer;
|
||||
time_t PlayersCheckTimer;
|
||||
uint32 AddRandomBots();
|
||||
bool ProcessBot(uint32 bot);
|
||||
void ScheduleRandomize(uint32 bot, uint32 time);
|
||||
void RandomTeleport(Player* bot);
|
||||
void RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth = false);
|
||||
uint32 GetZoneLevel(uint16 mapId, float teleX, float teleY, float teleZ);
|
||||
void PrepareTeleportCache();
|
||||
typedef void(RandomPlayerbotMgr::*ConsoleCommandHandler)(Player*);
|
||||
|
||||
std::vector<Player*> players;
|
||||
uint32 processTicks;
|
||||
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
|
||||
std::map<uint32, std::vector<WorldLocation>> rpgLocsCache;
|
||||
std::map<uint32, std::map<uint32, std::vector<WorldLocation>>> rpgLocsCacheLevel;
|
||||
std::map<TeamId, std::map<BattlegroundTypeId, std::vector<uint32>>> BattleMastersCache;
|
||||
std::map<uint32, std::map<std::string, CachedEvent>> eventCache;
|
||||
std::list<uint32> currentBots;
|
||||
uint32 bgBotsCount;
|
||||
uint32 playersLevel;
|
||||
PerformanceMonitorOperation* totalPmo;
|
||||
};
|
||||
|
||||
#define sRandomPlayerbotMgr RandomPlayerbotMgr::instance()
|
||||
|
||||
#endif
|
||||
72
src/ServerFacade.cpp
Normal file
72
src/ServerFacade.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "ServerFacade.h"
|
||||
#include "Playerbots.h"
|
||||
#include "TargetedMovementGenerator.h"
|
||||
|
||||
float ServerFacade::GetDistance2d(Unit* unit, WorldObject* wo)
|
||||
{
|
||||
ASSERT_NOTNULL(unit);
|
||||
ASSERT_NOTNULL(wo);
|
||||
|
||||
float dist = unit->GetDistance2d(wo);
|
||||
return std::round(dist * 10.0f) / 10.0f;
|
||||
}
|
||||
|
||||
float ServerFacade::GetDistance2d(Unit *unit, float x, float y)
|
||||
{
|
||||
float dist = unit->GetDistance2d(x, y);
|
||||
return std::round(dist * 10.0f) / 10.0f;
|
||||
}
|
||||
|
||||
bool ServerFacade::IsDistanceLessThan(float dist1, float dist2)
|
||||
{
|
||||
return dist1 - dist2 < sPlayerbotAIConfig->targetPosRecalcDistance;
|
||||
}
|
||||
|
||||
bool ServerFacade::IsDistanceGreaterThan(float dist1, float dist2)
|
||||
{
|
||||
return dist1 - dist2 > sPlayerbotAIConfig->targetPosRecalcDistance;
|
||||
}
|
||||
|
||||
bool ServerFacade::IsDistanceGreaterOrEqualThan(float dist1, float dist2)
|
||||
{
|
||||
return !IsDistanceLessThan(dist1, dist2);
|
||||
}
|
||||
|
||||
bool ServerFacade::IsDistanceLessOrEqualThan(float dist1, float dist2)
|
||||
{
|
||||
return !IsDistanceGreaterThan(dist1, dist2);
|
||||
}
|
||||
|
||||
void ServerFacade::SetFacingTo(Player* bot, WorldObject* wo, bool force)
|
||||
{
|
||||
float angle = bot->GetAngle(wo);
|
||||
if (!force && bot->isMoving())
|
||||
bot->SetFacingTo(bot->GetAngle(wo));
|
||||
else
|
||||
{
|
||||
bot->SetOrientation(angle);
|
||||
bot->SendMovementFlagUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
Unit* ServerFacade::GetChaseTarget(Unit* target)
|
||||
{
|
||||
MovementGenerator* movementGen = target->GetMotionMaster()->top();
|
||||
if (movementGen && movementGen->GetMovementGeneratorType() == CHASE_MOTION_TYPE)
|
||||
{
|
||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
return static_cast<ChaseMovementGenerator<Player> const*>(movementGen)->GetTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<ChaseMovementGenerator<Creature> const*>(movementGen)->GetTarget();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
40
src/ServerFacade.h
Normal file
40
src/ServerFacade.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_SERVERFACADE_H
|
||||
#define _PLAYERBOT_SERVERFACADE_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
class Player;
|
||||
class Unit;
|
||||
class WorldObject;
|
||||
|
||||
class ServerFacade
|
||||
{
|
||||
public:
|
||||
ServerFacade() { };
|
||||
virtual ~ServerFacade() { };
|
||||
static ServerFacade* instance()
|
||||
{
|
||||
static ServerFacade instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
public:
|
||||
float GetDistance2d(Unit* unit, WorldObject* wo);
|
||||
float GetDistance2d(Unit* unit, float x, float y);
|
||||
bool IsDistanceLessThan(float dist1, float dist2);
|
||||
bool IsDistanceGreaterThan(float dist1, float dist2);
|
||||
bool IsDistanceGreaterOrEqualThan(float dist1, float dist2);
|
||||
bool IsDistanceLessOrEqualThan(float dist1, float dist2);
|
||||
|
||||
void SetFacingTo(Player* bot, WorldObject* wo, bool force = false);
|
||||
|
||||
Unit* GetChaseTarget(Unit* target);
|
||||
};
|
||||
|
||||
#define sServerFacade ServerFacade::instance()
|
||||
|
||||
#endif
|
||||
517
src/Talentspec.cpp
Normal file
517
src/Talentspec.cpp
Normal file
@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "Talentspec.h"
|
||||
#include "Event.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
uint32 TalentSpec::TalentListEntry::tabPage() const
|
||||
{
|
||||
return talentTabInfo->TalentTabID == 41 ? 1 : talentTabInfo->tabpage;
|
||||
}
|
||||
|
||||
//Checks a talent link on basic validity.
|
||||
bool TalentSpec::CheckTalentLink(std::string const link, std::ostringstream* out)
|
||||
{
|
||||
std::string const validChar = "-";
|
||||
std::string const validNums = "012345";
|
||||
uint32 nums = 0;
|
||||
|
||||
for (char const& c : link)
|
||||
{
|
||||
if (validChar.find(c) == std::string::npos && validNums.find(c) == std::string::npos)
|
||||
{
|
||||
*out << "talent link is invalid. Must be in format 0-0-0";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (validNums.find(c) != std::string::npos)
|
||||
nums++;
|
||||
}
|
||||
|
||||
if (nums == 0)
|
||||
{
|
||||
*out << "talent link is invalid. Needs atleast one number.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 TalentSpec::LeveltoPoints(uint32 level) const
|
||||
{
|
||||
uint32 talentPointsForLevel = level < 10 ? 0 : level - 9;
|
||||
return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT));
|
||||
}
|
||||
|
||||
uint32 TalentSpec::PointstoLevel(uint32 points) const
|
||||
{
|
||||
return uint32(ceil(points / sWorld->getRate(RATE_TALENT))) + 9;
|
||||
}
|
||||
|
||||
TalentSpec::TalentSpec(uint32 classMask)
|
||||
{
|
||||
GetTalents(classMask);
|
||||
}
|
||||
|
||||
TalentSpec::TalentSpec(TalentSpec* base, std::string const link)
|
||||
{
|
||||
talents = base->talents;
|
||||
ReadTalents(link);
|
||||
}
|
||||
|
||||
TalentSpec::TalentSpec(Player* bot)
|
||||
{
|
||||
GetTalents(bot->getClassMask());
|
||||
ReadTalents(bot);
|
||||
}
|
||||
|
||||
TalentSpec::TalentSpec(Player* bot, std::string const link)
|
||||
{
|
||||
GetTalents(bot->getClassMask());
|
||||
ReadTalents(link);
|
||||
}
|
||||
|
||||
//Check the talentspec for errors.
|
||||
bool TalentSpec::CheckTalents(uint32 level, std::ostringstream* out)
|
||||
{
|
||||
for (auto& entry : talents)
|
||||
{
|
||||
if (entry.rank > entry.maxRank)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]);
|
||||
*out << "spec is not for this class. " << spellInfo->SpellName[0] << " has " << (entry.rank - entry.maxRank) << " points above max rank.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.rank > 0 && entry.talentInfo->DependsOn)
|
||||
{
|
||||
if (sTalentStore.LookupEntry(entry.talentInfo->DependsOn))
|
||||
{
|
||||
bool found = false;
|
||||
SpellInfo const* spellInfodep = nullptr;
|
||||
|
||||
for (auto& dep : talents)
|
||||
if (dep.talentInfo->TalentID == entry.talentInfo->DependsOn)
|
||||
{
|
||||
spellInfodep = sSpellMgr->GetSpellInfo(dep.talentInfo->RankID[0]);
|
||||
if (dep.rank >= entry.talentInfo->DependsOnRank)
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]);
|
||||
*out << "spec is invalid. Talent:" << spellInfo->SpellName[0] << " needs: " << spellInfodep->SpellName[0] << " at rank: " << entry.talentInfo->DependsOnRank;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < 3; i++)
|
||||
{
|
||||
std::vector<TalentListEntry> talentTree = GetTalentTree(i);
|
||||
uint32 points = 0;
|
||||
|
||||
for (auto& entry : talentTree)
|
||||
{
|
||||
if (entry.rank > 0 && entry.talentInfo->Row * 5 > points)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]);
|
||||
*out << "spec is is invalid. Talent " << spellInfo->SpellName[0] << " is selected with only " << points << " in row below it.";
|
||||
return false;
|
||||
}
|
||||
|
||||
points += entry.rank;
|
||||
}
|
||||
}
|
||||
|
||||
if (points > LeveltoPoints(level))
|
||||
{
|
||||
*out << "spec is for a higher level. (" << PointstoLevel(points) << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Set the talents for the bots to the current spec.
|
||||
void TalentSpec::ApplyTalents(Player* bot, std::ostringstream* out)
|
||||
{
|
||||
for (auto& entry : talents)
|
||||
for (uint8 rank = 0; rank < MAX_TALENT_RANK; ++rank)
|
||||
{
|
||||
uint32 spellId = entry.talentInfo->RankID[rank];
|
||||
if (!spellId)
|
||||
continue;
|
||||
|
||||
if (bot->HasSpell(spellId) && entry.rank - 1 != rank)
|
||||
{
|
||||
bot->removeSpell(spellId, false, false);
|
||||
}
|
||||
else if (!bot->HasSpell(spellId) && entry.rank - 1 == rank)
|
||||
{
|
||||
bot->learnSpell(spellId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Returns a base talentlist for a class.
|
||||
void TalentSpec::GetTalents(uint32 classMask)
|
||||
{
|
||||
TalentListEntry entry;
|
||||
|
||||
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
|
||||
{
|
||||
TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
|
||||
if (!talentInfo)
|
||||
continue;
|
||||
|
||||
TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
|
||||
if (!talentTabInfo)
|
||||
continue;
|
||||
|
||||
if ((classMask & talentTabInfo->ClassMask) == 0)
|
||||
continue;
|
||||
|
||||
entry.entry = i;
|
||||
entry.rank = 0;
|
||||
entry.talentInfo = talentInfo;
|
||||
entry.talentTabInfo = talentTabInfo;
|
||||
|
||||
for (uint8 rank = 0; rank < MAX_TALENT_RANK; ++rank)
|
||||
{
|
||||
uint32 spellId = talentInfo->RankID[rank];
|
||||
if (!spellId)
|
||||
continue;
|
||||
|
||||
entry.maxRank = rank + 1;
|
||||
}
|
||||
|
||||
talents.push_back(entry);
|
||||
}
|
||||
|
||||
SortTalents(talents, SORT_BY_DEFAULT);
|
||||
}
|
||||
|
||||
//Sorts a talent list by page, row, column.
|
||||
bool sortTalentMap(TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j, uint32* tabSort)
|
||||
{
|
||||
uint32 itab = i.tabPage();
|
||||
uint32 jtab = j.tabPage();
|
||||
if (tabSort[itab] < tabSort[jtab])
|
||||
return true;
|
||||
|
||||
if (tabSort[itab] > tabSort[jtab])
|
||||
return false;
|
||||
|
||||
if (i.talentInfo->Row < j.talentInfo->Row)
|
||||
return true;
|
||||
|
||||
if (i.talentInfo->Row > j.talentInfo->Row)
|
||||
return false;
|
||||
|
||||
if (i.talentInfo->Col < j.talentInfo->Col)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TalentSpec::SortTalents(uint32 sortBy)
|
||||
{
|
||||
SortTalents(talents, sortBy);
|
||||
}
|
||||
|
||||
//Sort the talents.
|
||||
void TalentSpec::SortTalents(std::vector<TalentListEntry>& talents, uint32 sortBy)
|
||||
{
|
||||
switch (sortBy)
|
||||
{
|
||||
case SORT_BY_DEFAULT:
|
||||
{
|
||||
uint32 tabSort[] = { 0, 1, 2 };
|
||||
std::sort(talents.begin(), talents.end(), [&tabSort](TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j)
|
||||
{
|
||||
return sortTalentMap(i, j, tabSort);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case SORT_BY_POINTS_TREE:
|
||||
{
|
||||
uint32 tabSort[] = { GetTalentPoints(talents, 0) * 100 - urand(0, 99), GetTalentPoints(talents, 1) * 100 - urand(0, 99), GetTalentPoints(talents, 2) * 100 - urand(0, 99) };
|
||||
std::sort(talents.begin(), talents.end(), [&tabSort](TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j)
|
||||
{
|
||||
return sortTalentMap(i, j, tabSort);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Set the talent ranks to the current rank of the player.
|
||||
void TalentSpec::ReadTalents(Player* bot)
|
||||
{
|
||||
for (auto& entry : talents)
|
||||
for (uint8 rank = 0; rank < MAX_TALENT_RANK; ++rank)
|
||||
{
|
||||
uint32 spellId = entry.talentInfo->RankID[rank];
|
||||
if (!spellId)
|
||||
continue;
|
||||
|
||||
if (bot->HasSpell(spellId))
|
||||
{
|
||||
entry.rank = rank + 1;
|
||||
points += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Set the talent ranks to the ranks of the link.
|
||||
void TalentSpec::ReadTalents(std::string const link)
|
||||
{
|
||||
uint32 rank = 0;
|
||||
uint32 pos = 0;
|
||||
uint32 tab = 0;
|
||||
std::string chr;
|
||||
|
||||
if (link.substr(pos, 1) == "-")
|
||||
{
|
||||
pos++;
|
||||
tab++;
|
||||
}
|
||||
|
||||
if (link.substr(pos, 1) == "-")
|
||||
{
|
||||
pos++;
|
||||
tab++;
|
||||
}
|
||||
|
||||
for (auto& entry : talents)
|
||||
{
|
||||
if (entry.tabPage() == tab)
|
||||
{
|
||||
chr = link.substr(pos, 1);
|
||||
|
||||
if (chr == " " || chr == "#")
|
||||
break;
|
||||
|
||||
entry.rank = stoi(chr);
|
||||
points += entry.rank;
|
||||
|
||||
pos++;
|
||||
if (pos <= link.size() && link.substr(pos, 1) == "-")
|
||||
{
|
||||
pos++;
|
||||
tab++;
|
||||
}
|
||||
|
||||
if (pos <= link.size() && link.substr(pos, 1) == "-")
|
||||
{
|
||||
pos++;
|
||||
tab++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos > link.size() - 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Returns only a specific tree from a talent list.
|
||||
std::vector<TalentSpec::TalentListEntry> TalentSpec::GetTalentTree(uint32 tabpage)
|
||||
{
|
||||
std::vector<TalentListEntry> retList;
|
||||
|
||||
for (auto& entry : talents)
|
||||
if (entry.tabPage() == tabpage)
|
||||
retList.push_back(entry);
|
||||
|
||||
return std::move(retList);
|
||||
}
|
||||
|
||||
uint32 TalentSpec::GetTalentPoints(int32 tabpage)
|
||||
{
|
||||
return GetTalentPoints(talents, tabpage);
|
||||
};
|
||||
|
||||
//Counts the point in a talent list.
|
||||
uint32 TalentSpec::GetTalentPoints(std::vector<TalentListEntry>& talents, int32 tabpage)
|
||||
{
|
||||
if (tabpage == -1)
|
||||
return points;
|
||||
|
||||
uint32 tPoints = 0;
|
||||
for (auto& entry : talents)
|
||||
if (entry.tabPage() == tabpage)
|
||||
tPoints = tPoints + entry.rank;
|
||||
|
||||
return tPoints;
|
||||
}
|
||||
|
||||
//Generates a wow-head link from a talent list.
|
||||
std::string const TalentSpec::GetTalentLink()
|
||||
{
|
||||
std::string link = "";
|
||||
std::string treeLink[3];
|
||||
uint32 points[3];
|
||||
uint32 curPoints = 0;
|
||||
|
||||
for (uint8 i = 0; i < 3; i++)
|
||||
{
|
||||
points[i] = GetTalentPoints(i);
|
||||
|
||||
for (auto& entry : GetTalentTree(i))
|
||||
{
|
||||
curPoints += entry.rank;
|
||||
treeLink[i] += std::to_string(entry.rank);
|
||||
if (curPoints >= points[i])
|
||||
{
|
||||
curPoints = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
link = treeLink[0];
|
||||
|
||||
if (treeLink[1] != "0" || treeLink[2] != "0")
|
||||
link = link + "-" + treeLink[1];
|
||||
|
||||
if (treeLink[2] != "0")
|
||||
link = link + "-" + treeLink[2];
|
||||
|
||||
return std::move(link);
|
||||
}
|
||||
|
||||
uint32 TalentSpec::highestTree()
|
||||
{
|
||||
uint32 p1 = GetTalentPoints(0);
|
||||
uint32 p2 = GetTalentPoints(1);
|
||||
uint32 p3 = GetTalentPoints(2);
|
||||
|
||||
if (p1 > p2 && p1 > p3)
|
||||
return 0;
|
||||
|
||||
if (p2 > p1 && p2 > p3)
|
||||
return 1;
|
||||
|
||||
if (p3 > p1 && p3 > p2)
|
||||
return 2;
|
||||
|
||||
if (p1 > p2 || p1 > p3)
|
||||
return 0;
|
||||
|
||||
if (p2 > p3 || p2 > p1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string const TalentSpec::FormatSpec(Player* bot)
|
||||
{
|
||||
uint8 cls = bot->getClass();
|
||||
|
||||
std::ostringstream out;
|
||||
//out << chathelper:: specs[cls][highestTree()] << " (";
|
||||
|
||||
uint32 c0 = GetTalentPoints(0);
|
||||
uint32 c1 = GetTalentPoints(1);
|
||||
uint32 c2 = GetTalentPoints(2);
|
||||
|
||||
out << (c0 ? "|h|cff00ff00" : "") << c0 << "|h|cffffffff/";
|
||||
out << (c1 ? "|h|cff00ff00" : "") << c1 << "|h|cffffffff/";
|
||||
out << (c2 ? "|h|cff00ff00" : "") << c2 << "|h|cffffffff";
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
//Removes talentpoints to match the level
|
||||
void TalentSpec::CropTalents(uint32 level)
|
||||
{
|
||||
if (points <= LeveltoPoints(level))
|
||||
return;
|
||||
|
||||
SortTalents(talents, SORT_BY_POINTS_TREE);
|
||||
|
||||
uint32 points = 0;
|
||||
for (auto& entry : talents)
|
||||
{
|
||||
if (points + entry.rank > LeveltoPoints(level))
|
||||
entry.rank = std::max(0u, LeveltoPoints(level) - points);
|
||||
|
||||
points += entry.rank;
|
||||
}
|
||||
|
||||
SortTalents(talents, SORT_BY_DEFAULT);
|
||||
}
|
||||
|
||||
//Substracts ranks. Follows the sorting of the newList.
|
||||
std::vector<TalentSpec::TalentListEntry> TalentSpec::SubTalentList(std::vector<TalentListEntry>& oldList, std::vector<TalentListEntry>& newList, uint32 reverse = SUBSTRACT_OLD_NEW)
|
||||
{
|
||||
std::vector<TalentSpec::TalentListEntry> deltaList = newList;
|
||||
|
||||
for (auto& newentry : deltaList)
|
||||
for (auto& oldentry : oldList)
|
||||
if (oldentry.entry == newentry.entry)
|
||||
{
|
||||
if (reverse == ABSOLUTE_DIST)
|
||||
newentry.rank = std::abs(int32(newentry.rank - oldentry.rank));
|
||||
else if (reverse == ADDED_POINTS || reverse == REMOVED_POINTS)
|
||||
newentry.rank = std::max(0u, (newentry.rank - oldentry.rank) * (reverse / 2));
|
||||
else
|
||||
newentry.rank = (newentry.rank - oldentry.rank) * reverse;
|
||||
}
|
||||
|
||||
return deltaList;
|
||||
}
|
||||
|
||||
bool TalentSpec::isEarlierVersionOf(TalentSpec& newSpec)
|
||||
{
|
||||
for (auto& newentry : newSpec.talents)
|
||||
for (auto& oldentry : talents)
|
||||
if (oldentry.entry == newentry.entry)
|
||||
if (oldentry.rank > newentry.rank)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Modifies current talents towards new talents up to a maxium of points.
|
||||
void TalentSpec::ShiftTalents(TalentSpec* currentSpec, uint32 level)
|
||||
{
|
||||
uint32 currentPoints = currentSpec->GetTalentPoints();
|
||||
if (points >= LeveltoPoints(level)) //We have no more points to spend. Better reset and crop
|
||||
{
|
||||
CropTalents(level);
|
||||
return;
|
||||
}
|
||||
|
||||
SortTalents(SORT_BY_POINTS_TREE); //Apply points first to the largest new tree.
|
||||
|
||||
std::vector<TalentSpec::TalentListEntry> deltaList = SubTalentList(currentSpec->talents, talents);
|
||||
|
||||
for (auto& entry : deltaList)
|
||||
{
|
||||
if (entry.rank < 0) //We have to remove talents. Might as well reset and crop the new list.
|
||||
{
|
||||
CropTalents(level);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Start from the current spec.
|
||||
talents = currentSpec->talents;
|
||||
|
||||
for (auto& entry : deltaList)
|
||||
{
|
||||
if (entry.rank + points > LeveltoPoints(level)) //Running out of points. Only apply what we have left.
|
||||
entry.rank = std::max(0, std::abs(int32(LeveltoPoints(level) - points)));
|
||||
|
||||
for (auto& subentry : talents)
|
||||
if (entry.entry == subentry.entry)
|
||||
subentry.rank = subentry.rank + entry.rank;
|
||||
|
||||
points = points + entry.rank;
|
||||
}
|
||||
}
|
||||
103
src/Talentspec.h
Normal file
103
src/Talentspec.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_TALENTSPEC_H
|
||||
#define _PLAYERBOT_TALENTSPEC_H
|
||||
|
||||
#include "Action.h"
|
||||
|
||||
struct TalentEntry;
|
||||
struct TalentTabEntry;
|
||||
|
||||
#define SORT_BY_DEFAULT 0
|
||||
#define SORT_BY_POINTS_TREE 1
|
||||
#define ABSOLUTE_DIST 0
|
||||
#define SUBSTRACT_OLD_NEW 1
|
||||
#define SUBSTRACT_NEW_OLD -1
|
||||
#define ADDED_POINTS 2
|
||||
#define REMOVED_POINTS -2
|
||||
|
||||
class TalentSpec
|
||||
{
|
||||
public:
|
||||
struct TalentListEntry
|
||||
{
|
||||
uint32 entry;
|
||||
uint32 rank;
|
||||
uint32 maxRank;
|
||||
TalentEntry const* talentInfo;
|
||||
TalentTabEntry const* talentTabInfo;
|
||||
uint32 tabPage() const;
|
||||
};
|
||||
|
||||
TalentSpec() { };
|
||||
TalentSpec(uint32 classMask);
|
||||
TalentSpec(TalentSpec* base, std::string const link);
|
||||
TalentSpec(Player* bot);
|
||||
TalentSpec(Player* bot, std::string const link);
|
||||
|
||||
uint32 points = 0;
|
||||
std::vector<TalentListEntry> talents;
|
||||
|
||||
bool CheckTalentLink(std::string const link, std::ostringstream* out);
|
||||
virtual bool CheckTalents(uint32 maxPoints, std::ostringstream* out);
|
||||
void CropTalents(uint32 level);
|
||||
void ShiftTalents(TalentSpec* oldTalents, uint32 level);
|
||||
void ApplyTalents(Player* bot, std::ostringstream* out);
|
||||
|
||||
uint32 GetTalentPoints(std::vector<TalentListEntry>& talents, int32 tabpage = -1);
|
||||
uint32 GetTalentPoints(int32 tabpage = -1);
|
||||
bool isEarlierVersionOf(TalentSpec& newSpec);
|
||||
|
||||
std::string const GetTalentLink();
|
||||
uint32 highestTree();
|
||||
std::string const FormatSpec(Player* bot);
|
||||
|
||||
protected:
|
||||
uint32 LeveltoPoints(uint32 level) const;
|
||||
uint32 PointstoLevel(uint32 points) const;
|
||||
void GetTalents(uint32 classMask);
|
||||
void SortTalents(std::vector<TalentListEntry>& talents, uint32 sortBy);
|
||||
void SortTalents(uint32 sortBy);
|
||||
|
||||
void ReadTalents(Player* bot);
|
||||
void ReadTalents(std::string const link);
|
||||
|
||||
std::vector<TalentListEntry> GetTalentTree(uint32 tabpage);
|
||||
std::vector<TalentListEntry> SubTalentList(std::vector<TalentListEntry>& oldList, std::vector<TalentListEntry>& newList, uint32 reverse);
|
||||
};
|
||||
|
||||
class TalentPath
|
||||
{
|
||||
public:
|
||||
TalentPath(uint32 pathId, std::string const pathName, uint32 pathProbability)
|
||||
{
|
||||
id = pathId;
|
||||
name = pathName;
|
||||
probability = pathProbability;
|
||||
};
|
||||
|
||||
uint32 id = 0;
|
||||
std::string name = "";
|
||||
uint32 probability = 100;
|
||||
std::vector<TalentSpec> talentSpec;
|
||||
};
|
||||
|
||||
class ClassSpecs
|
||||
{
|
||||
public:
|
||||
ClassSpecs() { };
|
||||
ClassSpecs(uint32 specsClassMask)
|
||||
{
|
||||
classMask = specsClassMask;
|
||||
baseSpec = TalentSpec(specsClassMask);
|
||||
}
|
||||
|
||||
uint32 classMask = 0;
|
||||
TalentSpec baseSpec;
|
||||
|
||||
std::vector<TalentPath> talentPath;
|
||||
};
|
||||
|
||||
#endif
|
||||
4343
src/TravelMgr.cpp
Normal file
4343
src/TravelMgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user