mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
Merge remote-tracking branch 'origin/test-staging' into TravelSystem-pr
This commit is contained in:
commit
bd14756b20
@ -651,9 +651,14 @@ AiPlayerbot.BotTaxiGapJitterMs = 100
|
|||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# PROFESSIONS
|
# PROFESSIONS
|
||||||
# Note: Random bots currently do not get professions
|
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Percentage of randombots in each class bucket that receive a class-matching
|
||||||
|
# weighted profession combination. The remaining randombots use the weighted
|
||||||
|
# random sane-pair profession pool.
|
||||||
|
# Default: 30
|
||||||
|
AiPlayerbot.ClassMatchingProfessionChance = 30
|
||||||
|
|
||||||
# Automatically adds the 'master fishing' strategy to bots that have the fishing skill when the bots master fishes.
|
# Automatically adds the 'master fishing' strategy to bots that have the fishing skill when the bots master fishes.
|
||||||
# Default: 1 (Enabled)
|
# Default: 1 (Enabled)
|
||||||
AiPlayerbot.EnableFishingWithMaster = 1
|
AiPlayerbot.EnableFishingWithMaster = 1
|
||||||
@ -801,6 +806,27 @@ AiPlayerbot.RandomGearQualityLimit = 3
|
|||||||
# Default: 0 (no limit)
|
# Default: 0 (no limit)
|
||||||
AiPlayerbot.RandomGearScoreLimit = 0
|
AiPlayerbot.RandomGearScoreLimit = 0
|
||||||
|
|
||||||
|
# Prefer armor of the class's ideal type: apply 3x score multiplier to class-appropriate armor.
|
||||||
|
# When enabled, Warriors strongly prefer plate, Shamans prefer mail, etc.
|
||||||
|
# A truly superior item can still win (no hard filtering), but same-quality
|
||||||
|
# armor of the preferred type will score 3x higher and be equipped instead.
|
||||||
|
#
|
||||||
|
# ARMOR TYPE PREFERENCES:
|
||||||
|
# Plate: Warriors, Paladins, Death Knights
|
||||||
|
# Mail: Hunters, Shamans
|
||||||
|
# Leather: Rogues, Druids
|
||||||
|
# Cloth: Priests, Mages, Warlocks
|
||||||
|
#
|
||||||
|
# Default: 0 (disabled)
|
||||||
|
AiPlayerbot.PreferClassArmorType = 0
|
||||||
|
|
||||||
|
|
||||||
|
# When enabled, bots prefer spec-appropriate weapons based on speed and weapon type during autogear.
|
||||||
|
# Examples: Arms Warriors favor slow 2H axes/polearms (Axe Specialization), Combat Rogues
|
||||||
|
# favor a slow MH with a fast OH, and Enhancement Shamans favor synchronized slow 1H weapons.
|
||||||
|
# Default: 0 (disabled)
|
||||||
|
AiPlayerbot.PreferredSpecWeapons = 0
|
||||||
|
|
||||||
# If disabled, random bots can only upgrade equipment through looting and quests
|
# If disabled, random bots can only upgrade equipment through looting and quests
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.IncrementalGearInit = 1
|
AiPlayerbot.IncrementalGearInit = 1
|
||||||
@ -1325,7 +1351,7 @@ AiPlayerbot.DeleteRandomBotArenaTeams = 0
|
|||||||
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,4395,3703,4298,3951"
|
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,4395,3703,4298,3951"
|
||||||
|
|
||||||
# PvP Restricted Areas (bots don't pvp)
|
# PvP Restricted Areas (bots don't pvp)
|
||||||
AiPlayerbot.PvpProhibitedAreaIds = "976,35,392,2268,4161,4010,4317,4312,3649,3887,3958,3724,4080,3938,3754,3786,3973"
|
AiPlayerbot.PvpProhibitedAreaIds = "976,35,392,2268,4161,4010,4317,4312,3649,3887,3958,3724,4080,3938,3754,3786,3973,4085,4086,4087,4088"
|
||||||
|
|
||||||
# Improve reaction speeds in battlegrounds and arenas (may cause lag)
|
# Improve reaction speeds in battlegrounds and arenas (may cause lag)
|
||||||
AiPlayerbot.FastReactInBG = 1
|
AiPlayerbot.FastReactInBG = 1
|
||||||
@ -1803,10 +1829,10 @@ AiPlayerbot.PremadeSpecLink.11.6.80 = 05320021--230033312031500531353013251
|
|||||||
# Requires sending the command "nc +worldbuff" in chat to a bot (or a group of bots) to enable
|
# Requires sending the command "nc +worldbuff" in chat to a bot (or a group of bots) to enable
|
||||||
# Each entry in the matrix should be formatted as follows: Entry:FactionID,ClassID,SpecID,MinimumLevel,MaximumLevel:SpellID1,SpellID2,etc.;
|
# Each entry in the matrix should be formatted as follows: Entry:FactionID,ClassID,SpecID,MinimumLevel,MaximumLevel:SpellID1,SpellID2,etc.;
|
||||||
# FactionID may be set to 0 for the entry to apply buffs to bots of either faction
|
# FactionID may be set to 0 for the entry to apply buffs to bots of either faction
|
||||||
# The default entries create a cross-faction list of level 80 buffs for each implemented pve spec from the "Premade Specs" section
|
# The default entries create a cross-faction level 60-69 Vanilla buffs, level 70-79 TBC buffs, and level 80 buffs for each implemented pve spec from the "Premade Specs" section
|
||||||
# The default entries may be deleted or modified, and new custom entries may be added
|
# The default entries may be deleted or modified, and new custom entries may be added
|
||||||
|
|
||||||
AiPlayerbot.WorldBuffMatrix = # WARRIOR ARMS 1:0,1,0,80,80:53760,57358; # WARRIOR FURY 2:0,1,1,80,80:53760,57358; # WARRIOR PROTECTION 3:0,1,2,80,80:53758,57356; # PALADIN HOLY 4:0,2,0,80,80:53749,57332,60347; # PALADIN PROTECTION 5:0,2,1,80,80:53758,57356; # PALADIN RETRIBUTION 6:0,2,2,80,80:53760,57371; # HUNTER BEAST 7:0,3,0,80,80:53760,57325; # HUNTER MARKSMANSHIP 8:0,3,1,80,80:53760,57358; # HUNTER SURVIVAL 9:0,3,2,80,80:53760,57367; # ROGUE ASSASSINATION 10:0,4,0,80,80:53760,57325; # ROGUE COMBAT 11:0,4,1,80,80:53760,57358; # ROGUE SUBTLETY 12:0,4,2,80,80:53760,57367; # PRIEST DISCIPLINE 13:0,5,0,80,80:53755,57327; # PRIEST HOLY 14:0,5,1,80,80:53755,57327; # PRIEST SHADOW 15:0,5,2,80,80:53755,57327; # DEATH KNIGHT BLOOD 16:0,6,0,80,80:53758,57356; # DEATH KNIGHT FROST 17:0,6,1,80,80:53760,57358; # DEATH KNIGHT UNHOLY 18:0,6,2,80,80:53760,57358; # DEATH KNIGHT BLOOD DPS 19:0,6,3,80,80:53760,57371; # SHAMAN ELEMENTAL 20:0,7,0,80,80:53755,57327; # SHAMAN ENHANCEMENT 21:0,7,1,80,80:53760,57325; # SHAMAN RESTORATION 22:0,7,2,80,80:53755,57327; # MAGE ARCANE 23:0,8,0,80,80:53755,57327; # MAGE FIRE 24:0,8,1,80,80:53755,57327; # MAGE FROST 25:0,8,2,80,80:53755,57327; # WARLOCK AFFLICTION 26:0,9,0,80,80:53755,57327; # WARLOCK DEMONOLOGY 27:0,9,1,80,80:53755,57327; # WARLOCK DESTRUCTION 28:0,9,2,80,80:53755,57327; # DRUID BALANCE 29:0,11,0,80,80:53755,57327; # DRUID FERAL BEAR 30:0,11,1,80,80:53749,53763,57367; # DRUID RESTORATION 31:0,11,2,80,80:54212,57334; # DRUID FERAL CAT 32:0,11,3,80,80:53760,57358
|
AiPlayerbot.WorldBuffMatrix = # WARRIOR ARMS 1:0,1,0,80,80:53760,57358; # WARRIOR FURY 2:0,1,1,80,80:53760,57358; # WARRIOR PROTECTION 3:0,1,2,80,80:53758,57356; # PALADIN HOLY 4:0,2,0,80,80:53749,57332,60347; # PALADIN PROTECTION 5:0,2,1,80,80:53758,57356; # PALADIN RETRIBUTION 6:0,2,2,80,80:53760,57371; # HUNTER BEAST 7:0,3,0,80,80:53760,57325; # HUNTER MARKSMANSHIP 8:0,3,1,80,80:53760,57358; # HUNTER SURVIVAL 9:0,3,2,80,80:53760,57367; # ROGUE ASSASSINATION 10:0,4,0,80,80:53760,57325; # ROGUE COMBAT 11:0,4,1,80,80:53760,57358; # ROGUE SUBTLETY 12:0,4,2,80,80:53760,57367; # PRIEST DISCIPLINE 13:0,5,0,80,80:53755,57327; # PRIEST HOLY 14:0,5,1,80,80:53755,57327; # PRIEST SHADOW 15:0,5,2,80,80:53755,57327; # DEATH KNIGHT BLOOD 16:0,6,0,80,80:53758,57356; # DEATH KNIGHT FROST 17:0,6,1,80,80:53760,57358; # DEATH KNIGHT UNHOLY 18:0,6,2,80,80:53760,57358; # DEATH KNIGHT BLOOD DPS 19:0,6,3,80,80:53760,57371; # SHAMAN ELEMENTAL 20:0,7,0,80,80:53755,57327; # SHAMAN ENHANCEMENT 21:0,7,1,80,80:53760,57325; # SHAMAN RESTORATION 22:0,7,2,80,80:53755,57327; # MAGE ARCANE 23:0,8,0,80,80:53755,57327; # MAGE FIRE 24:0,8,1,80,80:53755,57327; # MAGE FROST 25:0,8,2,80,80:53755,57327; # WARLOCK AFFLICTION 26:0,9,0,80,80:53755,57327; # WARLOCK DEMONOLOGY 27:0,9,1,80,80:53755,57327; # WARLOCK DESTRUCTION 28:0,9,2,80,80:53755,57327; # DRUID BALANCE 29:0,11,0,80,80:53755,57327; # DRUID FERAL BEAR 30:0,11,1,80,80:53749,53763,57367; # DRUID RESTORATION 31:0,11,2,80,80:54212,57334; # DRUID FERAL CAT 32:0,11,3,80,80:53760,57358; # WARRIOR ARMS TBC 33:0,1,0,70,79:28520,33256; # WARRIOR FURY TBC 34:0,1,1,70,79:28520,33256; # WARRIOR PROTECTION TBC 35:0,1,2,70,79:28518,33257; # PALADIN HOLY TBC 36:0,2,0,70,79:28491,39627,33263; # PALADIN PROTECTION TBC 37:0,2,1,70,79:28518,33257; # PALADIN RETRIBUTION TBC 38:0,2,2,70,79:28520,33256; # HUNTER BEAST TBC 39:0,3,0,70,79:28520,33261; # HUNTER MARKSMANSHIP TBC 40:0,3,1,70,79:28520,33261; # HUNTER SURVIVAL TBC 41:0,3,2,70,79:28520,33261; # ROGUE ASSASSINATION TBC 42:0,4,0,70,79:28520,33261; # ROGUE COMBAT TBC 43:0,4,1,70,79:28520,33261; # ROGUE SUBTLETY TBC 44:0,4,2,70,79:28520,33261; # PRIEST DISCIPLINE TBC 45:0,5,0,70,79:28491,39627,33263; # PRIEST HOLY TBC 46:0,5,1,70,79:28491,39627,33263; # PRIEST SHADOW TBC 47:0,5,2,70,79:28540,33263; # SHAMAN ELEMENTAL TBC 48:0,7,0,70,79:28521,33263; # SHAMAN ENHANCEMENT TBC 49:0,7,1,70,79:28520,33261; # SHAMAN RESTORATION TBC 50:0,7,2,70,79:28491,39627,33263; # MAGE ARCANE TBC 51:0,8,0,70,79:28521,33263; # MAGE FIRE TBC 52:0,8,1,70,79:28540,33263; # MAGE FROST TBC 53:0,8,2,70,79:28540,33263; # WARLOCK AFFLICTION TBC 54:0,9,0,70,79:28540,33263; # WARLOCK DEMONOLOGY TBC 55:0,9,1,70,79:28540,33263; # WARLOCK DESTRUCTION TBC 56:0,9,2,70,79:28540,33263; # DRUID BALANCE TBC 57:0,11,0,70,79:28521,33263; # DRUID FERAL BEAR TBC 58:0,11,1,70,79:28518,33257; # DRUID RESTORATION TBC 59:0,11,2,70,79:28491,39627,33263; # DRUID FERAL CAT TBC 60:0,11,3,70,79:28520,33261; # WARRIOR ARMS VANILLA 61:0,1,0,60,69:17538,24799; # WARRIOR FURY VANILLA 62:0,1,1,60,69:17538,24799; # WARRIOR PROTECTION VANILLA 63:0,1,2,60,69:17626,25661; # PALADIN HOLY VANILLA 64:0,2,0,60,69:17627,18194; # PALADIN PROTECTION VANILLA 65:0,2,1,60,69:17626,25661; # PALADIN RETRIBUTION VANILLA 66:0,2,2,60,69:17628,24799; # HUNTER BEAST VANILLA 67:0,3,0,60,69:17538,18192; # HUNTER MARKSMANSHIP VANILLA 68:0,3,1,60,69:17538,18192; # HUNTER SURVIVAL VANILLA 69:0,3,2,60,69:17538,18192; # ROGUE ASSASSINATION VANILLA 70:0,4,0,60,69:17538,18192; # ROGUE COMBAT VANILLA 71:0,4,1,60,69:17538,18192; # ROGUE SUBTLETY VANILLA 72:0,4,2,60,69:17538,18192; # PRIEST DISCIPLINE VANILLA 73:0,5,0,60,69:17628,18194; # PRIEST HOLY VANILLA 74:0,5,1,60,69:17627,18194; # PRIEST SHADOW VANILLA 75:0,5,2,60,69:17628,18194; # SHAMAN ELEMENTAL VANILLA 76:0,7,0,60,69:17628,18194; # SHAMAN ENHANCEMENT VANILLA 77:0,7,1,60,69:17538,24799; # SHAMAN RESTORATION VANILLA 78:0,7,2,60,69:17627,18194; # MAGE ARCANE VANILLA 79:0,8,0,60,69:17628,18194; # MAGE FIRE VANILLA 80:0,8,1,60,69:17628,18194; # MAGE FROST VANILLA 81:0,8,2,60,69:17628,18194; # WARLOCK AFFLICTION VANILLA 82:0,9,0,60,69:17628,25661; # WARLOCK DEMONOLOGY VANILLA 83:0,9,1,60,69:17628,25661; # WARLOCK DESTRUCTION VANILLA 84:0,9,2,60,69:17628,25661; # DRUID BALANCE VANILLA 85:0,11,0,60,69:17628,18194; # DRUID FERAL BEAR VANILLA 86:0,11,1,60,69:17626,25661; # DRUID RESTORATION VANILLA 87:0,11,2,60,69:17627,18194; # DRUID FERAL CAT VANILLA 88:0,11,3,60,69:17538,24799
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1837,12 +1863,24 @@ AiPlayerbot.WorldBuffMatrix = # WARRIOR ARMS 1:0,1,0,80,80:53760,57358; # WARRIO
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# arms pve
|
||||||
AiPlayerbot.RandomClassSpecProb.1.0 = 20
|
AiPlayerbot.RandomClassSpecProb.1.0 = 20
|
||||||
AiPlayerbot.RandomClassSpecIndex.1.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.1.0 = 0
|
||||||
|
# fury pve
|
||||||
AiPlayerbot.RandomClassSpecProb.1.1 = 40
|
AiPlayerbot.RandomClassSpecProb.1.1 = 40
|
||||||
AiPlayerbot.RandomClassSpecIndex.1.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.1.1 = 1
|
||||||
|
# prot pve
|
||||||
AiPlayerbot.RandomClassSpecProb.1.2 = 40
|
AiPlayerbot.RandomClassSpecProb.1.2 = 40
|
||||||
AiPlayerbot.RandomClassSpecIndex.1.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.1.2 = 2
|
||||||
|
# arms pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.1.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.1.3 = 3
|
||||||
|
# fury pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.1.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.1.4 = 4
|
||||||
|
# prot pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.1.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.1.5 = 5
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1854,12 +1892,24 @@ AiPlayerbot.RandomClassSpecIndex.1.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# holy pve
|
||||||
AiPlayerbot.RandomClassSpecProb.2.0 = 30
|
AiPlayerbot.RandomClassSpecProb.2.0 = 30
|
||||||
AiPlayerbot.RandomClassSpecIndex.2.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.2.0 = 0
|
||||||
|
# prot pve
|
||||||
AiPlayerbot.RandomClassSpecProb.2.1 = 40
|
AiPlayerbot.RandomClassSpecProb.2.1 = 40
|
||||||
AiPlayerbot.RandomClassSpecIndex.2.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.2.1 = 1
|
||||||
|
# ret pve
|
||||||
AiPlayerbot.RandomClassSpecProb.2.2 = 30
|
AiPlayerbot.RandomClassSpecProb.2.2 = 30
|
||||||
AiPlayerbot.RandomClassSpecIndex.2.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.2.2 = 2
|
||||||
|
# holy pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.2.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.2.3 = 3
|
||||||
|
# prot pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.2.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.2.4 = 4
|
||||||
|
# ret pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.2.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.2.5 = 5
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1871,12 +1921,24 @@ AiPlayerbot.RandomClassSpecIndex.2.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# bm pve
|
||||||
AiPlayerbot.RandomClassSpecProb.3.0 = 33
|
AiPlayerbot.RandomClassSpecProb.3.0 = 33
|
||||||
AiPlayerbot.RandomClassSpecIndex.3.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.3.0 = 0
|
||||||
|
# mm pve
|
||||||
AiPlayerbot.RandomClassSpecProb.3.1 = 33
|
AiPlayerbot.RandomClassSpecProb.3.1 = 33
|
||||||
AiPlayerbot.RandomClassSpecIndex.3.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.3.1 = 1
|
||||||
|
# surv pve
|
||||||
AiPlayerbot.RandomClassSpecProb.3.2 = 33
|
AiPlayerbot.RandomClassSpecProb.3.2 = 33
|
||||||
AiPlayerbot.RandomClassSpecIndex.3.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.3.2 = 2
|
||||||
|
# bm pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.3.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.3.3 = 3
|
||||||
|
# mm pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.3.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.3.4 = 4
|
||||||
|
# surv pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.3.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.3.5 = 5
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1888,12 +1950,24 @@ AiPlayerbot.RandomClassSpecIndex.3.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# as pve
|
||||||
AiPlayerbot.RandomClassSpecProb.4.0 = 45
|
AiPlayerbot.RandomClassSpecProb.4.0 = 45
|
||||||
AiPlayerbot.RandomClassSpecIndex.4.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.4.0 = 0
|
||||||
|
# combat pve
|
||||||
AiPlayerbot.RandomClassSpecProb.4.1 = 45
|
AiPlayerbot.RandomClassSpecProb.4.1 = 45
|
||||||
AiPlayerbot.RandomClassSpecIndex.4.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.4.1 = 1
|
||||||
|
# subtlety pve
|
||||||
AiPlayerbot.RandomClassSpecProb.4.2 = 10
|
AiPlayerbot.RandomClassSpecProb.4.2 = 10
|
||||||
AiPlayerbot.RandomClassSpecIndex.4.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.4.2 = 2
|
||||||
|
# as pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.4.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.4.3 = 3
|
||||||
|
# combat pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.4.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.4.4 = 4
|
||||||
|
# subtlety pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.4.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.4.5 = 5
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1905,12 +1979,24 @@ AiPlayerbot.RandomClassSpecIndex.4.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# disc pve
|
||||||
AiPlayerbot.RandomClassSpecProb.5.0 = 40
|
AiPlayerbot.RandomClassSpecProb.5.0 = 40
|
||||||
AiPlayerbot.RandomClassSpecIndex.5.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.5.0 = 0
|
||||||
|
# holy pve
|
||||||
AiPlayerbot.RandomClassSpecProb.5.1 = 35
|
AiPlayerbot.RandomClassSpecProb.5.1 = 35
|
||||||
AiPlayerbot.RandomClassSpecIndex.5.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.5.1 = 1
|
||||||
|
# shadow pve
|
||||||
AiPlayerbot.RandomClassSpecProb.5.2 = 25
|
AiPlayerbot.RandomClassSpecProb.5.2 = 25
|
||||||
AiPlayerbot.RandomClassSpecIndex.5.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.5.2 = 2
|
||||||
|
# disc pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.5.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.5.3 = 3
|
||||||
|
# holy pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.5.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.5.4 = 4
|
||||||
|
# shadow pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.5.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.5.5 = 5
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1922,12 +2008,27 @@ AiPlayerbot.RandomClassSpecIndex.5.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# blood pve
|
||||||
AiPlayerbot.RandomClassSpecProb.6.0 = 30
|
AiPlayerbot.RandomClassSpecProb.6.0 = 30
|
||||||
AiPlayerbot.RandomClassSpecIndex.6.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.6.0 = 0
|
||||||
|
# frost pve
|
||||||
AiPlayerbot.RandomClassSpecProb.6.1 = 40
|
AiPlayerbot.RandomClassSpecProb.6.1 = 40
|
||||||
AiPlayerbot.RandomClassSpecIndex.6.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.6.1 = 1
|
||||||
|
# unholy pve
|
||||||
AiPlayerbot.RandomClassSpecProb.6.2 = 30
|
AiPlayerbot.RandomClassSpecProb.6.2 = 30
|
||||||
AiPlayerbot.RandomClassSpecIndex.6.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.6.2 = 2
|
||||||
|
# double aura blood pve
|
||||||
|
AiPlayerbot.RandomClassSpecProb.6.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.6.3 = 3
|
||||||
|
# blood pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.6.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.6.4 = 4
|
||||||
|
# frost pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.6.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.6.5 = 5
|
||||||
|
# unholy pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.6.6 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.6.6 = 6
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1939,12 +2040,24 @@ AiPlayerbot.RandomClassSpecIndex.6.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# ele pve
|
||||||
AiPlayerbot.RandomClassSpecProb.7.0 = 33
|
AiPlayerbot.RandomClassSpecProb.7.0 = 33
|
||||||
AiPlayerbot.RandomClassSpecIndex.7.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.7.0 = 0
|
||||||
|
# enh pve
|
||||||
AiPlayerbot.RandomClassSpecProb.7.1 = 33
|
AiPlayerbot.RandomClassSpecProb.7.1 = 33
|
||||||
AiPlayerbot.RandomClassSpecIndex.7.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.7.1 = 1
|
||||||
|
# resto pve
|
||||||
AiPlayerbot.RandomClassSpecProb.7.2 = 33
|
AiPlayerbot.RandomClassSpecProb.7.2 = 33
|
||||||
AiPlayerbot.RandomClassSpecIndex.7.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.7.2 = 2
|
||||||
|
# ele pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.7.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.7.3 = 3
|
||||||
|
# enh pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.7.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.7.4 = 4
|
||||||
|
# resto pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.7.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.7.5 = 5
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1956,12 +2069,27 @@ AiPlayerbot.RandomClassSpecIndex.7.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# arcane pve
|
||||||
AiPlayerbot.RandomClassSpecProb.8.0 = 30
|
AiPlayerbot.RandomClassSpecProb.8.0 = 30
|
||||||
AiPlayerbot.RandomClassSpecIndex.8.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.8.0 = 0
|
||||||
|
# fire pve
|
||||||
AiPlayerbot.RandomClassSpecProb.8.1 = 30
|
AiPlayerbot.RandomClassSpecProb.8.1 = 30
|
||||||
AiPlayerbot.RandomClassSpecIndex.8.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.8.1 = 1
|
||||||
|
# frost pve
|
||||||
AiPlayerbot.RandomClassSpecProb.8.2 = 40
|
AiPlayerbot.RandomClassSpecProb.8.2 = 40
|
||||||
AiPlayerbot.RandomClassSpecIndex.8.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.8.2 = 2
|
||||||
|
# frostfire pve
|
||||||
|
AiPlayerbot.RandomClassSpecProb.8.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.8.3 = 3
|
||||||
|
# arcane pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.8.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.8.4 = 4
|
||||||
|
# fire pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.8.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.8.5 = 5
|
||||||
|
# frost pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.8.6 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.8.6 = 6
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1973,12 +2101,24 @@ AiPlayerbot.RandomClassSpecIndex.8.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# affli pve
|
||||||
AiPlayerbot.RandomClassSpecProb.9.0 = 33
|
AiPlayerbot.RandomClassSpecProb.9.0 = 33
|
||||||
AiPlayerbot.RandomClassSpecIndex.9.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.9.0 = 0
|
||||||
|
# demo pve
|
||||||
AiPlayerbot.RandomClassSpecProb.9.1 = 34
|
AiPlayerbot.RandomClassSpecProb.9.1 = 34
|
||||||
AiPlayerbot.RandomClassSpecIndex.9.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.9.1 = 1
|
||||||
|
# destro pve
|
||||||
AiPlayerbot.RandomClassSpecProb.9.2 = 33
|
AiPlayerbot.RandomClassSpecProb.9.2 = 33
|
||||||
AiPlayerbot.RandomClassSpecIndex.9.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.9.2 = 2
|
||||||
|
# affli pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.9.3 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.9.3 = 3
|
||||||
|
# demo pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.9.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.9.4 = 4
|
||||||
|
# destro pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.9.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.9.5 = 5
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -1990,14 +2130,27 @@ AiPlayerbot.RandomClassSpecIndex.9.2 = 2
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# balance pve
|
||||||
AiPlayerbot.RandomClassSpecProb.11.0 = 20
|
AiPlayerbot.RandomClassSpecProb.11.0 = 20
|
||||||
AiPlayerbot.RandomClassSpecIndex.11.0 = 0
|
AiPlayerbot.RandomClassSpecIndex.11.0 = 0
|
||||||
|
# bear pve
|
||||||
AiPlayerbot.RandomClassSpecProb.11.1 = 25
|
AiPlayerbot.RandomClassSpecProb.11.1 = 25
|
||||||
AiPlayerbot.RandomClassSpecIndex.11.1 = 1
|
AiPlayerbot.RandomClassSpecIndex.11.1 = 1
|
||||||
|
# resto pve
|
||||||
AiPlayerbot.RandomClassSpecProb.11.2 = 35
|
AiPlayerbot.RandomClassSpecProb.11.2 = 35
|
||||||
AiPlayerbot.RandomClassSpecIndex.11.2 = 2
|
AiPlayerbot.RandomClassSpecIndex.11.2 = 2
|
||||||
|
# cat pve
|
||||||
AiPlayerbot.RandomClassSpecProb.11.3 = 20
|
AiPlayerbot.RandomClassSpecProb.11.3 = 20
|
||||||
AiPlayerbot.RandomClassSpecIndex.11.3 = 3
|
AiPlayerbot.RandomClassSpecIndex.11.3 = 3
|
||||||
|
# balance pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.11.4 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.11.4 = 4
|
||||||
|
# cat pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.11.5 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.11.5 = 5
|
||||||
|
# resto pvp
|
||||||
|
AiPlayerbot.RandomClassSpecProb.11.6 = 0
|
||||||
|
AiPlayerbot.RandomClassSpecIndex.11.6 = 6
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|||||||
@ -0,0 +1,102 @@
|
|||||||
|
-- #########################################################
|
||||||
|
-- Playerbots - Add pull command texts
|
||||||
|
-- Localized for all WotLK locales (koKR, frFR, deDE, zhCN,
|
||||||
|
-- zhTW, esES, esMX, ruRU)
|
||||||
|
-- #########################################################
|
||||||
|
|
||||||
|
DELETE FROM ai_playerbot_texts WHERE name IN (
|
||||||
|
'pull_no_target_error',
|
||||||
|
'pull_target_too_far_error',
|
||||||
|
'pull_invalid_target_error',
|
||||||
|
'pull_action_unavailable_error'
|
||||||
|
);
|
||||||
|
DELETE FROM ai_playerbot_texts_chance WHERE name IN (
|
||||||
|
'pull_no_target_error',
|
||||||
|
'pull_target_too_far_error',
|
||||||
|
'pull_invalid_target_error',
|
||||||
|
'pull_action_unavailable_error'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- pull_no_target_error
|
||||||
|
INSERT INTO `ai_playerbot_texts`
|
||||||
|
(`id`, `name`, `text`, `say_type`, `reply_type`,
|
||||||
|
`text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`,
|
||||||
|
`text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`)
|
||||||
|
VALUES (
|
||||||
|
1755,
|
||||||
|
'pull_no_target_error',
|
||||||
|
'You have no target',
|
||||||
|
0, 0,
|
||||||
|
'대상이 없습니다',
|
||||||
|
'Vous n''avez pas de cible',
|
||||||
|
'Du hast kein Ziel',
|
||||||
|
'你没有目标',
|
||||||
|
'你沒有目標',
|
||||||
|
'No tienes objetivo',
|
||||||
|
'No tienes objetivo',
|
||||||
|
'У вас нет цели');
|
||||||
|
|
||||||
|
INSERT INTO ai_playerbot_texts_chance (name, probability) VALUES ('pull_no_target_error', 100);
|
||||||
|
|
||||||
|
-- pull_target_too_far_error
|
||||||
|
INSERT INTO `ai_playerbot_texts`
|
||||||
|
(`id`, `name`, `text`, `say_type`, `reply_type`,
|
||||||
|
`text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`,
|
||||||
|
`text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`)
|
||||||
|
VALUES (
|
||||||
|
1756,
|
||||||
|
'pull_target_too_far_error',
|
||||||
|
'The target is too far away',
|
||||||
|
0, 0,
|
||||||
|
'대상이 너무 멀리 있습니다',
|
||||||
|
'La cible est trop loin',
|
||||||
|
'Das Ziel ist zu weit entfernt',
|
||||||
|
'目标太远了',
|
||||||
|
'目標太遠了',
|
||||||
|
'El objetivo está demasiado lejos',
|
||||||
|
'El objetivo está demasiado lejos',
|
||||||
|
'Цель слишком далеко');
|
||||||
|
|
||||||
|
INSERT INTO ai_playerbot_texts_chance (name, probability) VALUES ('pull_target_too_far_error', 100);
|
||||||
|
|
||||||
|
-- pull_invalid_target_error
|
||||||
|
INSERT INTO `ai_playerbot_texts`
|
||||||
|
(`id`, `name`, `text`, `say_type`, `reply_type`,
|
||||||
|
`text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`,
|
||||||
|
`text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`)
|
||||||
|
VALUES (
|
||||||
|
1757,
|
||||||
|
'pull_invalid_target_error',
|
||||||
|
'The target can''t be pulled',
|
||||||
|
0, 0,
|
||||||
|
'해당 대상은 풀링할 수 없습니다',
|
||||||
|
'La cible ne peut pas être attirée',
|
||||||
|
'Das Ziel kann nicht gepullt werden',
|
||||||
|
'该目标无法被拉怪',
|
||||||
|
'該目標無法被拉怪',
|
||||||
|
'No se puede hacer pull al objetivo',
|
||||||
|
'No se puede hacer pull al objetivo',
|
||||||
|
'Эту цель нельзя пуллить');
|
||||||
|
|
||||||
|
INSERT INTO ai_playerbot_texts_chance (name, probability) VALUES ('pull_invalid_target_error', 100);
|
||||||
|
|
||||||
|
-- pull_action_unavailable_error: %action_name is replaced with the configured pull action
|
||||||
|
INSERT INTO `ai_playerbot_texts`
|
||||||
|
(`id`, `name`, `text`, `say_type`, `reply_type`,
|
||||||
|
`text_loc1`, `text_loc2`, `text_loc3`, `text_loc4`,
|
||||||
|
`text_loc5`, `text_loc6`, `text_loc7`, `text_loc8`)
|
||||||
|
VALUES (
|
||||||
|
1758,
|
||||||
|
'pull_action_unavailable_error',
|
||||||
|
'Can''t perform pull action ''%action_name''',
|
||||||
|
0, 0,
|
||||||
|
'''%action_name'' 풀 액션을 수행할 수 없습니다',
|
||||||
|
'Impossible d''effectuer l''action d''engagement ''%action_name''',
|
||||||
|
'Die Pull-Aktion ''%action_name'' kann nicht ausgeführt werden',
|
||||||
|
'无法执行拉怪动作“%action_name”',
|
||||||
|
'無法執行拉怪動作「%action_name」',
|
||||||
|
'No se puede realizar la acción de pull ''%action_name''',
|
||||||
|
'No se puede realizar la acción de pull ''%action_name''',
|
||||||
|
'Невозможно выполнить действие пула ''%action_name''');
|
||||||
|
|
||||||
|
INSERT INTO ai_playerbot_texts_chance (name, probability) VALUES ('pull_action_unavailable_error', 100);
|
||||||
@ -45,6 +45,7 @@
|
|||||||
#include "NonCombatActions.h"
|
#include "NonCombatActions.h"
|
||||||
#include "OutfitAction.h"
|
#include "OutfitAction.h"
|
||||||
#include "PositionAction.h"
|
#include "PositionAction.h"
|
||||||
|
#include "PullActions.h"
|
||||||
#include "DropQuestAction.h"
|
#include "DropQuestAction.h"
|
||||||
#include "RandomBotUpdateAction.h"
|
#include "RandomBotUpdateAction.h"
|
||||||
#include "ReachTargetActions.h"
|
#include "ReachTargetActions.h"
|
||||||
@ -105,6 +106,13 @@ public:
|
|||||||
creators["shoot"] = &ActionContext::shoot;
|
creators["shoot"] = &ActionContext::shoot;
|
||||||
creators["lifeblood"] = &ActionContext::lifeblood;
|
creators["lifeblood"] = &ActionContext::lifeblood;
|
||||||
creators["arcane torrent"] = &ActionContext::arcane_torrent;
|
creators["arcane torrent"] = &ActionContext::arcane_torrent;
|
||||||
|
creators["pull my target"] = &ActionContext::pull_my_target;
|
||||||
|
creators["pull rti target"] = &ActionContext::pull_rti_target;
|
||||||
|
creators["pull start"] = &ActionContext::pull_start;
|
||||||
|
creators["pull action"] = &ActionContext::pull_action;
|
||||||
|
creators["pull end"] = &ActionContext::pull_end;
|
||||||
|
creators["return to pull position"] = &ActionContext::return_to_pull_position;
|
||||||
|
creators["reach pull"] = &ActionContext::reach_pull;
|
||||||
creators["end pull"] = &ActionContext::end_pull;
|
creators["end pull"] = &ActionContext::end_pull;
|
||||||
creators["healthstone"] = &ActionContext::healthstone;
|
creators["healthstone"] = &ActionContext::healthstone;
|
||||||
creators["healing potion"] = &ActionContext::healing_potion;
|
creators["healing potion"] = &ActionContext::healing_potion;
|
||||||
@ -313,6 +321,13 @@ private:
|
|||||||
static Action* gift_of_the_naaru(PlayerbotAI* botAI) { return new CastGiftOfTheNaaruAction(botAI); }
|
static Action* gift_of_the_naaru(PlayerbotAI* botAI) { return new CastGiftOfTheNaaruAction(botAI); }
|
||||||
static Action* lifeblood(PlayerbotAI* botAI) { return new CastLifeBloodAction(botAI); }
|
static Action* lifeblood(PlayerbotAI* botAI) { return new CastLifeBloodAction(botAI); }
|
||||||
static Action* arcane_torrent(PlayerbotAI* botAI) { return new CastArcaneTorrentAction(botAI); }
|
static Action* arcane_torrent(PlayerbotAI* botAI) { return new CastArcaneTorrentAction(botAI); }
|
||||||
|
static Action* pull_my_target(PlayerbotAI* botAI) { return new PullMyTargetAction(botAI); }
|
||||||
|
static Action* pull_rti_target(PlayerbotAI* botAI) { return new PullRtiTargetAction(botAI); }
|
||||||
|
static Action* pull_start(PlayerbotAI* botAI) { return new PullStartAction(botAI); }
|
||||||
|
static Action* pull_action(PlayerbotAI* botAI) { return new PullAction(botAI); }
|
||||||
|
static Action* pull_end(PlayerbotAI* botAI) { return new PullEndAction(botAI); }
|
||||||
|
static Action* return_to_pull_position(PlayerbotAI* botAI) { return new ReturnToPullPositionAction(botAI); }
|
||||||
|
static Action* reach_pull(PlayerbotAI* botAI) { return new ReachPullAction(botAI); }
|
||||||
static Action* mana_tap(PlayerbotAI* botAI) { return new CastManaTapAction(botAI); }
|
static Action* mana_tap(PlayerbotAI* botAI) { return new CastManaTapAction(botAI); }
|
||||||
static Action* end_pull(PlayerbotAI* botAI) { return new ChangeCombatStrategyAction(botAI, "-pull"); }
|
static Action* end_pull(PlayerbotAI* botAI) { return new ChangeCombatStrategyAction(botAI, "-pull"); }
|
||||||
static Action* cancel_channel(PlayerbotAI* botAI) { return new CancelChannelAction(botAI); }
|
static Action* cancel_channel(PlayerbotAI* botAI) { return new CancelChannelAction(botAI); }
|
||||||
|
|||||||
@ -53,22 +53,6 @@ bool AttackMyTargetAction::Execute(Event /*event*/)
|
|||||||
|
|
||||||
bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/)
|
bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/)
|
||||||
{
|
{
|
||||||
Unit* oldTarget = context->GetValue<Unit*>("current target")->Get();
|
|
||||||
bool shouldMelee = bot->IsWithinMeleeRange(target) || botAI->IsMelee(bot);
|
|
||||||
|
|
||||||
bool sameTarget = oldTarget == target && bot->GetVictim() == target;
|
|
||||||
bool inCombat = botAI->GetState() == BOT_STATE_COMBAT;
|
|
||||||
bool sameAttackMode = bot->HasUnitState(UNIT_STATE_MELEE_ATTACKING) == shouldMelee;
|
|
||||||
|
|
||||||
if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE ||
|
|
||||||
bot->HasUnitState(UNIT_STATE_IN_FLIGHT))
|
|
||||||
{
|
|
||||||
if (verbose)
|
|
||||||
botAI->TellError("I cannot attack in flight");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target)
|
if (!target)
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -85,6 +69,15 @@ bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE ||
|
||||||
|
bot->HasUnitState(UNIT_STATE_IN_FLIGHT))
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
botAI->TellError("I cannot attack in flight");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if bot OR target is in prohibited zone/area (skip for duels)
|
// Check if bot OR target is in prohibited zone/area (skip for duels)
|
||||||
if ((target->IsPlayer() || target->IsPet()) &&
|
if ((target->IsPlayer() || target->IsPet()) &&
|
||||||
(!bot->duel || bot->duel->Opponent != target) &&
|
(!bot->duel || bot->duel->Opponent != target) &&
|
||||||
@ -121,6 +114,18 @@ bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Infantry attacks are not allowed from vehicles drivers.
|
||||||
|
// Check is needed to stop some auto-attack situations.
|
||||||
|
if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Unit* oldTarget = context->GetValue<Unit*>("current target")->Get();
|
||||||
|
bool shouldMelee = bot->IsWithinMeleeRange(target) || botAI->IsMelee(bot);
|
||||||
|
|
||||||
|
bool sameTarget = oldTarget == target && bot->GetVictim() == target;
|
||||||
|
bool inCombat = botAI->GetState() == BOT_STATE_COMBAT;
|
||||||
|
bool sameAttackMode = bot->HasUnitState(UNIT_STATE_MELEE_ATTACKING) == shouldMelee;
|
||||||
|
|
||||||
if (sameTarget && inCombat && sameAttackMode)
|
if (sameTarget && inCombat && sameAttackMode)
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -146,8 +151,7 @@ bool AttackAction::Attack(Unit* target, bool /*with_pet*/ /*true*/)
|
|||||||
ObjectGuid guid = target->GetGUID();
|
ObjectGuid guid = target->GetGUID();
|
||||||
bot->SetSelection(target->GetGUID());
|
bot->SetSelection(target->GetGUID());
|
||||||
|
|
||||||
context->GetValue<Unit*>("old target")->Set(oldTarget);
|
context->GetValue<Unit*>("old target")->Set(oldTarget);
|
||||||
|
|
||||||
context->GetValue<Unit*>("current target")->Set(target);
|
context->GetValue<Unit*>("current target")->Set(target);
|
||||||
context->GetValue<LootObjectStack*>("available loot")->Get()->Add(guid);
|
context->GetValue<LootObjectStack*>("available loot")->Get()->Add(guid);
|
||||||
|
|
||||||
|
|||||||
@ -73,7 +73,7 @@ void AutoMaintenanceOnLevelupAction::LearnSpells(std::ostringstream* out)
|
|||||||
LearnQuestSpells(out);
|
LearnQuestSpells(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoMaintenanceOnLevelupAction::LearnTrainerSpells(std::ostringstream* out)
|
void AutoMaintenanceOnLevelupAction::LearnTrainerSpells(std::ostringstream* /*out*/)
|
||||||
{
|
{
|
||||||
PlayerbotFactory factory(bot, bot->GetLevel());
|
PlayerbotFactory factory(bot, bot->GetLevel());
|
||||||
factory.InitSkills();
|
factory.InitSkills();
|
||||||
|
|||||||
@ -27,7 +27,7 @@ bool BankAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BankAction::ExecuteBank(std::string const text, Unit* bank)
|
bool BankAction::ExecuteBank(std::string const text, Unit* /*bank*/)
|
||||||
{
|
{
|
||||||
if (text.empty() || text == "?")
|
if (text.empty() || text == "?")
|
||||||
{
|
{
|
||||||
|
|||||||
@ -534,21 +534,18 @@ bool BGJoinAction::JoinQueue(uint32 type)
|
|||||||
|
|
||||||
botAI->GetAiObjectContext()->GetValue<uint32>("bg type")->Set(0);
|
botAI->GetAiObjectContext()->GetValue<uint32>("bg type")->Set(0);
|
||||||
|
|
||||||
|
WorldPacket* packet = nullptr;
|
||||||
if (!isArena)
|
if (!isArena)
|
||||||
{
|
{
|
||||||
WorldPacket* packet = new WorldPacket(CMSG_BATTLEMASTER_JOIN, 20);
|
packet = new WorldPacket(CMSG_BATTLEMASTER_JOIN, 20);
|
||||||
*packet << bot->GetGUID() << bgTypeId_ << instanceId << joinAsGroup;
|
*packet << bot->GetGUID() << bgTypeId_ << instanceId << joinAsGroup;
|
||||||
/// FIX race condition
|
|
||||||
// bot->GetSession()->HandleBattlemasterJoinOpcode(packet);
|
|
||||||
bot->GetSession()->QueuePacket(packet);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WorldPacket arena_packet(CMSG_BATTLEMASTER_JOIN_ARENA, 20);
|
packet = new WorldPacket(CMSG_BATTLEMASTER_JOIN_ARENA, 20);
|
||||||
arena_packet << unit->GetGUID() << arenaslot << asGroup << uint8(isRated);
|
*packet << unit->GetGUID() << arenaslot << asGroup << uint8(isRated);
|
||||||
bot->GetSession()->HandleBattlemasterJoinArena(arena_packet);
|
|
||||||
}
|
}
|
||||||
|
bot->GetSession()->QueuePacket(packet);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Execute(Event event) override;
|
bool Execute(Event event) override;
|
||||||
virtual std::string const castString(WorldObject* target) { return "cast"; }
|
virtual std::string const castString(WorldObject* /*target*/) { return "cast"; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ncCast = false;
|
bool ncCast = false;
|
||||||
@ -49,7 +49,7 @@ public:
|
|||||||
|
|
||||||
bool isUseful() override { return false; }
|
bool isUseful() override { return false; }
|
||||||
virtual bool AcceptSpell(SpellInfo const* spellInfo);
|
virtual bool AcceptSpell(SpellInfo const* spellInfo);
|
||||||
virtual uint32 GetSpellPriority(SpellInfo const* spellInfo) { return 1; }
|
virtual uint32 GetSpellPriority(SpellInfo const* /*spellInfo*/) { return 1; }
|
||||||
virtual bool castSpell(uint32 spellId, WorldObject* wo);
|
virtual bool castSpell(uint32 spellId, WorldObject* wo);
|
||||||
bool Execute(Event event) override;
|
bool Execute(Event event) override;
|
||||||
|
|
||||||
|
|||||||
@ -80,7 +80,7 @@ bool FollowChatShortcutAction::Execute(Event /*event*/)
|
|||||||
true, priority);
|
true, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Pet* pet = bot->GetPet())
|
if (bot->GetPet())
|
||||||
botAI->PetFollow();
|
botAI->PetFollow();
|
||||||
|
|
||||||
if (moved)
|
if (moved)
|
||||||
|
|||||||
@ -116,6 +116,7 @@ bool ChooseRpgTargetAction::Execute(Event /*event*/)
|
|||||||
GuidPosition masterRpgTarget;
|
GuidPosition masterRpgTarget;
|
||||||
if (master && master != bot && GET_PLAYERBOT_AI(master) && master->GetMapId() == bot->GetMapId() && !master->IsBeingTeleported())
|
if (master && master != bot && GET_PLAYERBOT_AI(master) && master->GetMapId() == bot->GetMapId() && !master->IsBeingTeleported())
|
||||||
{
|
{
|
||||||
|
//TODO Implement
|
||||||
Player* player = botAI->GetMaster();
|
Player* player = botAI->GetMaster();
|
||||||
//GuidPosition masterRpgTarget = PAI_VALUE(GuidPosition, "rpg target"); //not used, line marked for removal.
|
//GuidPosition masterRpgTarget = PAI_VALUE(GuidPosition, "rpg target"); //not used, line marked for removal.
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,31 +62,16 @@ bool CleanQuestLogAction::Execute(Event event)
|
|||||||
{
|
{
|
||||||
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
||||||
if (!requester)
|
if (!requester)
|
||||||
{
|
|
||||||
botAI->TellMaster("No event owner detected");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!sPlayerbotAIConfig.dropObsoleteQuests)
|
if (!sPlayerbotAIConfig.dropObsoleteQuests)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Only output this message if "debug rpg" strategy is enabled
|
// Only output this message if "debug rpg" strategy is enabled
|
||||||
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
||||||
{
|
|
||||||
botAI->TellMaster("Clean Quest Log command received, removing grey/trivial quests...");
|
botAI->TellMaster("Clean Quest Log command received, removing grey/trivial quests...");
|
||||||
}
|
|
||||||
|
|
||||||
uint8 botLevel = bot->GetLevel(); // Get bot's level
|
uint8 botLevel = bot->GetLevel(); // Get bot's level
|
||||||
uint8 numQuest = 0;
|
|
||||||
for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
|
|
||||||
{
|
|
||||||
if (bot->GetQuestSlotQuestId(slot))
|
|
||||||
{
|
|
||||||
numQuest++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
|
for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
|
||||||
{
|
{
|
||||||
@ -101,34 +86,24 @@ bool CleanQuestLogAction::Execute(Event event)
|
|||||||
// Determine if quest is trivial by comparing levels
|
// Determine if quest is trivial by comparing levels
|
||||||
int32 questLevel = quest->GetQuestLevel();
|
int32 questLevel = quest->GetQuestLevel();
|
||||||
if (questLevel == -1) // For scaling quests, default to bot level
|
if (questLevel == -1) // For scaling quests, default to bot level
|
||||||
{
|
|
||||||
questLevel = botLevel;
|
questLevel = botLevel;
|
||||||
}
|
|
||||||
|
|
||||||
// Set the level difference for when a quest becomes trivial
|
// Set the level difference for when a quest becomes trivial
|
||||||
// This was determined by using the Lua code the client uses
|
// This was determined by using the Lua code the client uses
|
||||||
int32 trivialLevel = 5;
|
int32 trivialLevel = 5;
|
||||||
if (botLevel >= 40)
|
if (botLevel >= 40)
|
||||||
{
|
|
||||||
trivialLevel = 8;
|
trivialLevel = 8;
|
||||||
}
|
|
||||||
else if (botLevel >= 30)
|
else if (botLevel >= 30)
|
||||||
{
|
|
||||||
trivialLevel = 7;
|
trivialLevel = 7;
|
||||||
}
|
|
||||||
else if (botLevel >= 20)
|
else if (botLevel >= 20)
|
||||||
{
|
|
||||||
trivialLevel = 6;
|
trivialLevel = 6;
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the quest is trivial (grey) for the bot
|
// Check if the quest is trivial (grey) for the bot
|
||||||
if ((botLevel - questLevel) > trivialLevel)
|
if ((botLevel - questLevel) > trivialLevel)
|
||||||
{
|
{
|
||||||
// Output only if "debug rpg" strategy is enabled
|
// Output only if "debug rpg" strategy is enabled
|
||||||
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
||||||
{
|
|
||||||
botAI->TellMaster("Quest [ " + quest->GetTitle() + " ] will be removed because it is trivial (grey).");
|
botAI->TellMaster("Quest [ " + quest->GetTitle() + " ] will be removed because it is trivial (grey).");
|
||||||
}
|
|
||||||
|
|
||||||
// Remove quest
|
// Remove quest
|
||||||
botAI->rpgStatistic.questDropped++;
|
botAI->rpgStatistic.questDropped++;
|
||||||
@ -137,8 +112,6 @@ bool CleanQuestLogAction::Execute(Event event)
|
|||||||
bot->SetQuestStatus(questId, QUEST_STATUS_NONE);
|
bot->SetQuestStatus(questId, QUEST_STATUS_NONE);
|
||||||
bot->RemoveRewardedQuest(questId);
|
bot->RemoveRewardedQuest(questId);
|
||||||
|
|
||||||
numQuest--;
|
|
||||||
|
|
||||||
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
||||||
{
|
{
|
||||||
const std::string text_quest = ChatHelper::FormatQuest(quest);
|
const std::string text_quest = ChatHelper::FormatQuest(quest);
|
||||||
@ -147,17 +120,13 @@ bool CleanQuestLogAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
||||||
{
|
|
||||||
botAI->TellMaster("Quest [ " + quest->GetTitle() + " ] has been removed.");
|
botAI->TellMaster("Quest [ " + quest->GetTitle() + " ] has been removed.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Only output if "debug rpg" strategy is enabled
|
// Only output if "debug rpg" strategy is enabled
|
||||||
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
||||||
{
|
|
||||||
botAI->TellMaster("Quest [ " + quest->GetTitle() + " ] is not trivial and will be kept.");
|
botAI->TellMaster("Quest [ " + quest->GetTitle() + " ] is not trivial and will be kept.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +143,6 @@ void CleanQuestLogAction::DropQuestType(uint8& numQuest, uint8 wantNum, bool isG
|
|||||||
{
|
{
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 g(rd());
|
std::mt19937 g(rd());
|
||||||
|
|
||||||
std::shuffle(slots.begin(), slots.end(), g);
|
std::shuffle(slots.begin(), slots.end(), g);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +168,10 @@ void CleanQuestLogAction::DropQuestType(uint8& numQuest, uint8 wantNum, bool isG
|
|||||||
bot->GetLevel() <= bot->GetQuestLevel(quest) + uint32(lowLevelDiff)) // Quest is not gray
|
bot->GetLevel() <= bot->GetQuestLevel(quest) + uint32(lowLevelDiff)) // Quest is not gray
|
||||||
{
|
{
|
||||||
if (bot->GetLevel() + 5 > bot->GetQuestLevel(quest)) // Quest is not red
|
if (bot->GetLevel() + 5 > bot->GetQuestLevel(quest)) // Quest is not red
|
||||||
|
{
|
||||||
if (!isGreen)
|
if (!isGreen)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else // Quest is gray
|
else // Quest is gray
|
||||||
{
|
{
|
||||||
|
|||||||
@ -93,8 +93,8 @@ bool FollowAction::Execute(Event /*event*/)
|
|||||||
? MovementPriority::MOVEMENT_COMBAT
|
? MovementPriority::MOVEMENT_COMBAT
|
||||||
: MovementPriority::MOVEMENT_NORMAL;
|
: MovementPriority::MOVEMENT_NORMAL;
|
||||||
|
|
||||||
bool const movingAllowed = IsMovingAllowed(mapId, destX, destY, destZ);
|
bool const movingAllowed = IsMovingAllowed();
|
||||||
bool const dupMove = IsDuplicateMove(mapId, destX, destY, destZ);
|
bool const dupMove = IsDuplicateMove(destX, destY, destZ);
|
||||||
bool const waiting = IsWaitingForLastMove(priority);
|
bool const waiting = IsWaitingForLastMove(priority);
|
||||||
|
|
||||||
if (movingAllowed && !dupMove && !waiting)
|
if (movingAllowed && !dupMove && !waiting)
|
||||||
|
|||||||
@ -273,7 +273,7 @@ bool BuffOnPartyAction::Execute(Event /*event*/)
|
|||||||
}
|
}
|
||||||
// End greater buff fix
|
// End greater buff fix
|
||||||
|
|
||||||
CastShootAction::CastShootAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "shoot")
|
CastShootAction::CastShootAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "shoot"), shootSpellId(0)
|
||||||
{
|
{
|
||||||
if (Item* const pItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED))
|
if (Item* const pItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED))
|
||||||
{
|
{
|
||||||
@ -283,17 +283,40 @@ CastShootAction::CastShootAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "s
|
|||||||
{
|
{
|
||||||
case ITEM_SUBCLASS_WEAPON_GUN:
|
case ITEM_SUBCLASS_WEAPON_GUN:
|
||||||
spell += " gun";
|
spell += " gun";
|
||||||
|
shootSpellId = 3018;
|
||||||
break;
|
break;
|
||||||
case ITEM_SUBCLASS_WEAPON_BOW:
|
case ITEM_SUBCLASS_WEAPON_BOW:
|
||||||
spell += " bow";
|
spell += " bow";
|
||||||
|
shootSpellId = 3018;
|
||||||
break;
|
break;
|
||||||
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
|
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
|
||||||
spell += " crossbow";
|
spell += " crossbow";
|
||||||
|
shootSpellId = 3018;
|
||||||
|
break;
|
||||||
|
case ITEM_SUBCLASS_WEAPON_THROWN:
|
||||||
|
spell = "throw";
|
||||||
|
shootSpellId = 2764;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CastShootAction::isPossible()
|
||||||
|
{
|
||||||
|
if (shootSpellId)
|
||||||
|
return botAI->CanCastSpell(shootSpellId, GetTarget(), false);
|
||||||
|
|
||||||
|
return CastSpellAction::isPossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CastShootAction::Execute(Event /*event*/)
|
||||||
|
{
|
||||||
|
if (shootSpellId)
|
||||||
|
return botAI->CastSpell(shootSpellId, GetTarget());
|
||||||
|
|
||||||
|
return botAI->CastSpell(spell, GetTarget());
|
||||||
|
}
|
||||||
|
|
||||||
Value<Unit*>* CastDebuffSpellOnAttackerAction::GetTargetValue()
|
Value<Unit*>* CastDebuffSpellOnAttackerAction::GetTargetValue()
|
||||||
{
|
{
|
||||||
return context->GetValue<Unit*>("attacker without aura", spell);
|
return context->GetValue<Unit*>("attacker without aura", spell);
|
||||||
|
|||||||
@ -253,7 +253,12 @@ class CastShootAction : public CastSpellAction
|
|||||||
public:
|
public:
|
||||||
CastShootAction(PlayerbotAI* botAI);
|
CastShootAction(PlayerbotAI* botAI);
|
||||||
|
|
||||||
|
bool isPossible() override;
|
||||||
|
bool Execute(Event event) override;
|
||||||
ActionThreatType getThreatType() override { return ActionThreatType::None; }
|
ActionThreatType getThreatType() override { return ActionThreatType::None; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 shootSpellId;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CastLifeBloodAction : public CastHealingSpellAction
|
class CastLifeBloodAction : public CastHealingSpellAction
|
||||||
|
|||||||
@ -53,7 +53,7 @@ bool GuildBankAction::Execute(std::string const text, GameObject* bank)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuildBankAction::MoveFromCharToBank(Item* item, GameObject* bank)
|
bool GuildBankAction::MoveFromCharToBank(Item* item, GameObject* /*bank*/)
|
||||||
{
|
{
|
||||||
uint32 playerSlot = item->GetSlot();
|
uint32 playerSlot = item->GetSlot();
|
||||||
uint32 playerBag = item->GetBagSlot();
|
uint32 playerBag = item->GetBagSlot();
|
||||||
|
|||||||
@ -78,7 +78,7 @@ private:
|
|||||||
class TakeMailProcessor : public MailProcessor
|
class TakeMailProcessor : public MailProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override
|
bool Process(uint32 /*index*/, Mail* mail, PlayerbotAI* botAI) override
|
||||||
{
|
{
|
||||||
Player* bot = botAI->GetBot();
|
Player* bot = botAI->GetBot();
|
||||||
if (!CheckBagSpace(bot))
|
if (!CheckBagSpace(bot))
|
||||||
@ -104,7 +104,7 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<uint32> guids;
|
std::vector<uint32> guids;
|
||||||
for (MailItemInfoVec::iterator i = mail->items.begin(); i != mail->items.end(); ++i)
|
for (MailItemInfoVec::iterator i = mail->items.begin(); i != mail->items.end(); ++i)
|
||||||
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(i->item_template))
|
if (sObjectMgr->GetItemTemplate(i->item_template))
|
||||||
guids.push_back(i->item_guid);
|
guids.push_back(i->item_guid);
|
||||||
|
|
||||||
for (std::vector<uint32>::iterator i = guids.begin(); i != guids.end(); ++i)
|
for (std::vector<uint32>::iterator i = guids.begin(); i != guids.end(); ++i)
|
||||||
@ -157,7 +157,7 @@ private:
|
|||||||
class DeleteMailProcessor : public MailProcessor
|
class DeleteMailProcessor : public MailProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override
|
bool Process(uint32 /*index*/, Mail* mail, PlayerbotAI* botAI) override
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "|cffffffff" << mail->subject << "|cffff0000 deleted";
|
out << "|cffffffff" << mail->subject << "|cffff0000 deleted";
|
||||||
@ -172,7 +172,7 @@ public:
|
|||||||
class ReadMailProcessor : public MailProcessor
|
class ReadMailProcessor : public MailProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override
|
bool Process(uint32 /*index*/, Mail* mail, PlayerbotAI* botAI) override
|
||||||
{
|
{
|
||||||
std::ostringstream out, body;
|
std::ostringstream out, body;
|
||||||
out << "|cffffffff" << mail->subject;
|
out << "|cffffffff" << mail->subject;
|
||||||
|
|||||||
@ -67,10 +67,10 @@ void MovementAction::CreateWp(Player* wpOwner, float x, float y, float z, float
|
|||||||
bool MovementAction::JumpTo(uint32 mapId, float x, float y, float z, MovementPriority priority)
|
bool MovementAction::JumpTo(uint32 mapId, float x, float y, float z, MovementPriority priority)
|
||||||
{
|
{
|
||||||
UpdateMovementState();
|
UpdateMovementState();
|
||||||
if (!IsMovingAllowed(mapId, x, y, z))
|
if (!IsMovingAllowed())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (IsDuplicateMove(mapId, x, y, z))
|
if (IsDuplicateMove(x, y, z))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (IsWaitingForLastMove(priority))
|
if (IsWaitingForLastMove(priority))
|
||||||
@ -173,11 +173,11 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
|||||||
bool exact_waypoint, MovementPriority priority, bool lessDelay, bool backwards)
|
bool exact_waypoint, MovementPriority priority, bool lessDelay, bool backwards)
|
||||||
{
|
{
|
||||||
UpdateMovementState();
|
UpdateMovementState();
|
||||||
if (!IsMovingAllowed(mapId, x, y, z))
|
if (!IsMovingAllowed())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (IsDuplicateMove(mapId, x, y, z))
|
if (IsDuplicateMove(x, y, z))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -899,20 +899,7 @@ bool MovementAction::IsMovingAllowed(WorldObject* target)
|
|||||||
return IsMovingAllowed();
|
return IsMovingAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MovementAction::IsMovingAllowed(uint32 mapId, float x, float y, float z)
|
bool MovementAction::IsDuplicateMove(float x, float y, float z)
|
||||||
{
|
|
||||||
// removed sqrt as means distance limit was effectively 22500 (ReactDistance<63>)
|
|
||||||
// leaving it commented incase we find ReactDistance limit causes problems
|
|
||||||
// float distance = sqrt(bot->GetDistance(x, y, z));
|
|
||||||
|
|
||||||
// Remove react distance limit
|
|
||||||
// if (!bot->InBattleground())
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
return IsMovingAllowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MovementAction::IsDuplicateMove(uint32 mapId, float x, float y, float z)
|
|
||||||
{
|
{
|
||||||
LastMovement& lastMove = *context->GetValue<LastMovement&>("last movement");
|
LastMovement& lastMove = *context->GetValue<LastMovement&>("last movement");
|
||||||
|
|
||||||
@ -1288,7 +1275,7 @@ bool MovementAction::Follow(Unit* target, float distance, float angle)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MovementAction::ChaseTo(WorldObject* obj, float distance, float angle)
|
bool MovementAction::ChaseTo(WorldObject* obj, float distance)
|
||||||
{
|
{
|
||||||
if (!IsMovingAllowed())
|
if (!IsMovingAllowed())
|
||||||
{
|
{
|
||||||
@ -1874,7 +1861,7 @@ bool FleeAction::isUseful()
|
|||||||
|
|
||||||
bool FleeWithPetAction::Execute(Event /*event*/)
|
bool FleeWithPetAction::Execute(Event /*event*/)
|
||||||
{
|
{
|
||||||
if (Pet* pet = bot->GetPet())
|
if (bot->GetPet())
|
||||||
botAI->PetFollow();
|
botAI->PetFollow();
|
||||||
|
|
||||||
return Flee(AI_VALUE(Unit*, "current target"));
|
return Flee(AI_VALUE(Unit*, "current target"));
|
||||||
|
|||||||
@ -57,14 +57,13 @@ protected:
|
|||||||
float GetFollowAngle();
|
float GetFollowAngle();
|
||||||
bool Follow(Unit* target, float distance = sPlayerbotAIConfig.followDistance);
|
bool Follow(Unit* target, float distance = sPlayerbotAIConfig.followDistance);
|
||||||
bool Follow(Unit* target, float distance, float angle);
|
bool Follow(Unit* target, float distance, float angle);
|
||||||
bool ChaseTo(WorldObject* obj, float distance = 0.0f, float angle = 0.0f);
|
bool ChaseTo(WorldObject* obj, float distance = 0.0f);
|
||||||
bool ReachCombatTo(Unit* target, float distance = 0.0f);
|
bool ReachCombatTo(Unit* target, float distance = 0.0f);
|
||||||
float MoveDelay(float distance, bool backwards = false);
|
float MoveDelay(float distance, bool backwards = false);
|
||||||
void WaitForReach(float distance);
|
void WaitForReach(float distance);
|
||||||
void SetNextMovementDelay(float delayMillis);
|
void SetNextMovementDelay(float delayMillis);
|
||||||
bool IsMovingAllowed(WorldObject* target);
|
bool IsMovingAllowed(WorldObject* target);
|
||||||
bool IsMovingAllowed(uint32 mapId, float x, float y, float z);
|
bool IsDuplicateMove(float x, float y, float z);
|
||||||
bool IsDuplicateMove(uint32 mapId, float x, float y, float z);
|
|
||||||
bool IsWaitingForLastMove(MovementPriority priority);
|
bool IsWaitingForLastMove(MovementPriority priority);
|
||||||
bool IsMovingAllowed();
|
bool IsMovingAllowed();
|
||||||
bool Flee(Unit* target);
|
bool Flee(Unit* target);
|
||||||
|
|||||||
321
src/Ai/Base/Actions/PullActions.cpp
Normal file
321
src/Ai/Base/Actions/PullActions.cpp
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AttackersValue.h"
|
||||||
|
#include "CreatureAI.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
#include "PlayerbotTextMgr.h"
|
||||||
|
#include "PositionValue.h"
|
||||||
|
#include "PullActions.h"
|
||||||
|
#include "PullStrategy.h"
|
||||||
|
#include "RtiTargetValue.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
float GetPullReachDistance(Player* bot, Unit* target, PullStrategy const* strategy)
|
||||||
|
{
|
||||||
|
if (!bot || !target || !strategy)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
float const combatDistance = bot->GetCombatReach() + target->GetCombatReach();
|
||||||
|
return std::max(0.0f, strategy->GetRange() - combatDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsWithinPullRange(Player* bot, Unit* target, PullStrategy const* strategy)
|
||||||
|
{
|
||||||
|
return bot && target && strategy && bot->GetExactDist(target) <= strategy->GetRange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PullRequestAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!botAI->IsTank(bot))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Unit* target = GetPullTarget(event);
|
||||||
|
if (!target || !target->IsInWorld())
|
||||||
|
{
|
||||||
|
std::string const text = PlayerbotTextMgr::instance().GetBotTextOrDefault(
|
||||||
|
"pull_no_target_error", "You have no target", {});
|
||||||
|
botAI->TellError(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float const maxPullDistance = sPlayerbotAIConfig.reactDistance * 3.0f;
|
||||||
|
if (target->GetMapId() != bot->GetMapId() || bot->GetDistance(target) > maxPullDistance)
|
||||||
|
{
|
||||||
|
std::string const text = PlayerbotTextMgr::instance().GetBotTextOrDefault(
|
||||||
|
"pull_target_too_far_error", "The target is too far away", {});
|
||||||
|
botAI->TellError(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AttackersValue::IsPossibleTarget(target, bot))
|
||||||
|
{
|
||||||
|
std::string const text = PlayerbotTextMgr::instance().GetBotTextOrDefault(
|
||||||
|
"pull_invalid_target_error", "The target can't be pulled", {});
|
||||||
|
botAI->TellError(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strategy->CanDoPullAction(target))
|
||||||
|
{
|
||||||
|
std::string const actionName = strategy->GetPullActionName();
|
||||||
|
std::string const text = PlayerbotTextMgr::instance().GetBotTextOrDefault(
|
||||||
|
"pull_action_unavailable_error",
|
||||||
|
"Can't perform pull action '%action_name'",
|
||||||
|
{{"%action_name", actionName}});
|
||||||
|
botAI->TellError(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PositionMap& posMap = AI_VALUE(PositionMap&, "position");
|
||||||
|
PositionInfo pullPosition = posMap["pull"];
|
||||||
|
pullPosition.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId());
|
||||||
|
posMap["pull"] = pullPosition;
|
||||||
|
|
||||||
|
strategy->RequestPull(target);
|
||||||
|
context->GetValue<Unit*>("current target")->Set(target);
|
||||||
|
botAI->ChangeEngine(BOT_STATE_COMBAT);
|
||||||
|
botAI->SetNextCheckDelay(sPlayerbotAIConfig.reactDelay);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit* PullMyTargetAction::GetPullTarget(Event event)
|
||||||
|
{
|
||||||
|
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
||||||
|
if (event.GetSource() == "attack anything")
|
||||||
|
return botAI->GetCreature(event.getObject());
|
||||||
|
|
||||||
|
return requester ? requester->GetSelectedUnit() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit* PullRtiTargetAction::GetPullTarget(Event /*event*/)
|
||||||
|
{
|
||||||
|
Unit* rtiTarget = AI_VALUE(Unit*, "rti target");
|
||||||
|
if (rtiTarget)
|
||||||
|
return rtiTarget;
|
||||||
|
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::string const rti = AI_VALUE(std::string, "rti");
|
||||||
|
int32 const index = RtiTargetValue::GetRtiIndex(rti);
|
||||||
|
if (index < 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
ObjectGuid const guid = group->GetTargetIcon(index);
|
||||||
|
return guid.IsEmpty() ? nullptr : botAI->GetUnit(guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PullStartAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Unit* target = strategy->GetTarget();
|
||||||
|
if (!target)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string const preActionName = strategy->GetPreActionName();
|
||||||
|
if (!preActionName.empty() && !botAI->DoSpecificAction(preActionName, event, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Pet* pet = bot->GetPet())
|
||||||
|
{
|
||||||
|
Creature* creature = pet->ToCreature();
|
||||||
|
if (creature)
|
||||||
|
{
|
||||||
|
strategy->SetPetReactState(creature->GetReactState());
|
||||||
|
creature->SetReactState(REACT_PASSIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strategy->OnPullStarted();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PullAction::PullAction(PlayerbotAI* botAI, std::string const name) : CastSpellAction(botAI, name) { InitPullAction(); }
|
||||||
|
|
||||||
|
Unit* PullAction::GetTarget()
|
||||||
|
{
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return strategy->GetTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<NextAction> PullAction::getPrerequisites()
|
||||||
|
{
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
Unit* target = strategy ? strategy->GetTarget() : nullptr;
|
||||||
|
if (!strategy || !target)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return IsWithinPullRange(bot, target, strategy) ? std::vector<NextAction>{}
|
||||||
|
: std::vector<NextAction>{ NextAction("reach pull", ACTION_MOVE) };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PullAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
InitPullAction();
|
||||||
|
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Unit* target = strategy->GetTarget();
|
||||||
|
if (!target || !target->IsInWorld())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (target->IsInCombat())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!IsWithinPullRange(bot, target, strategy))
|
||||||
|
{
|
||||||
|
strategy->RequestPull(target, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bot->isMoving())
|
||||||
|
{
|
||||||
|
bot->StopMoving();
|
||||||
|
strategy->RequestPull(target, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->GetValue<Unit*>("current target")->Set(target);
|
||||||
|
if (!botAI->DoSpecificAction(strategy->GetPullActionName(), event, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PullAction::isPossible()
|
||||||
|
{
|
||||||
|
InitPullAction();
|
||||||
|
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Unit* target = strategy->GetTarget();
|
||||||
|
std::string const spellName = strategy->GetSpellName();
|
||||||
|
if (!target || !target->IsInWorld() || target->GetMapId() != bot->GetMapId() || spellName.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PullAction::InitPullAction()
|
||||||
|
{
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string const spellName = strategy->GetSpellName();
|
||||||
|
if (spellName.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
spell = spellName;
|
||||||
|
|
||||||
|
bool isShoot = (spellName == "shoot" || spellName == "shoot bow" ||
|
||||||
|
spellName == "shoot gun" || spellName == "shoot crossbow" ||
|
||||||
|
spellName == "throw");
|
||||||
|
range = botAI->GetRange(isShoot ? "shoot" : "spell");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PullEndAction::Execute(Event /*event*/)
|
||||||
|
{
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Unit* pullTarget = strategy->GetTarget();
|
||||||
|
|
||||||
|
if (!strategy->HasPullStarted() && !strategy->IsPullPendingToStart() && !strategy->HasTarget())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Pet* pet = bot->GetPet())
|
||||||
|
{
|
||||||
|
Creature* creature = pet->ToCreature();
|
||||||
|
if (creature)
|
||||||
|
creature->SetReactState(strategy->GetPetReactState());
|
||||||
|
}
|
||||||
|
|
||||||
|
PositionMap& posMap = AI_VALUE(PositionMap&, "position");
|
||||||
|
PositionInfo pullPosition = posMap["pull"];
|
||||||
|
if (pullPosition.isSet())
|
||||||
|
posMap.erase("pull");
|
||||||
|
|
||||||
|
if (pullTarget && context->GetValue<Unit*>("current target")->Get() == pullTarget)
|
||||||
|
context->GetValue<Unit*>("current target")->Set(nullptr);
|
||||||
|
|
||||||
|
strategy->OnPullEnded();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReturnToPullPositionAction::Execute(Event /*event*/)
|
||||||
|
{
|
||||||
|
PositionInfo pullPosition = AI_VALUE(PositionMap&, "position")["pull"];
|
||||||
|
if (!pullPosition.isSet() || pullPosition.mapId != bot->GetMapId())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return MoveTo(pullPosition.mapId, pullPosition.x, pullPosition.y, pullPosition.z,
|
||||||
|
false, false, false, false, MovementPriority::MOVEMENT_COMBAT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReturnToPullPositionAction::isUseful()
|
||||||
|
{
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
Unit* target = strategy ? strategy->GetTarget() : nullptr;
|
||||||
|
if (!strategy || !target || !target->IsInCombat())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PositionInfo pullPosition = AI_VALUE(PositionMap&, "position")["pull"];
|
||||||
|
return pullPosition.isSet() && pullPosition.mapId == bot->GetMapId() &&
|
||||||
|
bot->GetDistance(pullPosition.x, pullPosition.y, pullPosition.z) > sPlayerbotAIConfig.followDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReachPullAction::Execute(Event /*event*/)
|
||||||
|
{
|
||||||
|
Unit* target = GetTarget();
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!target || !strategy)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float const reachDistance = GetPullReachDistance(bot, target, strategy);
|
||||||
|
return ReachCombatTo(target, reachDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReachPullAction::isUseful()
|
||||||
|
{
|
||||||
|
if (botAI->HasStrategy("stay", botAI->GetState()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
Unit* target = strategy ? strategy->GetTarget() : nullptr;
|
||||||
|
return target && !IsWithinPullRange(bot, target, strategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit* ReachPullAction::GetTarget()
|
||||||
|
{
|
||||||
|
PullStrategy* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return strategy->GetTarget();
|
||||||
|
}
|
||||||
90
src/Ai/Base/Actions/PullActions.h
Normal file
90
src/Ai/Base/Actions/PullActions.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAYERBOT_PULLACTIONS_H
|
||||||
|
#define _PLAYERBOT_PULLACTIONS_H
|
||||||
|
|
||||||
|
#include "GenericSpellActions.h"
|
||||||
|
#include "ReachTargetActions.h"
|
||||||
|
|
||||||
|
class PullRequestAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullRequestAction(PlayerbotAI* botAI, std::string const name) : Action(botAI, name) {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual Unit* GetPullTarget(Event event) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PullMyTargetAction : public PullRequestAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullMyTargetAction(PlayerbotAI* botAI) : PullRequestAction(botAI, "pull my target") {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Unit* GetPullTarget(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PullRtiTargetAction : public PullRequestAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullRtiTargetAction(PlayerbotAI* botAI) : PullRequestAction(botAI, "pull rti target") {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Unit* GetPullTarget(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PullStartAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullStartAction(PlayerbotAI* botAI, std::string const name = "pull start") : Action(botAI, name) {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PullAction : public CastSpellAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullAction(PlayerbotAI* botAI, std::string const name = "pull action");
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isPossible() override;
|
||||||
|
std::vector<NextAction> getPrerequisites() override;
|
||||||
|
Unit* GetTarget() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void InitPullAction();
|
||||||
|
};
|
||||||
|
|
||||||
|
class PullEndAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullEndAction(PlayerbotAI* botAI, std::string const name = "pull end") : Action(botAI, name) {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReachPullAction : public ReachTargetAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReachPullAction(PlayerbotAI* botAI) : ReachTargetAction(botAI, "reach pull", botAI->GetRange("spell")) {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
Unit* GetTarget() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReturnToPullPositionAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReturnToPullPositionAction(PlayerbotAI* botAI) : MovementAction(botAI, "return to pull position") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -45,7 +45,7 @@ std::once_flag ReadyChecker::initFlag;
|
|||||||
class HealthChecker : public ReadyChecker
|
class HealthChecker : public ReadyChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Check(PlayerbotAI* botAI, AiObjectContext* context) override
|
bool Check(PlayerbotAI* /*botAI*/, AiObjectContext* context) override
|
||||||
{
|
{
|
||||||
return AI_VALUE2(uint8, "health", "self target") > sPlayerbotAIConfig.almostFullHealth;
|
return AI_VALUE2(uint8, "health", "self target") > sPlayerbotAIConfig.almostFullHealth;
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ public:
|
|||||||
class ManaChecker : public ReadyChecker
|
class ManaChecker : public ReadyChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Check(PlayerbotAI* botAI, AiObjectContext* context) override
|
bool Check(PlayerbotAI* /*botAI*/, AiObjectContext* context) override
|
||||||
{
|
{
|
||||||
return !AI_VALUE2(bool, "has mana", "self target") ||
|
return !AI_VALUE2(bool, "has mana", "self target") ||
|
||||||
AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig.mediumHealth;
|
AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig.mediumHealth;
|
||||||
@ -68,7 +68,7 @@ public:
|
|||||||
class DistanceChecker : public ReadyChecker
|
class DistanceChecker : public ReadyChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Check(PlayerbotAI* botAI, AiObjectContext* context) override
|
bool Check(PlayerbotAI* botAI, AiObjectContext* /*context*/) override
|
||||||
{
|
{
|
||||||
Player* bot = botAI->GetBot();
|
Player* bot = botAI->GetBot();
|
||||||
if (Player* master = botAI->GetMaster())
|
if (Player* master = botAI->GetMaster())
|
||||||
@ -90,7 +90,7 @@ public:
|
|||||||
class HunterChecker : public ReadyChecker
|
class HunterChecker : public ReadyChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Check(PlayerbotAI* botAI, AiObjectContext* context) override
|
bool Check(PlayerbotAI* botAI, AiObjectContext* /*context*/) override
|
||||||
{
|
{
|
||||||
Player* bot = botAI->GetBot();
|
Player* bot = botAI->GetBot();
|
||||||
if (bot->getClass() == CLASS_HUNTER)
|
if (bot->getClass() == CLASS_HUNTER)
|
||||||
@ -126,7 +126,7 @@ class ItemCountChecker : public ReadyChecker
|
|||||||
public:
|
public:
|
||||||
ItemCountChecker(std::string const item, std::string const name) : item(item), name(name) {}
|
ItemCountChecker(std::string const item, std::string const name) : item(item), name(name) {}
|
||||||
|
|
||||||
bool Check(PlayerbotAI* botAI, AiObjectContext* context) override
|
bool Check(PlayerbotAI* /*botAI*/, AiObjectContext* context) override
|
||||||
{
|
{
|
||||||
return AI_VALUE2(uint32, "item count", item) > 0;
|
return AI_VALUE2(uint32, "item count", item) > 0;
|
||||||
}
|
}
|
||||||
@ -225,4 +225,4 @@ bool ReadyCheckAction::ReadyCheck()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FinishReadyCheckAction::Execute(Event event) { return ReadyCheck(); }
|
bool FinishReadyCheckAction::Execute(Event /*event*/) { return ReadyCheck(); }
|
||||||
|
|||||||
@ -65,7 +65,7 @@ void ReleaseSpiritAction::IncrementDeathCount() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseSpiritAction::LogRelease(const std::string& releaseMsg, bool isAutoRelease) const
|
void ReleaseSpiritAction::LogRelease(const std::string& releaseMsg) const
|
||||||
{
|
{
|
||||||
const std::string teamPrefix = bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H";
|
const std::string teamPrefix = bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H";
|
||||||
|
|
||||||
@ -82,13 +82,13 @@ bool AutoReleaseSpiritAction::Execute(Event /*event*/)
|
|||||||
{
|
{
|
||||||
IncrementDeathCount();
|
IncrementDeathCount();
|
||||||
bot->DurabilityRepairAll(false, 1.0f, false);
|
bot->DurabilityRepairAll(false, 1.0f, false);
|
||||||
LogRelease("auto released", true);
|
LogRelease("auto released");
|
||||||
|
|
||||||
WorldPacket packet(CMSG_REPOP_REQUEST);
|
WorldPacket packet(CMSG_REPOP_REQUEST);
|
||||||
packet << uint8(0);
|
packet << uint8(0);
|
||||||
bot->GetSession()->HandleRepopRequestOpcode(packet);
|
bot->GetSession()->HandleRepopRequestOpcode(packet);
|
||||||
|
|
||||||
LogRelease("releases spirit", true);
|
LogRelease("releases spirit");
|
||||||
|
|
||||||
if (bot->InBattleground())
|
if (bot->InBattleground())
|
||||||
{
|
{
|
||||||
|
|||||||
@ -18,7 +18,7 @@ public:
|
|||||||
: Action(botAI, name) {}
|
: Action(botAI, name) {}
|
||||||
|
|
||||||
bool Execute(Event event) override;
|
bool Execute(Event event) override;
|
||||||
void LogRelease(const std::string& releaseType, bool isAutoRelease = false) const;
|
void LogRelease(const std::string& releaseType) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void IncrementDeathCount() const;
|
void IncrementDeathCount() const;
|
||||||
|
|||||||
@ -251,9 +251,9 @@ GraveyardStruct const* SpiritHealerAction::GetGrave(bool startZone)
|
|||||||
std::vector<uint32> races;
|
std::vector<uint32> races;
|
||||||
|
|
||||||
if (bot->GetTeamId() == TEAM_ALLIANCE)
|
if (bot->GetTeamId() == TEAM_ALLIANCE)
|
||||||
races = {RACE_HUMAN, RACE_DWARF, RACE_GNOME, RACE_NIGHTELF};
|
races = {RACE_HUMAN, RACE_DWARF, RACE_GNOME, RACE_NIGHTELF, RACE_DRAENEI};
|
||||||
else
|
else
|
||||||
races = {RACE_ORC, RACE_TROLL, RACE_TAUREN, RACE_UNDEAD_PLAYER};
|
races = {RACE_ORC, RACE_TROLL, RACE_TAUREN, RACE_UNDEAD_PLAYER, RACE_BLOODELF};
|
||||||
|
|
||||||
float graveDistance = -1;
|
float graveDistance = -1;
|
||||||
|
|
||||||
|
|||||||
@ -154,7 +154,7 @@ bool SayAction::isUseful()
|
|||||||
return (time(nullptr) - lastSaid) > 30;
|
return (time(nullptr) - lastSaid) > 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint32& guid2, std::string& msg, std::string& chanName, std::string& name)
|
void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, std::string& msg, std::string& chanName, std::string& name)
|
||||||
{
|
{
|
||||||
std::string respondsText = "";
|
std::string respondsText = "";
|
||||||
|
|
||||||
@ -205,14 +205,14 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint
|
|||||||
if (msg.starts_with(sPlayerbotAIConfig.toxicLinksPrefix)
|
if (msg.starts_with(sPlayerbotAIConfig.toxicLinksPrefix)
|
||||||
&& (GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllItemIds(msg).size() > 0 || GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllQuestIds(msg).size() > 0))
|
&& (GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllItemIds(msg).size() > 0 || GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllQuestIds(msg).size() > 0))
|
||||||
{
|
{
|
||||||
HandleToxicLinksReply(bot, chatChannelSource, msg, name);
|
HandleToxicLinksReply(bot, chatChannelSource);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//thunderfury
|
//thunderfury
|
||||||
if (GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllItemIds(msg).count(19019))
|
if (GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllItemIds(msg).count(19019))
|
||||||
{
|
{
|
||||||
HandleThunderfuryReply(bot, chatChannelSource, msg, name);
|
HandleThunderfuryReply(bot, chatChannelSource);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +220,7 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint
|
|||||||
SendGeneralResponse(bot, chatChannelSource, messageRepy, name);
|
SendGeneralResponse(bot, chatChannelSource, messageRepy, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name)
|
bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string> placeholders;
|
std::map<std::string, std::string> placeholders;
|
||||||
const auto thunderfury = sObjectMgr->GetItemTemplate(19019);
|
const auto thunderfury = sObjectMgr->GetItemTemplate(19019);
|
||||||
@ -248,7 +248,7 @@ bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chat
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name)
|
bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource)
|
||||||
{
|
{
|
||||||
//quests
|
//quests
|
||||||
std::vector<uint32> incompleteQuests;
|
std::vector<uint32> incompleteQuests;
|
||||||
|
|||||||
@ -29,12 +29,12 @@ class ChatReplyAction : public Action
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ChatReplyAction(PlayerbotAI* ai) : Action(ai, "chat message") {}
|
ChatReplyAction(PlayerbotAI* ai) : Action(ai, "chat message") {}
|
||||||
virtual bool Execute(Event event) { return true; }
|
virtual bool Execute(Event /*event*/) { return true; }
|
||||||
bool isUseful() { return true; }
|
bool isUseful() { return true; }
|
||||||
|
|
||||||
static void ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint32& guid2, std::string& msg, std::string& chanName, std::string& name);
|
static void ChatReplyDo(Player* bot, uint32& type, uint32& guid1, std::string& msg, std::string& chanName, std::string& name);
|
||||||
static bool HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
|
static bool HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource);
|
||||||
static bool HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
|
static bool HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource);
|
||||||
static bool HandleWTBItemsReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
|
static bool HandleWTBItemsReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
|
||||||
static bool HandleLFGQuestsReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
|
static bool HandleLFGQuestsReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
|
||||||
static bool SendGeneralResponse(Player* bot, ChatChannelSource chatChannelSource, std::string& responseMessage, std::string& name);
|
static bool SendGeneralResponse(Player* bot, ChatChannelSource chatChannelSource, std::string& responseMessage, std::string& name);
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
std::set<uint32> const FISHING_SPELLS = {7620, 7731, 7732, 18248, 33095, 51294};
|
std::set<uint32> const FISHING_SPELLS = {7620, 7731, 7732, 18248, 33095, 51294};
|
||||||
|
|
||||||
Creature* SeeSpellAction::CreateWps(Player* wpOwner, float x, float y, float z, float o, uint32 entry, Creature* lastWp,
|
Creature* SeeSpellAction::CreateWps(Player* wpOwner, float x, float y, float z, float o, uint32 entry, Creature* /*lastWp*/,
|
||||||
bool important)
|
bool important)
|
||||||
{
|
{
|
||||||
float dist = wpOwner->GetDistance(x, y, z);
|
float dist = wpOwner->GetDistance(x, y, z);
|
||||||
|
|||||||
@ -61,7 +61,7 @@ bool SummonAction::Execute(Event /*event*/)
|
|||||||
if (!master)
|
if (!master)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Pet* pet = bot->GetPet())
|
if (bot->GetPet())
|
||||||
botAI->PetFollow();
|
botAI->PetFollow();
|
||||||
|
|
||||||
if (master->GetSession()->GetSecurity() >= SEC_PLAYER)
|
if (master->GetSession()->GetSecurity() >= SEC_PLAYER)
|
||||||
|
|||||||
@ -43,6 +43,7 @@
|
|||||||
#include "NewRpgAction.h"
|
#include "NewRpgAction.h"
|
||||||
#include "PassLeadershipToMasterAction.h"
|
#include "PassLeadershipToMasterAction.h"
|
||||||
#include "PositionAction.h"
|
#include "PositionAction.h"
|
||||||
|
#include "PullActions.h"
|
||||||
#include "QueryItemUsageAction.h"
|
#include "QueryItemUsageAction.h"
|
||||||
#include "QueryQuestAction.h"
|
#include "QueryQuestAction.h"
|
||||||
#include "RangeAction.h"
|
#include "RangeAction.h"
|
||||||
@ -138,6 +139,8 @@ public:
|
|||||||
creators["autogear"] = &ChatActionContext::autogear;
|
creators["autogear"] = &ChatActionContext::autogear;
|
||||||
creators["equip upgrade"] = &ChatActionContext::equip_upgrade;
|
creators["equip upgrade"] = &ChatActionContext::equip_upgrade;
|
||||||
creators["attack my target"] = &ChatActionContext::attack_my_target;
|
creators["attack my target"] = &ChatActionContext::attack_my_target;
|
||||||
|
creators["pull my target"] = &ChatActionContext::pull_my_target;
|
||||||
|
creators["pull rti target"] = &ChatActionContext::pull_rti_target;
|
||||||
creators["chat"] = &ChatActionContext::chat;
|
creators["chat"] = &ChatActionContext::chat;
|
||||||
creators["home"] = &ChatActionContext::home;
|
creators["home"] = &ChatActionContext::home;
|
||||||
creators["destroy"] = &ChatActionContext::destroy;
|
creators["destroy"] = &ChatActionContext::destroy;
|
||||||
@ -250,6 +253,8 @@ private:
|
|||||||
static Action* home(PlayerbotAI* botAI) { return new SetHomeAction(botAI); }
|
static Action* home(PlayerbotAI* botAI) { return new SetHomeAction(botAI); }
|
||||||
static Action* chat(PlayerbotAI* botAI) { return new ChangeChatAction(botAI); }
|
static Action* chat(PlayerbotAI* botAI) { return new ChangeChatAction(botAI); }
|
||||||
static Action* attack_my_target(PlayerbotAI* botAI) { return new AttackMyTargetAction(botAI); }
|
static Action* attack_my_target(PlayerbotAI* botAI) { return new AttackMyTargetAction(botAI); }
|
||||||
|
static Action* pull_my_target(PlayerbotAI* botAI) { return new PullMyTargetAction(botAI); }
|
||||||
|
static Action* pull_rti_target(PlayerbotAI* botAI) { return new PullRtiTargetAction(botAI); }
|
||||||
static Action* trainer(PlayerbotAI* botAI) { return new TrainerAction(botAI); }
|
static Action* trainer(PlayerbotAI* botAI) { return new TrainerAction(botAI); }
|
||||||
static Action* maintenance(PlayerbotAI* botAI) { return new MaintenanceAction(botAI); }
|
static Action* maintenance(PlayerbotAI* botAI) { return new MaintenanceAction(botAI); }
|
||||||
static Action* remove_glyph(PlayerbotAI* botAI) { return new RemoveGlyphAction(botAI); }
|
static Action* remove_glyph(PlayerbotAI* botAI) { return new RemoveGlyphAction(botAI); }
|
||||||
|
|||||||
@ -66,6 +66,9 @@ public:
|
|||||||
creators["autogear"] = &ChatTriggerContext::autogear;
|
creators["autogear"] = &ChatTriggerContext::autogear;
|
||||||
creators["equip upgrade"] = &ChatTriggerContext::equip_upgrade;
|
creators["equip upgrade"] = &ChatTriggerContext::equip_upgrade;
|
||||||
creators["attack"] = &ChatTriggerContext::attack;
|
creators["attack"] = &ChatTriggerContext::attack;
|
||||||
|
creators["pull"] = &ChatTriggerContext::pull;
|
||||||
|
creators["pull back"] = &ChatTriggerContext::pull_back;
|
||||||
|
creators["pull rti"] = &ChatTriggerContext::pull_rti;
|
||||||
creators["chat"] = &ChatTriggerContext::chat;
|
creators["chat"] = &ChatTriggerContext::chat;
|
||||||
creators["accept"] = &ChatTriggerContext::accept;
|
creators["accept"] = &ChatTriggerContext::accept;
|
||||||
creators["home"] = &ChatTriggerContext::home;
|
creators["home"] = &ChatTriggerContext::home;
|
||||||
@ -209,6 +212,9 @@ private:
|
|||||||
static Trigger* accept(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "accept"); }
|
static Trigger* accept(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "accept"); }
|
||||||
static Trigger* chat(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "chat"); }
|
static Trigger* chat(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "chat"); }
|
||||||
static Trigger* attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "attack"); }
|
static Trigger* attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "attack"); }
|
||||||
|
static Trigger* pull(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pull"); }
|
||||||
|
static Trigger* pull_back(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pull back"); }
|
||||||
|
static Trigger* pull_rti(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pull rti"); }
|
||||||
static Trigger* trainer(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "trainer"); }
|
static Trigger* trainer(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "trainer"); }
|
||||||
static Trigger* maintenance(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "maintenance"); }
|
static Trigger* maintenance(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "maintenance"); }
|
||||||
static Trigger* remove_glyph(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "remove glyph"); }
|
static Trigger* remove_glyph(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "remove glyph"); }
|
||||||
|
|||||||
@ -11,7 +11,7 @@ public:
|
|||||||
ChatCommandActionNodeFactoryInternal() { creators["tank attack chat shortcut"] = &tank_attack_chat_shortcut; }
|
ChatCommandActionNodeFactoryInternal() { creators["tank attack chat shortcut"] = &tank_attack_chat_shortcut; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ActionNode* tank_attack_chat_shortcut(PlayerbotAI* botAI)
|
static ActionNode* tank_attack_chat_shortcut(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode("tank attack chat shortcut",
|
return new ActionNode("tank attack chat shortcut",
|
||||||
/*P*/ {},
|
/*P*/ {},
|
||||||
@ -81,6 +81,12 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
|||||||
new TriggerNode("attackers", { NextAction("tell attackers", relevance) }));
|
new TriggerNode("attackers", { NextAction("tell attackers", relevance) }));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode("target", { NextAction("tell target", relevance) }));
|
new TriggerNode("target", { NextAction("tell target", relevance) }));
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("pull", { NextAction("pull my target", relevance) }));
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("pull back", { NextAction("pull my target", relevance) }));
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("pull rti", { NextAction("pull rti target", relevance) }));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode("ready", { NextAction("ready check", relevance) }));
|
new TriggerNode("ready", { NextAction("ready check", relevance) }));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
|
|||||||
@ -64,11 +64,11 @@ std::vector<NextAction> AvoidAoeStrategy::getDefaultActions()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvoidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void AvoidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvoidAoeStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
void AvoidAoeStrategy::InitMultipliers(std::vector<Multiplier*>& /*multipliers*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ std::vector<NextAction> TankFaceStrategy::getDefaultActions()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TankFaceStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void TankFaceStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,6 @@ void DuelStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
|
|
||||||
DuelStrategy::DuelStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {}
|
DuelStrategy::DuelStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) {}
|
||||||
|
|
||||||
void StartDuelStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) {}
|
void StartDuelStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/) {}
|
||||||
|
|
||||||
StartDuelStrategy::StartDuelStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
StartDuelStrategy::StartDuelStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||||
|
|||||||
@ -12,6 +12,6 @@ std::vector<NextAction> FollowMasterStrategy::getDefaultActions()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void FollowMasterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void FollowMasterStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,4 +12,4 @@ std::vector<NextAction> GuardStrategy::getDefaultActions()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuardStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) {}
|
void GuardStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/) {}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ void MaintenanceStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
{
|
{
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode(
|
new TriggerNode(
|
||||||
"random",
|
"seldom",
|
||||||
{
|
{
|
||||||
NextAction("clean quest log", 6.0f)
|
NextAction("clean quest log", 6.0f)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ void CollisionStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
new TriggerNode("collision", { NextAction("move out of collision", 2.0f) }));
|
new TriggerNode("collision", { NextAction("move out of collision", 2.0f) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MountStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void MountStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,188 @@
|
|||||||
|
|
||||||
#include "PullStrategy.h"
|
#include "PullStrategy.h"
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
#include "PassiveMultiplier.h"
|
#include "PassiveMultiplier.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
#include "SpellMgr.h"
|
||||||
|
|
||||||
|
class PullStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullStrategyActionNodeFactory()
|
||||||
|
{
|
||||||
|
creators["pull start"] = &pull_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static ActionNode* pull_start(PlayerbotAI* /*botAI*/)
|
||||||
|
{
|
||||||
|
return new ActionNode("pull start", {}, {}, { NextAction("pull action", ACTION_NORMAL) });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PullStrategy::PullStrategy(PlayerbotAI* botAI, std::string const action, std::string const preAction)
|
||||||
|
: Strategy(botAI), action(action), preAction(preAction)
|
||||||
|
{
|
||||||
|
actionNodeFactories.Add(new PullStrategyActionNodeFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
PullStrategy* PullStrategy::Get(PlayerbotAI* botAI)
|
||||||
|
{
|
||||||
|
if (!botAI)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (PullStrategy* strategy = dynamic_cast<PullStrategy*>(botAI->GetStrategy("pull", BOT_STATE_NON_COMBAT)))
|
||||||
|
{
|
||||||
|
if (strategy->IsPullPendingToStart() || strategy->HasPullStarted() || strategy->HasTarget())
|
||||||
|
return strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dynamic_cast<PullStrategy*>(botAI->GetStrategy("pull", BOT_STATE_COMBAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit* PullStrategy::GetTarget() const
|
||||||
|
{
|
||||||
|
ObjectGuid const guid = botAI->GetAiObjectContext()->GetValue<ObjectGuid>("pull strategy target")->Get();
|
||||||
|
if (guid.IsEmpty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
Unit* target = botAI->GetUnit(guid);
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
if (!bot || !target || !target->IsAlive() || !target->IsInWorld() ||
|
||||||
|
target->GetMapId() != bot->GetMapId())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PullStrategy::HasTarget() const { return GetTarget() != nullptr; }
|
||||||
|
|
||||||
|
void PullStrategy::SetTarget(Unit* target)
|
||||||
|
{
|
||||||
|
botAI->GetAiObjectContext()->GetValue<ObjectGuid>("pull strategy target")->Set(target ? target->GetGUID() : ObjectGuid::Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PullStrategy::GetPullActionName() const
|
||||||
|
{
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PullStrategy::GetSpellName() const
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
std::string spellName = GetPullActionName();
|
||||||
|
if (!bot || spellName != "shoot")
|
||||||
|
return spellName;
|
||||||
|
|
||||||
|
Item* equippedWeapon = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
|
||||||
|
if (!equippedWeapon)
|
||||||
|
return spellName;
|
||||||
|
|
||||||
|
ItemTemplate const* itemTemplate = equippedWeapon->GetTemplate();
|
||||||
|
if (!itemTemplate)
|
||||||
|
return spellName;
|
||||||
|
|
||||||
|
switch (itemTemplate->SubClass)
|
||||||
|
{
|
||||||
|
case ITEM_SUBCLASS_WEAPON_THROWN:
|
||||||
|
return "throw";
|
||||||
|
case ITEM_SUBCLASS_WEAPON_GUN:
|
||||||
|
return "shoot gun";
|
||||||
|
case ITEM_SUBCLASS_WEAPON_BOW:
|
||||||
|
return "shoot bow";
|
||||||
|
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
|
||||||
|
return "shoot crossbow";
|
||||||
|
default:
|
||||||
|
return spellName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float PullStrategy::GetRange() const
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
std::string const spellName = GetSpellName();
|
||||||
|
if (bot && !spellName.empty())
|
||||||
|
{
|
||||||
|
uint32 const spellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", spellName)->Get();
|
||||||
|
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
|
||||||
|
return bot->GetSpellMaxRangeForTarget(GetTarget(), spellInfo) - CONTACT_DISTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (action == "shoot" ? botAI->GetRange("shoot") : botAI->GetRange("spell")) - CONTACT_DISTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PullStrategy::GetPreActionName() const
|
||||||
|
{
|
||||||
|
return preAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PullStrategy::CanDoPullAction(Unit* target)
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
if (!bot || !target)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!target->IsInWorld() || target->GetMapId() != bot->GetMapId())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (bot->getClass() != CLASS_DRUID && bot->getClass() != CLASS_PALADIN &&
|
||||||
|
GetPullActionName() == "shoot" && !bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string const spellName = GetSpellName();
|
||||||
|
if (spellName.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PullStrategy::RequestPull(Unit* target, bool resetTime)
|
||||||
|
{
|
||||||
|
SetTarget(target);
|
||||||
|
pendingToStart = true;
|
||||||
|
if (resetTime)
|
||||||
|
pullStartTime = time(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PullStrategy::OnPullStarted() { pendingToStart = false; }
|
||||||
|
|
||||||
|
void PullStrategy::OnPullEnded()
|
||||||
|
{
|
||||||
|
pullStartTime = 0;
|
||||||
|
pendingToStart = false;
|
||||||
|
SetTarget(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
PullMultiplier::PullMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "pull") {}
|
||||||
|
|
||||||
|
float PullMultiplier::GetValue(Action* action)
|
||||||
|
{
|
||||||
|
PullStrategy const* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy || !strategy->HasTarget() || !action)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
if (!strategy->IsPullPendingToStart() && !strategy->HasPullStarted())
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
std::string const actionName = action->getName();
|
||||||
|
if (actionName == "pull my target" ||
|
||||||
|
actionName == "pull rti target" ||
|
||||||
|
actionName == "reach pull" ||
|
||||||
|
actionName == "pull start" ||
|
||||||
|
actionName == "pull action" ||
|
||||||
|
actionName == "return to pull position" ||
|
||||||
|
actionName == "pull end" ||
|
||||||
|
actionName == "follow" ||
|
||||||
|
actionName == "set facing")
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
class MagePullMultiplier : public PassiveMultiplier
|
class MagePullMultiplier : public PassiveMultiplier
|
||||||
{
|
{
|
||||||
@ -24,8 +204,16 @@ float MagePullMultiplier::GetValue(Action* action)
|
|||||||
if (!action)
|
if (!action)
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
|
||||||
|
PullStrategy const* strategy = PullStrategy::Get(botAI);
|
||||||
|
if (!strategy || !strategy->HasTarget())
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
std::string const name = action->getName();
|
std::string const name = action->getName();
|
||||||
if (actionName == name || name == "reach spell" || name == "change strategy")
|
if (actionName == name || name == "pull action" || name == "pull start" || name == "pull end" ||
|
||||||
|
name == "pull my target" || name == "pull rti target" ||
|
||||||
|
name == "reach spell" || name == "reach pull" ||
|
||||||
|
name == "return to pull position" || name == "follow" ||
|
||||||
|
name == "set facing" || name == "change strategy")
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
|
||||||
return PassiveMultiplier::GetValue(action);
|
return PassiveMultiplier::GetValue(action);
|
||||||
@ -34,18 +222,32 @@ float MagePullMultiplier::GetValue(Action* action)
|
|||||||
std::vector<NextAction> PullStrategy::getDefaultActions()
|
std::vector<NextAction> PullStrategy::getDefaultActions()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
NextAction(action, 105.0f),
|
NextAction("pull action", 105.0f),
|
||||||
NextAction("follow", 104.0f),
|
|
||||||
NextAction("end pull", 103.0f),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void PullStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) { CombatStrategy::InitTriggers(triggers); }
|
void PullStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
|
{
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"pull start",
|
||||||
|
{
|
||||||
|
NextAction("pull start", 106.0f),
|
||||||
|
NextAction("pull action", ACTION_MOVE)
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"pull end",
|
||||||
|
{
|
||||||
|
NextAction("pull end", 107.0f)
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
void PullStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
void PullStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||||
{
|
{
|
||||||
|
multipliers.push_back(new PullMultiplier(botAI));
|
||||||
multipliers.push_back(new MagePullMultiplier(botAI, action));
|
multipliers.push_back(new MagePullMultiplier(botAI, action));
|
||||||
CombatStrategy::InitMultipliers(multipliers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PossibleAddsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void PossibleAddsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
@ -61,3 +263,15 @@ void PossibleAddsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PullBackStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
|
{
|
||||||
|
Strategy::InitTriggers(triggers);
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"return to pull position",
|
||||||
|
{
|
||||||
|
NextAction("return to pull position", ACTION_MOVE + 5.0f)
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|||||||
@ -6,22 +6,65 @@
|
|||||||
#ifndef _PLAYERBOT_PULLSTRATEGY_H
|
#ifndef _PLAYERBOT_PULLSTRATEGY_H
|
||||||
#define _PLAYERBOT_PULLSTRATEGY_H
|
#define _PLAYERBOT_PULLSTRATEGY_H
|
||||||
|
|
||||||
#include "CombatStrategy.h"
|
#include "Strategy.h"
|
||||||
|
|
||||||
|
class Action;
|
||||||
|
class Multiplier;
|
||||||
|
class Unit;
|
||||||
|
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
|
|
||||||
class PullStrategy : public CombatStrategy
|
class PullStrategy : public Strategy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PullStrategy(PlayerbotAI* botAI, std::string const action) : CombatStrategy(botAI), action(action) {}
|
PullStrategy(PlayerbotAI* botAI, std::string const action, std::string const preAction = "");
|
||||||
|
|
||||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||||
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
||||||
std::string const getName() override { return "pull"; }
|
std::string const getName() override { return "pull"; }
|
||||||
std::vector<NextAction> getDefaultActions() override;
|
std::vector<NextAction> getDefaultActions() override;
|
||||||
|
uint32 GetType() const override { return STRATEGY_TYPE_COMBAT | STRATEGY_TYPE_NONCOMBAT; }
|
||||||
|
|
||||||
|
static PullStrategy* Get(PlayerbotAI* botAI);
|
||||||
|
static uint8 GetMaxPullTime() { return 15; }
|
||||||
|
|
||||||
|
time_t GetPullStartTime() const { return pullStartTime; }
|
||||||
|
bool IsPullPendingToStart() const { return pendingToStart; }
|
||||||
|
bool HasPullStarted() const { return pullStartTime > 0; }
|
||||||
|
|
||||||
|
bool CanDoPullAction(Unit* target);
|
||||||
|
Unit* GetTarget() const;
|
||||||
|
bool HasTarget() const;
|
||||||
|
|
||||||
|
virtual std::string GetPullActionName() const;
|
||||||
|
std::string GetSpellName() const;
|
||||||
|
float GetRange() const;
|
||||||
|
virtual std::string GetPreActionName() const;
|
||||||
|
|
||||||
|
void RequestPull(Unit* target, bool resetTime = true);
|
||||||
|
void OnPullStarted();
|
||||||
|
void OnPullEnded();
|
||||||
|
|
||||||
|
ReactStates GetPetReactState() const { return petReactState; }
|
||||||
|
void SetPetReactState(ReactStates reactState) { petReactState = reactState; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetTarget(Unit* target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string const action;
|
std::string const action;
|
||||||
|
std::string const preAction;
|
||||||
|
bool pendingToStart = false;
|
||||||
|
time_t pullStartTime = 0;
|
||||||
|
ReactStates petReactState = REACT_DEFENSIVE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PullMultiplier : public Multiplier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullMultiplier(PlayerbotAI* botAI);
|
||||||
|
|
||||||
|
float GetValue(Action* action) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PossibleAddsStrategy : public Strategy
|
class PossibleAddsStrategy : public Strategy
|
||||||
@ -33,4 +76,13 @@ public:
|
|||||||
std::string const getName() override { return "adds"; }
|
std::string const getName() override { return "adds"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PullBackStrategy : public Strategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullBackStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||||
|
|
||||||
|
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||||
|
std::string const getName() override { return "pull back"; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,4 +7,4 @@
|
|||||||
|
|
||||||
RTSCStrategy::RTSCStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
RTSCStrategy::RTSCStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||||
|
|
||||||
void RTSCStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) {}
|
void RTSCStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/) {}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ public:
|
|||||||
RacialsStrategyActionNodeFactory() { creators["lifeblood"] = &lifeblood; }
|
RacialsStrategyActionNodeFactory() { creators["lifeblood"] = &lifeblood; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ActionNode* lifeblood(PlayerbotAI* botAI)
|
static ActionNode* lifeblood(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode("lifeblood",
|
return new ActionNode("lifeblood",
|
||||||
/*P*/ {},
|
/*P*/ {},
|
||||||
|
|||||||
@ -11,7 +11,7 @@ public:
|
|||||||
UsePotionsStrategyActionNodeFactory() { creators["healthstone"] = &healthstone; }
|
UsePotionsStrategyActionNodeFactory() { creators["healthstone"] = &healthstone; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ActionNode* healthstone(PlayerbotAI* botAI)
|
static ActionNode* healthstone(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode("healthstone",
|
return new ActionNode("healthstone",
|
||||||
/*P*/ {},
|
/*P*/ {},
|
||||||
|
|||||||
@ -82,6 +82,7 @@ float WaitForAttackMultiplier::GetValue(Action* action)
|
|||||||
actionName != "set facing" &&
|
actionName != "set facing" &&
|
||||||
actionName != "pull my target" &&
|
actionName != "pull my target" &&
|
||||||
actionName != "pull rti target" &&
|
actionName != "pull rti target" &&
|
||||||
|
actionName != "reach pull" &&
|
||||||
actionName != "pull start" &&
|
actionName != "pull start" &&
|
||||||
actionName != "pull action" &&
|
actionName != "pull action" &&
|
||||||
actionName != "pull end")
|
actionName != "pull end")
|
||||||
|
|||||||
@ -95,6 +95,7 @@ public:
|
|||||||
creators["sit"] = &StrategyContext::sit;
|
creators["sit"] = &StrategyContext::sit;
|
||||||
creators["mark rti"] = &StrategyContext::mark_rti;
|
creators["mark rti"] = &StrategyContext::mark_rti;
|
||||||
creators["adds"] = &StrategyContext::possible_adds;
|
creators["adds"] = &StrategyContext::possible_adds;
|
||||||
|
creators["pull back"] = &StrategyContext::pull_back;
|
||||||
creators["close"] = &StrategyContext::close;
|
creators["close"] = &StrategyContext::close;
|
||||||
creators["ranged"] = &StrategyContext::ranged;
|
creators["ranged"] = &StrategyContext::ranged;
|
||||||
creators["behind"] = &StrategyContext::behind;
|
creators["behind"] = &StrategyContext::behind;
|
||||||
@ -171,6 +172,7 @@ private:
|
|||||||
static Strategy* map_full(PlayerbotAI* botAI) { return new MapFullStrategy(botAI); }
|
static Strategy* map_full(PlayerbotAI* botAI) { return new MapFullStrategy(botAI); }
|
||||||
static Strategy* sit(PlayerbotAI* botAI) { return new SitStrategy(botAI); }
|
static Strategy* sit(PlayerbotAI* botAI) { return new SitStrategy(botAI); }
|
||||||
static Strategy* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsStrategy(botAI); }
|
static Strategy* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsStrategy(botAI); }
|
||||||
|
static Strategy* pull_back(PlayerbotAI* botAI) { return new PullBackStrategy(botAI); }
|
||||||
static Strategy* mount(PlayerbotAI* botAI) { return new MountStrategy(botAI); }
|
static Strategy* mount(PlayerbotAI* botAI) { return new MountStrategy(botAI); }
|
||||||
static Strategy* bg(PlayerbotAI* botAI) { return new BGStrategy(botAI); }
|
static Strategy* bg(PlayerbotAI* botAI) { return new BGStrategy(botAI); }
|
||||||
static Strategy* battleground(PlayerbotAI* botAI) { return new BattlegroundStrategy(botAI); }
|
static Strategy* battleground(PlayerbotAI* botAI) { return new BattlegroundStrategy(botAI); }
|
||||||
|
|||||||
62
src/Ai/Base/Trigger/PullTriggers.cpp
Normal file
62
src/Ai/Base/Trigger/PullTriggers.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PullTriggers.h"
|
||||||
|
|
||||||
|
#include "PositionValue.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
#include "PullStrategy.h"
|
||||||
|
|
||||||
|
bool PullStartTrigger::IsActive()
|
||||||
|
{
|
||||||
|
PullStrategy const* strategy = PullStrategy::Get(botAI);
|
||||||
|
return strategy && strategy->IsPullPendingToStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PullEndTrigger::IsActive()
|
||||||
|
{
|
||||||
|
PullStrategy const* strategy = PullStrategy::Get(botAI);
|
||||||
|
|
||||||
|
if (!strategy || !strategy->HasPullStarted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Unit* target = strategy->GetTarget();
|
||||||
|
if (!target || !target->IsInWorld() || !target->IsAlive())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
time_t const secondsSincePullStarted = time(nullptr) - strategy->GetPullStartTime();
|
||||||
|
if (secondsSincePullStarted >= PullStrategy::GetMaxPullTime())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
float distanceToPullTarget = bot->GetDistance(target);
|
||||||
|
if (distanceToPullTarget > ATTACK_DISTANCE && !target->IsNonMeleeSpellCast(false, false, true) &&
|
||||||
|
(!botAI->IsRanged(bot) || distanceToPullTarget > botAI->GetRange("spell")))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!botAI->HasStrategy("pull back", BOT_STATE_COMBAT))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
PositionInfo pullPosition = AI_VALUE(PositionMap&, "position")["pull"];
|
||||||
|
if (!pullPosition.isSet() || pullPosition.mapId != bot->GetMapId())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return bot->GetDistance(pullPosition.x, pullPosition.y, pullPosition.z) <= botAI->GetRange("follow");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReturnToPullPositionTrigger::IsActive()
|
||||||
|
{
|
||||||
|
PullStrategy const* strategy = PullStrategy::Get(botAI);
|
||||||
|
|
||||||
|
Unit* target = strategy ? strategy->GetTarget() : nullptr;
|
||||||
|
if (!strategy || !strategy->HasPullStarted() || !target || !target->IsInCombat() ||
|
||||||
|
!botAI->HasStrategy("pull back", BOT_STATE_COMBAT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PositionInfo pullPosition = AI_VALUE(PositionMap&, "position")["pull"];
|
||||||
|
return pullPosition.isSet() && pullPosition.mapId == bot->GetMapId() &&
|
||||||
|
bot->GetDistance(pullPosition.x, pullPosition.y, pullPosition.z) > sPlayerbotAIConfig.followDistance;
|
||||||
|
}
|
||||||
35
src/Ai/Base/Trigger/PullTriggers.h
Normal file
35
src/Ai/Base/Trigger/PullTriggers.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAYERBOT_PULLTRIGGERS_H
|
||||||
|
#define _PLAYERBOT_PULLTRIGGERS_H
|
||||||
|
|
||||||
|
#include "Trigger.h"
|
||||||
|
|
||||||
|
class PullStartTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullStartTrigger(PlayerbotAI* botAI, std::string const name = "pull start") : Trigger(botAI, name) {}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PullEndTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullEndTrigger(PlayerbotAI* botAI, std::string const name = "pull end") : Trigger(botAI, name) {}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReturnToPullPositionTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReturnToPullPositionTrigger(PlayerbotAI* botAI) : Trigger(botAI, "return to pull position") {}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#include "NewRpgStrategy.h"
|
#include "NewRpgStrategy.h"
|
||||||
#include "NewRpgTriggers.h"
|
#include "NewRpgTriggers.h"
|
||||||
#include "PvpTriggers.h"
|
#include "PvpTriggers.h"
|
||||||
|
#include "PullTriggers.h"
|
||||||
#include "RpgTriggers.h"
|
#include "RpgTriggers.h"
|
||||||
#include "RtiTriggers.h"
|
#include "RtiTriggers.h"
|
||||||
#include "StuckTriggers.h"
|
#include "StuckTriggers.h"
|
||||||
@ -129,6 +130,9 @@ public:
|
|||||||
creators["has attackers"] = &TriggerContext::has_attackers;
|
creators["has attackers"] = &TriggerContext::has_attackers;
|
||||||
creators["no possible targets"] = &TriggerContext::no_possible_targets;
|
creators["no possible targets"] = &TriggerContext::no_possible_targets;
|
||||||
creators["possible adds"] = &TriggerContext::possible_adds;
|
creators["possible adds"] = &TriggerContext::possible_adds;
|
||||||
|
creators["pull start"] = &TriggerContext::pull_start;
|
||||||
|
creators["pull end"] = &TriggerContext::pull_end;
|
||||||
|
creators["return to pull position"] = &TriggerContext::return_to_pull_position;
|
||||||
|
|
||||||
creators["no drink"] = &TriggerContext::no_drink;
|
creators["no drink"] = &TriggerContext::no_drink;
|
||||||
creators["no food"] = &TriggerContext::no_food;
|
creators["no food"] = &TriggerContext::no_food;
|
||||||
@ -280,6 +284,9 @@ private:
|
|||||||
static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); }
|
static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); }
|
||||||
static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); }
|
static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); }
|
||||||
static Trigger* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsTrigger(botAI); }
|
static Trigger* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsTrigger(botAI); }
|
||||||
|
static Trigger* pull_start(PlayerbotAI* botAI) { return new PullStartTrigger(botAI); }
|
||||||
|
static Trigger* pull_end(PlayerbotAI* botAI) { return new PullEndTrigger(botAI); }
|
||||||
|
static Trigger* return_to_pull_position(PlayerbotAI* botAI) { return new ReturnToPullPositionTrigger(botAI); }
|
||||||
static Trigger* can_loot(PlayerbotAI* botAI) { return new CanLootTrigger(botAI); }
|
static Trigger* can_loot(PlayerbotAI* botAI) { return new CanLootTrigger(botAI); }
|
||||||
static Trigger* far_from_loot_target(PlayerbotAI* botAI) { return new FarFromCurrentLootTrigger(botAI); }
|
static Trigger* far_from_loot_target(PlayerbotAI* botAI) { return new FarFromCurrentLootTrigger(botAI); }
|
||||||
static Trigger* far_from_master(PlayerbotAI* botAI) { return new FarFromMasterTrigger(botAI); }
|
static Trigger* far_from_master(PlayerbotAI* botAI) { return new FarFromMasterTrigger(botAI); }
|
||||||
|
|||||||
@ -19,6 +19,7 @@ WorldLocation ArrowFormation::GetLocationInternal()
|
|||||||
uint32 tankLines = 1 + tanks.Size() / 6;
|
uint32 tankLines = 1 + tanks.Size() / 6;
|
||||||
uint32 meleeLines = 1 + melee.Size() / 6;
|
uint32 meleeLines = 1 + melee.Size() / 6;
|
||||||
uint32 rangedLines = 1 + ranged.Size() / 6;
|
uint32 rangedLines = 1 + ranged.Size() / 6;
|
||||||
|
//TODO Implement Healer Lines
|
||||||
uint32 healerLines = 1 + healers.Size() / 6;
|
uint32 healerLines = 1 + healers.Size() / 6;
|
||||||
float offset = 0.f;
|
float offset = 0.f;
|
||||||
|
|
||||||
@ -147,7 +148,7 @@ UnitPosition MultiLineUnitPlacer::Place(FormationUnit* unit, uint32 index, uint3
|
|||||||
return placer.Place(unit, indexInLine, lineSize);
|
return placer.Place(unit, indexInLine, lineSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnitPosition SingleLineUnitPlacer::Place(FormationUnit* unit, uint32 index, uint32 count)
|
UnitPosition SingleLineUnitPlacer::Place(FormationUnit* /*unit*/, uint32 index, uint32 count)
|
||||||
{
|
{
|
||||||
float angle = orientation - M_PI / 2.0f;
|
float angle = orientation - M_PI / 2.0f;
|
||||||
float x = cos(angle) * sPlayerbotAIConfig.followDistance * ((float)index - (float)count / 2);
|
float x = cos(angle) * sPlayerbotAIConfig.followDistance * ((float)index - (float)count / 2);
|
||||||
|
|||||||
@ -20,7 +20,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void CheckAttacker(Unit* creature, ThreatManager* threatMgr) override
|
void CheckAttacker(Unit* creature, ThreatManager* /*threatMgr*/) override
|
||||||
{
|
{
|
||||||
Player* bot = botAI->GetBot();
|
Player* bot = botAI->GetBot();
|
||||||
if (!botAI->CanCastSpell(spell, creature))
|
if (!botAI->CanCastSpell(spell, creature))
|
||||||
|
|||||||
@ -13,7 +13,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckAttacker(Unit* attacker, ThreatManager* threatMgr) override
|
void CheckAttacker(Unit* attacker, ThreatManager* /*threatMgr*/) override
|
||||||
{
|
{
|
||||||
if (botAI->HasAura(spell, attacker))
|
if (botAI->HasAura(spell, attacker))
|
||||||
result = attacker;
|
result = attacker;
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public:
|
|||||||
result = nullptr;
|
result = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckAttacker(Unit* attacker, ThreatManager* threatMgr) override
|
void CheckAttacker(Unit* attacker, ThreatManager* /*threatMgr*/) override
|
||||||
{
|
{
|
||||||
if (Group* group = botAI->GetBot()->GetGroup())
|
if (Group* group = botAI->GetBot()->GetGroup())
|
||||||
{
|
{
|
||||||
|
|||||||
@ -11,8 +11,6 @@ std::vector<Item*> InventoryItemValueBase::Find(std::string const qualifier)
|
|||||||
{
|
{
|
||||||
std::vector<Item*> result;
|
std::vector<Item*> result;
|
||||||
|
|
||||||
Player* bot = InventoryAction::botAI->GetBot();
|
|
||||||
|
|
||||||
std::vector<Item*> items = InventoryAction::parseItems(qualifier);
|
std::vector<Item*> items = InventoryAction::parseItems(qualifier);
|
||||||
for (Item* item : items)
|
for (Item* item : items)
|
||||||
result.push_back(item);
|
result.push_back(item);
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class InventoryItemValueBase : public InventoryAction
|
|||||||
public:
|
public:
|
||||||
InventoryItemValueBase(PlayerbotAI* botAI) : InventoryAction(botAI, "empty") {}
|
InventoryItemValueBase(PlayerbotAI* botAI) : InventoryAction(botAI, "empty") {}
|
||||||
|
|
||||||
bool Execute(Event event) override { return false; }
|
bool Execute(Event /*event*/) override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<Item*> Find(std::string const qualifier);
|
std::vector<Item*> Find(std::string const qualifier);
|
||||||
|
|||||||
@ -48,23 +48,6 @@ Item* ItemForSpellValue::Calculate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround as some spells have no item mask (e.g. shaman weapon enhancements)
|
|
||||||
if (!strcmpi(spellInfo->SpellName[0], "rockbiter weapon") ||
|
|
||||||
!strcmpi(spellInfo->SpellName[0], "flametongue weapon") ||
|
|
||||||
!strcmpi(spellInfo->SpellName[0], "earthliving weapon") ||
|
|
||||||
!strcmpi(spellInfo->SpellName[0], "frostbrand weapon") || !strcmpi(spellInfo->SpellName[0], "windfury weapon"))
|
|
||||||
{
|
|
||||||
itemForSpell = GetItemFitsToSpellRequirements(EQUIPMENT_SLOT_MAINHAND, spellInfo);
|
|
||||||
if (itemForSpell && itemForSpell->GetTemplate()->Class == ITEM_CLASS_WEAPON)
|
|
||||||
return itemForSpell;
|
|
||||||
|
|
||||||
itemForSpell = GetItemFitsToSpellRequirements(EQUIPMENT_SLOT_OFFHAND, spellInfo);
|
|
||||||
if (itemForSpell && itemForSpell->GetTemplate()->Class == ITEM_CLASS_WEAPON)
|
|
||||||
return itemForSpell;
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(spellInfo->Targets & TARGET_FLAG_ITEM))
|
if (!(spellInfo->Targets & TARGET_FLAG_ITEM))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|||||||
@ -234,6 +234,11 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto,
|
|||||||
calculator.SetItemSetBonus(false);
|
calculator.SetItemSetBonus(false);
|
||||||
calculator.SetOverflowPenalty(false);
|
calculator.SetOverflowPenalty(false);
|
||||||
|
|
||||||
|
// Apply PvP weights if the bot is specced for PvP
|
||||||
|
bool isPvp = sRandomPlayerbotMgr.IsSpecPvp(bot->GetGUID().GetCounter(), bot->getClass());
|
||||||
|
if (isPvp)
|
||||||
|
calculator.SetPvpSpec(true);
|
||||||
|
|
||||||
float itemScore = calculator.CalculateItem(itemProto->ItemId, randomPropertyId);
|
float itemScore = calculator.CalculateItem(itemProto->ItemId, randomPropertyId);
|
||||||
|
|
||||||
if (itemScore)
|
if (itemScore)
|
||||||
@ -864,8 +869,6 @@ bool ItemUsageValue::SpellGivesSkillUp(uint32 spellId, Player* bot)
|
|||||||
{
|
{
|
||||||
uint32 SkillValue = bot->GetPureSkillValue(skill->SkillLine);
|
uint32 SkillValue = bot->GetPureSkillValue(skill->SkillLine);
|
||||||
|
|
||||||
uint32 craft_skill_gain = sWorld->getIntConfig(CONFIG_SKILL_GAIN_CRAFTING);
|
|
||||||
|
|
||||||
if (SkillGainChance(SkillValue, skill->TrivialSkillLineRankHigh,
|
if (SkillGainChance(SkillValue, skill->TrivialSkillLineRankHigh,
|
||||||
(skill->TrivialSkillLineRankHigh + skill->TrivialSkillLineRankLow) / 2,
|
(skill->TrivialSkillLineRankHigh + skill->TrivialSkillLineRankLow) / 2,
|
||||||
skill->TrivialSkillLineRankLow) > 0)
|
skill->TrivialSkillLineRankLow) > 0)
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class FindLeastHpTargetStrategy : public FindNonCcTargetStrategy
|
|||||||
public:
|
public:
|
||||||
FindLeastHpTargetStrategy(PlayerbotAI* botAI) : FindNonCcTargetStrategy(botAI), minHealth(0) {}
|
FindLeastHpTargetStrategy(PlayerbotAI* botAI) : FindNonCcTargetStrategy(botAI), minHealth(0) {}
|
||||||
|
|
||||||
void CheckAttacker(Unit* attacker, ThreatManager* threatMgr) override
|
void CheckAttacker(Unit* attacker, ThreatManager* /*threatMgr*/) override
|
||||||
{
|
{
|
||||||
if (IsCcTarget(attacker))
|
if (IsCcTarget(attacker))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -60,7 +60,7 @@ public:
|
|||||||
class AllLootStrategy : public LootStrategy
|
class AllLootStrategy : public LootStrategy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool CanLoot(ItemTemplate const* proto, AiObjectContext* context) override { return true; }
|
bool CanLoot(ItemTemplate const* /*proto*/, AiObjectContext* /*context*/) override { return true; }
|
||||||
|
|
||||||
std::string const GetName() override { return "all"; }
|
std::string const GetName() override { return "all"; }
|
||||||
};
|
};
|
||||||
|
|||||||
@ -28,4 +28,4 @@ void NearestCorpsesValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
Cell::VisitObjects(bot, searcher, range);
|
Cell::VisitObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestCorpsesValue::AcceptUnit(Unit* unit) { return true; }
|
bool NearestCorpsesValue::AcceptUnit(Unit* /*unit*/) { return true; }
|
||||||
|
|||||||
@ -27,7 +27,7 @@ Unit* PartyMemberValue::FindPartyMember(std::vector<Player*>* party, FindPlayerP
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ignoreOutOfGroup)
|
Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool /*ignoreOutOfGroup*/)
|
||||||
{
|
{
|
||||||
Player* master = GetMaster();
|
Player* master = GetMaster();
|
||||||
// GuidVector nearestPlayers;
|
// GuidVector nearestPlayers;
|
||||||
|
|||||||
@ -40,13 +40,13 @@ bool SpellCastUsefulValue::Calculate()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: workaround
|
if (qualifier == "windfury weapon" || qualifier == "flametongue weapon" ||
|
||||||
if (qualifier == "windfury weapon" || qualifier == "flametongue weapon" || qualifier == "frostbrand weapon" ||
|
qualifier == "frostbrand weapon" || qualifier == "rockbiter weapon" ||
|
||||||
qualifier == "rockbiter weapon" || qualifier == "earthliving weapon" || qualifier == "spellstone")
|
qualifier == "earthliving weapon" || qualifier == "spellstone")
|
||||||
{
|
{
|
||||||
if (Item* item = AI_VALUE2(Item*, "item for spell", spellid))
|
if (Item* item = AI_VALUE2(Item*, "item for spell", spellid);
|
||||||
if (item->IsInWorld() && item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT))
|
item && item->IsInWorld() && item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<uint32>& skipSpells = AI_VALUE(std::set<uint32>&, "skip spells list");
|
std::set<uint32>& skipSpells = AI_VALUE(std::set<uint32>&, "skip spells list");
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class FindTankTargetSmartStrategy : public FindTargetStrategy
|
|||||||
public:
|
public:
|
||||||
FindTankTargetSmartStrategy(PlayerbotAI* botAI) : FindTargetStrategy(botAI) {}
|
FindTankTargetSmartStrategy(PlayerbotAI* botAI) : FindTargetStrategy(botAI) {}
|
||||||
|
|
||||||
void CheckAttacker(Unit* attacker, ThreatManager* threatMgr) override
|
void CheckAttacker(Unit* attacker, ThreatManager* /*threatMgr*/) override
|
||||||
{
|
{
|
||||||
if (Group* group = botAI->GetBot()->GetGroup())
|
if (Group* group = botAI->GetBot()->GetGroup())
|
||||||
{
|
{
|
||||||
|
|||||||
@ -161,7 +161,7 @@ Unit* FindTargetValue::Calculate()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindBossTargetStrategy::CheckAttacker(Unit* attacker, ThreatManager* threatManager)
|
void FindBossTargetStrategy::CheckAttacker(Unit* attacker, ThreatManager* /*threatManager*/)
|
||||||
{
|
{
|
||||||
UnitAI* unitAI = attacker->GetAI();
|
UnitAI* unitAI = attacker->GetAI();
|
||||||
BossAI* bossAI = dynamic_cast<BossAI*>(unitAI);
|
BossAI* bossAI = dynamic_cast<BossAI*>(unitAI);
|
||||||
|
|||||||
@ -116,6 +116,15 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PullStrategyTargetValue : public ManualSetValue<ObjectGuid>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PullStrategyTargetValue(PlayerbotAI* botAI, std::string const name = "pull strategy target")
|
||||||
|
: ManualSetValue<ObjectGuid>(botAI, ObjectGuid::Empty, name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class FindTargetValue : public UnitCalculatedValue, public Qualified
|
class FindTargetValue : public UnitCalculatedValue, public Qualified
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -241,6 +241,7 @@ public:
|
|||||||
creators["travel target"] = &ValueContext::travel_target;
|
creators["travel target"] = &ValueContext::travel_target;
|
||||||
creators["talk target"] = &ValueContext::talk_target;
|
creators["talk target"] = &ValueContext::talk_target;
|
||||||
creators["pull target"] = &ValueContext::pull_target;
|
creators["pull target"] = &ValueContext::pull_target;
|
||||||
|
creators["pull strategy target"] = &ValueContext::pull_strategy_target;
|
||||||
creators["focus heal targets"] = &ValueContext::focus_heal_targets;
|
creators["focus heal targets"] = &ValueContext::focus_heal_targets;
|
||||||
creators["group"] = &ValueContext::group;
|
creators["group"] = &ValueContext::group;
|
||||||
creators["range"] = &ValueContext::range;
|
creators["range"] = &ValueContext::range;
|
||||||
@ -498,6 +499,7 @@ private:
|
|||||||
static UntypedValue* next_rpg_action(PlayerbotAI* botAI) { return new NextRpgActionValue(botAI); }
|
static UntypedValue* next_rpg_action(PlayerbotAI* botAI) { return new NextRpgActionValue(botAI); }
|
||||||
static UntypedValue* travel_target(PlayerbotAI* botAI) { return new TravelTargetValue(botAI); }
|
static UntypedValue* travel_target(PlayerbotAI* botAI) { return new TravelTargetValue(botAI); }
|
||||||
static UntypedValue* pull_target(PlayerbotAI* botAI) { return new PullTargetValue(botAI); }
|
static UntypedValue* pull_target(PlayerbotAI* botAI) { return new PullTargetValue(botAI); }
|
||||||
|
static UntypedValue* pull_strategy_target(PlayerbotAI* botAI) { return new PullStrategyTargetValue(botAI); }
|
||||||
static UntypedValue* focus_heal_targets(PlayerbotAI* botAI) { return new FocusHealTargetValue(botAI); }
|
static UntypedValue* focus_heal_targets(PlayerbotAI* botAI) { return new FocusHealTargetValue(botAI); }
|
||||||
|
|
||||||
static UntypedValue* bg_master(PlayerbotAI* botAI) { return new BgMasterValue(botAI); }
|
static UntypedValue* bg_master(PlayerbotAI* botAI) { return new BgMasterValue(botAI); }
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
#include "BloodDKStrategy.h"
|
#include "BloodDKStrategy.h"
|
||||||
#include "DKActions.h"
|
#include "DKActions.h"
|
||||||
#include "DKTriggers.h"
|
#include "DKTriggers.h"
|
||||||
|
#include "DeathKnightPullStrategy.h"
|
||||||
#include "FrostDKStrategy.h"
|
#include "FrostDKStrategy.h"
|
||||||
#include "GenericDKNonCombatStrategy.h"
|
#include "GenericDKNonCombatStrategy.h"
|
||||||
#include "GenericTriggers.h"
|
#include "GenericTriggers.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "PullStrategy.h"
|
|
||||||
#include "UnholyDKStrategy.h"
|
#include "UnholyDKStrategy.h"
|
||||||
|
|
||||||
class DeathKnightStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
class DeathKnightStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||||
@ -28,7 +28,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static Strategy* nc(PlayerbotAI* botAI) { return new GenericDKNonCombatStrategy(botAI); }
|
static Strategy* nc(PlayerbotAI* botAI) { return new GenericDKNonCombatStrategy(botAI); }
|
||||||
static Strategy* pull(PlayerbotAI* botAI) { return new PullStrategy(botAI, "icy touch"); }
|
static Strategy* pull(PlayerbotAI* botAI) { return new DeathKnightPullStrategy(botAI); }
|
||||||
static Strategy* frost_aoe(PlayerbotAI* botAI) { return new FrostDKAoeStrategy(botAI); }
|
static Strategy* frost_aoe(PlayerbotAI* botAI) { return new FrostDKAoeStrategy(botAI); }
|
||||||
static Strategy* unholy_aoe(PlayerbotAI* botAI) { return new UnholyDKAoeStrategy(botAI); }
|
static Strategy* unholy_aoe(PlayerbotAI* botAI) { return new UnholyDKAoeStrategy(botAI); }
|
||||||
};
|
};
|
||||||
|
|||||||
43
src/Ai/Class/Dk/Strategy/DeathKnightPullStrategy.cpp
Normal file
43
src/Ai/Class/Dk/Strategy/DeathKnightPullStrategy.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DeathKnightPullStrategy.h"
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
|
||||||
|
std::string DeathKnightPullStrategy::GetPullActionName() const
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
Unit* target = GetTarget();
|
||||||
|
if (!bot || !target ||
|
||||||
|
(!botAI->HasStrategy("blood", BOT_STATE_COMBAT) && !botAI->HasStrategy("blood", BOT_STATE_NON_COMBAT)))
|
||||||
|
{
|
||||||
|
return PullStrategy::GetPullActionName();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 const deathGripSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "death grip")->Get();
|
||||||
|
if (deathGripSpellId && bot->HasSpell(deathGripSpellId) &&
|
||||||
|
botAI->CanCastSpell(deathGripSpellId, target))
|
||||||
|
{
|
||||||
|
return "death grip";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 const icyTouchSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "icy touch")->Get();
|
||||||
|
if (!icyTouchSpellId || !bot->HasSpell(icyTouchSpellId) ||
|
||||||
|
!botAI->CanCastSpell(icyTouchSpellId, target))
|
||||||
|
{
|
||||||
|
uint32 const darkCommandSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "dark command")->Get();
|
||||||
|
if (darkCommandSpellId && bot->HasSpell(darkCommandSpellId) &&
|
||||||
|
botAI->CanCastSpell(darkCommandSpellId, target))
|
||||||
|
{
|
||||||
|
return "dark command";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PullStrategy::GetPullActionName();
|
||||||
|
}
|
||||||
19
src/Ai/Class/Dk/Strategy/DeathKnightPullStrategy.h
Normal file
19
src/Ai/Class/Dk/Strategy/DeathKnightPullStrategy.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAYERBOT_DEATH_KNIGHT_PULL_STRATEGY_H
|
||||||
|
#define _PLAYERBOT_DEATH_KNIGHT_PULL_STRATEGY_H
|
||||||
|
|
||||||
|
#include "PullStrategy.h"
|
||||||
|
|
||||||
|
class DeathKnightPullStrategy : public PullStrategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DeathKnightPullStrategy(PlayerbotAI* botAI) : PullStrategy(botAI, "icy touch") {}
|
||||||
|
|
||||||
|
std::string GetPullActionName() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -47,7 +47,7 @@ void GenericDKNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
|||||||
new TriggerNode("bone shield", { NextAction("bone shield", 21.0f) }));
|
new TriggerNode("bone shield", { NextAction("bone shield", 21.0f) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DKBuffDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void DKBuffDpsStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "MeleeDruidStrategy.h"
|
#include "MeleeDruidStrategy.h"
|
||||||
#include "OffhealDruidCatStrategy.h"
|
#include "OffhealDruidCatStrategy.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
#include "DruidPullStrategy.h"
|
||||||
|
|
||||||
class DruidStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
class DruidStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||||
{
|
{
|
||||||
@ -26,6 +27,7 @@ public:
|
|||||||
DruidStrategyFactoryInternal()
|
DruidStrategyFactoryInternal()
|
||||||
{
|
{
|
||||||
creators["nc"] = &DruidStrategyFactoryInternal::nc;
|
creators["nc"] = &DruidStrategyFactoryInternal::nc;
|
||||||
|
creators["pull"] = &DruidStrategyFactoryInternal::pull;
|
||||||
creators["cat aoe"] = &DruidStrategyFactoryInternal::cat_aoe;
|
creators["cat aoe"] = &DruidStrategyFactoryInternal::cat_aoe;
|
||||||
creators["caster aoe"] = &DruidStrategyFactoryInternal::caster_aoe;
|
creators["caster aoe"] = &DruidStrategyFactoryInternal::caster_aoe;
|
||||||
creators["caster debuff"] = &DruidStrategyFactoryInternal::caster_debuff;
|
creators["caster debuff"] = &DruidStrategyFactoryInternal::caster_debuff;
|
||||||
@ -40,6 +42,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static Strategy* nc(PlayerbotAI* botAI) { return new GenericDruidNonCombatStrategy(botAI); }
|
static Strategy* nc(PlayerbotAI* botAI) { return new GenericDruidNonCombatStrategy(botAI); }
|
||||||
|
static Strategy* pull(PlayerbotAI* botAI) { return new DruidPullStrategy(botAI); }
|
||||||
static Strategy* cat_aoe(PlayerbotAI* botAI) { return new CatAoeDruidStrategy(botAI); }
|
static Strategy* cat_aoe(PlayerbotAI* botAI) { return new CatAoeDruidStrategy(botAI); }
|
||||||
static Strategy* caster_aoe(PlayerbotAI* botAI) { return new CasterDruidAoeStrategy(botAI); }
|
static Strategy* caster_aoe(PlayerbotAI* botAI) { return new CasterDruidAoeStrategy(botAI); }
|
||||||
static Strategy* caster_debuff(PlayerbotAI* botAI) { return new CasterDruidDebuffStrategy(botAI); }
|
static Strategy* caster_debuff(PlayerbotAI* botAI) { return new CasterDruidDebuffStrategy(botAI); }
|
||||||
|
|||||||
@ -311,4 +311,4 @@ void CatDpsDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CatAoeDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) {}
|
void CatAoeDruidStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/) {}
|
||||||
|
|||||||
46
src/Ai/Class/Druid/Strategy/DruidPullStrategy.cpp
Normal file
46
src/Ai/Class/Druid/Strategy/DruidPullStrategy.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DruidPullStrategy.h"
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
|
||||||
|
std::string DruidPullStrategy::GetPullActionName() const
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
std::string actionName = PullStrategy::GetPullActionName();
|
||||||
|
if (!bot)
|
||||||
|
return actionName;
|
||||||
|
|
||||||
|
uint32 const faerieFireFeralId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "faerie fire (feral)")->Get();
|
||||||
|
if (faerieFireFeralId && bot->HasSpell(faerieFireFeralId) &&
|
||||||
|
(botAI->HasStrategy("bear", BOT_STATE_COMBAT) || botAI->HasStrategy("cat", BOT_STATE_COMBAT)))
|
||||||
|
{
|
||||||
|
actionName = "faerie fire (feral)";
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit* target = GetTarget();
|
||||||
|
uint32 const faerieFireSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", actionName)->Get();
|
||||||
|
if (target && (!faerieFireSpellId || !bot->HasSpell(faerieFireSpellId) ||
|
||||||
|
!botAI->CanCastSpell(faerieFireSpellId, target)))
|
||||||
|
{
|
||||||
|
uint32 const growlSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "growl")->Get();
|
||||||
|
if (growlSpellId && bot->HasSpell(growlSpellId) && botAI->CanCastSpell(growlSpellId, target))
|
||||||
|
return "growl";
|
||||||
|
}
|
||||||
|
|
||||||
|
return actionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DruidPullStrategy::GetPreActionName() const
|
||||||
|
{
|
||||||
|
if (GetPullActionName() == "faerie fire")
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return PullStrategy::GetPreActionName();
|
||||||
|
}
|
||||||
20
src/Ai/Class/Druid/Strategy/DruidPullStrategy.h
Normal file
20
src/Ai/Class/Druid/Strategy/DruidPullStrategy.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAYERBOT_DRUID_PULL_STRATEGY_H
|
||||||
|
#define _PLAYERBOT_DRUID_PULL_STRATEGY_H
|
||||||
|
|
||||||
|
#include "PullStrategy.h"
|
||||||
|
|
||||||
|
class DruidPullStrategy : public PullStrategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DruidPullStrategy(PlayerbotAI* botAI) : PullStrategy(botAI, "faerie fire", "dire bear form") {}
|
||||||
|
|
||||||
|
std::string GetPullActionName() const override;
|
||||||
|
std::string GetPreActionName() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -392,7 +392,7 @@ class CastExplosiveShotRank4Action : public CastExplosiveShotBaseAction
|
|||||||
public:
|
public:
|
||||||
CastExplosiveShotRank4Action(PlayerbotAI* botAI) :
|
CastExplosiveShotRank4Action(PlayerbotAI* botAI) :
|
||||||
CastExplosiveShotBaseAction(botAI) {}
|
CastExplosiveShotBaseAction(botAI) {}
|
||||||
bool Execute(Event event) override
|
bool Execute(Event /*event*/) override
|
||||||
{
|
{
|
||||||
return botAI->CastSpell(60053, GetTarget());
|
return botAI->CastSpell(60053, GetTarget());
|
||||||
}
|
}
|
||||||
@ -412,7 +412,7 @@ class CastExplosiveShotRank3Action : public CastExplosiveShotBaseAction
|
|||||||
public:
|
public:
|
||||||
CastExplosiveShotRank3Action(PlayerbotAI* botAI) :
|
CastExplosiveShotRank3Action(PlayerbotAI* botAI) :
|
||||||
CastExplosiveShotBaseAction(botAI) {}
|
CastExplosiveShotBaseAction(botAI) {}
|
||||||
bool Execute(Event event) override
|
bool Execute(Event /*event*/) override
|
||||||
{
|
{
|
||||||
return botAI->CastSpell(60052, GetTarget());
|
return botAI->CastSpell(60052, GetTarget());
|
||||||
}
|
}
|
||||||
@ -432,7 +432,7 @@ class CastExplosiveShotRank2Action : public CastExplosiveShotBaseAction
|
|||||||
public:
|
public:
|
||||||
CastExplosiveShotRank2Action(PlayerbotAI* botAI) :
|
CastExplosiveShotRank2Action(PlayerbotAI* botAI) :
|
||||||
CastExplosiveShotBaseAction(botAI) {}
|
CastExplosiveShotBaseAction(botAI) {}
|
||||||
bool Execute(Event event) override
|
bool Execute(Event /*event*/) override
|
||||||
{
|
{
|
||||||
return botAI->CastSpell(60051, GetTarget());
|
return botAI->CastSpell(60051, GetTarget());
|
||||||
}
|
}
|
||||||
@ -452,7 +452,7 @@ class CastExplosiveShotRank1Action : public CastExplosiveShotBaseAction
|
|||||||
public:
|
public:
|
||||||
CastExplosiveShotRank1Action(PlayerbotAI* botAI) :
|
CastExplosiveShotRank1Action(PlayerbotAI* botAI) :
|
||||||
CastExplosiveShotBaseAction(botAI) {}
|
CastExplosiveShotBaseAction(botAI) {}
|
||||||
bool Execute(Event event) override
|
bool Execute(Event /*event*/) override
|
||||||
{
|
{
|
||||||
return botAI->CastSpell(53301, GetTarget());
|
return botAI->CastSpell(53301, GetTarget());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "OffhealRetPaladinStrategy.h"
|
#include "OffhealRetPaladinStrategy.h"
|
||||||
#include "PaladinActions.h"
|
#include "PaladinActions.h"
|
||||||
#include "PaladinBuffStrategies.h"
|
#include "PaladinBuffStrategies.h"
|
||||||
|
#include "PaladinPullStrategy.h"
|
||||||
#include "PaladinTriggers.h"
|
#include "PaladinTriggers.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "TankPaladinStrategy.h"
|
#include "TankPaladinStrategy.h"
|
||||||
@ -22,6 +23,7 @@ public:
|
|||||||
PaladinStrategyFactoryInternal()
|
PaladinStrategyFactoryInternal()
|
||||||
{
|
{
|
||||||
creators["nc"] = &PaladinStrategyFactoryInternal::nc;
|
creators["nc"] = &PaladinStrategyFactoryInternal::nc;
|
||||||
|
creators["pull"] = &PaladinStrategyFactoryInternal::pull;
|
||||||
creators["cure"] = &PaladinStrategyFactoryInternal::cure;
|
creators["cure"] = &PaladinStrategyFactoryInternal::cure;
|
||||||
creators["boost"] = &PaladinStrategyFactoryInternal::boost;
|
creators["boost"] = &PaladinStrategyFactoryInternal::boost;
|
||||||
creators["cc"] = &PaladinStrategyFactoryInternal::cc;
|
creators["cc"] = &PaladinStrategyFactoryInternal::cc;
|
||||||
@ -31,6 +33,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static Strategy* nc(PlayerbotAI* botAI) { return new GenericPaladinNonCombatStrategy(botAI); }
|
static Strategy* nc(PlayerbotAI* botAI) { return new GenericPaladinNonCombatStrategy(botAI); }
|
||||||
|
static Strategy* pull(PlayerbotAI* botAI) { return new PaladinPullStrategy(botAI); }
|
||||||
static Strategy* cure(PlayerbotAI* botAI) { return new PaladinCureStrategy(botAI); }
|
static Strategy* cure(PlayerbotAI* botAI) { return new PaladinCureStrategy(botAI); }
|
||||||
static Strategy* boost(PlayerbotAI* botAI) { return new PaladinBoostStrategy(botAI); }
|
static Strategy* boost(PlayerbotAI* botAI) { return new PaladinBoostStrategy(botAI); }
|
||||||
static Strategy* cc(PlayerbotAI* botAI) { return new PaladinCcStrategy(botAI); }
|
static Strategy* cc(PlayerbotAI* botAI) { return new PaladinCcStrategy(botAI); }
|
||||||
|
|||||||
@ -54,7 +54,7 @@ void PaladinCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
{ NextAction("cleanse magic on party", ACTION_DISPEL + 1) }));
|
{ NextAction("cleanse magic on party", ACTION_DISPEL + 1) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaladinBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void PaladinBoostStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
|
|
||||||
// triggers.push_back(new TriggerNode("divine favor", { NextAction("divine favor",
|
// triggers.push_back(new TriggerNode("divine favor", { NextAction("divine favor",
|
||||||
|
|||||||
46
src/Ai/Class/Paladin/Strategy/PaladinPullStrategy.cpp
Normal file
46
src/Ai/Class/Paladin/Strategy/PaladinPullStrategy.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PaladinPullStrategy.h"
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
|
||||||
|
std::string PaladinPullStrategy::GetPullActionName() const
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
Unit* target = GetTarget();
|
||||||
|
if (!bot || !target ||
|
||||||
|
(!botAI->HasStrategy("tank", BOT_STATE_COMBAT) && !botAI->HasStrategy("tank", BOT_STATE_NON_COMBAT)))
|
||||||
|
{
|
||||||
|
return PullStrategy::GetPullActionName();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 const avengersShieldSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "avenger's shield")->Get();
|
||||||
|
if (avengersShieldSpellId && bot->HasSpell(avengersShieldSpellId) &&
|
||||||
|
botAI->CanCastSpell(avengersShieldSpellId, target))
|
||||||
|
{
|
||||||
|
return "avenger's shield";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 const handOfReckoningSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "hand of reckoning")->Get();
|
||||||
|
if (handOfReckoningSpellId && bot->HasSpell(handOfReckoningSpellId) &&
|
||||||
|
botAI->CanCastSpell(handOfReckoningSpellId, target))
|
||||||
|
{
|
||||||
|
return "hand of reckoning";
|
||||||
|
}
|
||||||
|
|
||||||
|
return PullStrategy::GetPullActionName();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PaladinPullStrategy::GetPreActionName() const
|
||||||
|
{
|
||||||
|
if (botAI->HasStrategy("tank", BOT_STATE_COMBAT) || botAI->HasStrategy("tank", BOT_STATE_NON_COMBAT))
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return PullStrategy::GetPreActionName();
|
||||||
|
}
|
||||||
20
src/Ai/Class/Paladin/Strategy/PaladinPullStrategy.h
Normal file
20
src/Ai/Class/Paladin/Strategy/PaladinPullStrategy.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAYERBOT_PALADIN_PULL_STRATEGY_H
|
||||||
|
#define _PLAYERBOT_PALADIN_PULL_STRATEGY_H
|
||||||
|
|
||||||
|
#include "PullStrategy.h"
|
||||||
|
|
||||||
|
class PaladinPullStrategy : public PullStrategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PaladinPullStrategy(PlayerbotAI* botAI) : PullStrategy(botAI, "judgement", "seal of righteousness") {}
|
||||||
|
|
||||||
|
std::string GetPullActionName() const override;
|
||||||
|
std::string GetPreActionName() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -124,12 +124,12 @@ void AoEWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WarlockBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void WarlockBoostStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
// Placeholder for future boost triggers
|
// Placeholder for future boost triggers
|
||||||
}
|
}
|
||||||
|
|
||||||
void WarlockPetStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void WarlockPetStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
// Placeholder for future pet triggers
|
// Placeholder for future pet triggers
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,6 @@ std::vector<NextAction> TankWarlockStrategy::getDefaultActions()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TankWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void TankWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& /*triggers*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ActionNode* charge(PlayerbotAI* botAI)
|
static ActionNode* charge(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"charge",
|
"charge",
|
||||||
@ -31,7 +31,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* death_wish(PlayerbotAI* botAI)
|
static ActionNode* death_wish(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"death wish",
|
"death wish",
|
||||||
@ -41,7 +41,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* piercing_howl(PlayerbotAI* botAI)
|
static ActionNode* piercing_howl(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"piercing howl",
|
"piercing howl",
|
||||||
@ -51,7 +51,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* mocking_blow(PlayerbotAI* botAI)
|
static ActionNode* mocking_blow(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"mocking blow",
|
"mocking blow",
|
||||||
@ -61,7 +61,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* heroic_strike(PlayerbotAI* botAI)
|
static ActionNode* heroic_strike(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"heroic strike",
|
"heroic strike",
|
||||||
@ -71,7 +71,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* enraged_regeneration(PlayerbotAI* botAI)
|
static ActionNode* enraged_regeneration(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"enraged regeneration",
|
"enraged regeneration",
|
||||||
@ -81,7 +81,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* retaliation(PlayerbotAI* botAI)
|
static ActionNode* retaliation(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"retaliation",
|
"retaliation",
|
||||||
@ -91,7 +91,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* shattering_throw(PlayerbotAI* botAI)
|
static ActionNode* shattering_throw(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"shattering throw",
|
"shattering throw",
|
||||||
|
|||||||
@ -18,7 +18,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ActionNode* charge(PlayerbotAI* botAI)
|
static ActionNode* charge(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"charge",
|
"charge",
|
||||||
@ -28,7 +28,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* intercept(PlayerbotAI* botAI)
|
static ActionNode* intercept(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"intercept",
|
"intercept",
|
||||||
@ -38,7 +38,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* piercing_howl(PlayerbotAI* botAI)
|
static ActionNode* piercing_howl(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"piercing howl",
|
"piercing howl",
|
||||||
@ -48,7 +48,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* pummel(PlayerbotAI* botAI)
|
static ActionNode* pummel(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"pummel",
|
"pummel",
|
||||||
@ -58,7 +58,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* enraged_regeneration(PlayerbotAI* botAI)
|
static ActionNode* enraged_regeneration(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"enraged regeneration",
|
"enraged regeneration",
|
||||||
|
|||||||
@ -24,7 +24,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ActionNode* heroic_throw_taunt(PlayerbotAI* botAI)
|
static ActionNode* heroic_throw_taunt(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"heroic throw",
|
"heroic throw",
|
||||||
@ -34,7 +34,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* heroic_throw_on_snare_target(PlayerbotAI* botAI)
|
static ActionNode* heroic_throw_on_snare_target(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"heroic throw on snare target",
|
"heroic throw on snare target",
|
||||||
@ -44,7 +44,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* last_stand(PlayerbotAI* botAI)
|
static ActionNode* last_stand(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"last stand",
|
"last stand",
|
||||||
@ -54,7 +54,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* devastate(PlayerbotAI* botAI)
|
static ActionNode* devastate(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"devastate",
|
"devastate",
|
||||||
@ -64,7 +64,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* commanding_shout(PlayerbotAI* botAI)
|
static ActionNode* commanding_shout(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"commanding shout",
|
"commanding shout",
|
||||||
@ -74,7 +74,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* sunder_armor(PlayerbotAI* botAI)
|
static ActionNode* sunder_armor(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"sunder armor",
|
"sunder armor",
|
||||||
@ -84,7 +84,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* charge(PlayerbotAI* botAI)
|
static ActionNode* charge(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"charge",
|
"charge",
|
||||||
@ -94,7 +94,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* taunt(PlayerbotAI* botAI)
|
static ActionNode* taunt(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"taunt",
|
"taunt",
|
||||||
@ -104,7 +104,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* vigilance(PlayerbotAI* botAI)
|
static ActionNode* vigilance(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"vigilance",
|
"vigilance",
|
||||||
@ -114,7 +114,7 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActionNode* enraged_regeneration(PlayerbotAI* botAI)
|
static ActionNode* enraged_regeneration(PlayerbotAI* /*botAI*/)
|
||||||
{
|
{
|
||||||
return new ActionNode(
|
return new ActionNode(
|
||||||
"enraged regeneration",
|
"enraged regeneration",
|
||||||
|
|||||||
27
src/Ai/Class/Warrior/Strategy/WarriorPullStrategy.cpp
Normal file
27
src/Ai/Class/Warrior/Strategy/WarriorPullStrategy.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "WarriorPullStrategy.h"
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
|
||||||
|
std::string WarriorPullStrategy::GetPullActionName() const
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
Unit* target = GetTarget();
|
||||||
|
if (!bot || !target)
|
||||||
|
return PullStrategy::GetPullActionName();
|
||||||
|
|
||||||
|
uint32 const heroicThrowSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "heroic throw")->Get();
|
||||||
|
if (heroicThrowSpellId && bot->HasSpell(heroicThrowSpellId) &&
|
||||||
|
botAI->CanCastSpell(heroicThrowSpellId, target))
|
||||||
|
{
|
||||||
|
return "heroic throw";
|
||||||
|
}
|
||||||
|
|
||||||
|
return PullStrategy::GetPullActionName();
|
||||||
|
}
|
||||||
19
src/Ai/Class/Warrior/Strategy/WarriorPullStrategy.h
Normal file
19
src/Ai/Class/Warrior/Strategy/WarriorPullStrategy.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||||
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAYERBOT_WARRIOR_PULL_STRATEGY_H
|
||||||
|
#define _PLAYERBOT_WARRIOR_PULL_STRATEGY_H
|
||||||
|
|
||||||
|
#include "PullStrategy.h"
|
||||||
|
|
||||||
|
class WarriorPullStrategy : public PullStrategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WarriorPullStrategy(PlayerbotAI* botAI) : PullStrategy(botAI, "shoot") {}
|
||||||
|
|
||||||
|
std::string GetPullActionName() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -10,8 +10,8 @@
|
|||||||
#include "GenericWarriorNonCombatStrategy.h"
|
#include "GenericWarriorNonCombatStrategy.h"
|
||||||
#include "NamedObjectContext.h"
|
#include "NamedObjectContext.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "PullStrategy.h"
|
|
||||||
#include "TankWarriorStrategy.h"
|
#include "TankWarriorStrategy.h"
|
||||||
|
#include "WarriorPullStrategy.h"
|
||||||
#include "WarriorActions.h"
|
#include "WarriorActions.h"
|
||||||
#include "WarriorTriggers.h"
|
#include "WarriorTriggers.h"
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
static Strategy* nc(PlayerbotAI* botAI) { return new GenericWarriorNonCombatStrategy(botAI); }
|
static Strategy* nc(PlayerbotAI* botAI) { return new GenericWarriorNonCombatStrategy(botAI); }
|
||||||
static Strategy* warrior_aoe(PlayerbotAI* botAI) { return new WarrirorAoeStrategy(botAI); }
|
static Strategy* warrior_aoe(PlayerbotAI* botAI) { return new WarrirorAoeStrategy(botAI); }
|
||||||
static Strategy* pull(PlayerbotAI* botAI) { return new PullStrategy(botAI, "shoot"); }
|
static Strategy* pull(PlayerbotAI* botAI) { return new WarriorPullStrategy(botAI); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WarriorCombatStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
class WarriorCombatStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||||
|
|||||||
117
src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.cpp
Normal file
117
src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include "Playerbots.h"
|
||||||
|
#include "AiFactory.h"
|
||||||
|
#include "AuchenaiCryptsTriggers.h"
|
||||||
|
#include "AuchenaiCryptsActions.h"
|
||||||
|
|
||||||
|
// Shirrak the Dead Watcher
|
||||||
|
|
||||||
|
static const Position SHIRRAK_RANGED_POSITION = { -21.777f, -162.700f, 26.062f };
|
||||||
|
static const Position SHIRRAK_TANK_POSITION = { -65.171f, -162.920f, 26.504f };
|
||||||
|
|
||||||
|
// Tank will position Shirrak at the specified coordinates, further down the corridor past the stairs
|
||||||
|
|
||||||
|
bool ShirrakTankPositionBossAction::Execute(Event /*event*/)
|
||||||
|
{
|
||||||
|
Unit* shirrak = AI_VALUE2(Unit*, "find target", "shirrak the dead watcher");
|
||||||
|
if (!shirrak)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (bot->GetVictim() != shirrak)
|
||||||
|
return Attack(shirrak);
|
||||||
|
|
||||||
|
if (shirrak->GetVictim() == bot && bot->IsWithinMeleeRange(shirrak) &&
|
||||||
|
bot->GetHealthPct()>30.0f)
|
||||||
|
{
|
||||||
|
const Position& position = SHIRRAK_TANK_POSITION;
|
||||||
|
float distToPosition = bot->GetExactDist2d(position.GetPositionX(),
|
||||||
|
position.GetPositionY());
|
||||||
|
if (distToPosition > 6.0f)
|
||||||
|
{
|
||||||
|
float dX = position.GetPositionX() - bot->GetPositionX();
|
||||||
|
float dY = position.GetPositionY() - bot->GetPositionY();
|
||||||
|
float moveDist = std::min(2.0f, distToPosition);
|
||||||
|
float moveX = bot->GetPositionX() + (dX / distToPosition) * moveDist;
|
||||||
|
float moveY = bot->GetPositionY() + (dY / distToPosition) * moveDist;
|
||||||
|
|
||||||
|
return MoveTo(bot->GetMapId(), moveX, moveY, bot->GetPositionZ(), false, false,
|
||||||
|
false, false, MovementPriority::MOVEMENT_COMBAT, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flee from Shirrak's Focus Fire
|
||||||
|
|
||||||
|
bool ShirrakFleeFocusFireAction::Execute(Event /*event*/)
|
||||||
|
{
|
||||||
|
std::list<Creature*> creatureList;
|
||||||
|
bot->GetCreatureListWithEntryInGrid(creatureList, static_cast<uint32>(AuchenaiCryptsIDs::NPC_FOCUS_FIRE), 20.0f);
|
||||||
|
|
||||||
|
for (Creature* flare : creatureList)
|
||||||
|
{
|
||||||
|
if (flare && flare->IsAlive())
|
||||||
|
{
|
||||||
|
float currentDistance = bot->GetDistance2d(flare);
|
||||||
|
constexpr float safeDistance = 12.0f;
|
||||||
|
constexpr float buffer = 5.0f;
|
||||||
|
|
||||||
|
if (currentDistance < safeDistance)
|
||||||
|
{
|
||||||
|
bot->AttackStop();
|
||||||
|
|
||||||
|
float distanceToMove = safeDistance - currentDistance + buffer;
|
||||||
|
|
||||||
|
return MoveAway(flare, distanceToMove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ranged should keep distance from Shirrak, staying at the edge of the stairs
|
||||||
|
|
||||||
|
bool ShirrakRangedKeepDistanceAction::Execute(Event /*event*/)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<Player*> rangedBots;
|
||||||
|
if (Group* group = bot->GetGroup())
|
||||||
|
{
|
||||||
|
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||||
|
{
|
||||||
|
Player* member = ref->GetSource();
|
||||||
|
if (member && botAI->IsRanged(member))
|
||||||
|
rangedBots.push_back(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto findIt = std::find(rangedBots.begin(), rangedBots.end(), bot);
|
||||||
|
size_t botIndex = (findIt != rangedBots.end()) ? std::distance(rangedBots.begin(), findIt) : 0;
|
||||||
|
size_t count = rangedBots.size();
|
||||||
|
|
||||||
|
constexpr float arcSpan = M_PI / 2.0f;
|
||||||
|
float arcCenter = M_PI;
|
||||||
|
float arcStart = arcCenter - (arcSpan / 2.0f);
|
||||||
|
|
||||||
|
float angle = (count <= 1) ? arcCenter : (arcStart + (arcSpan * (float)botIndex / (float)(count - 1)));
|
||||||
|
|
||||||
|
constexpr float spreadRadius = 3.0f;
|
||||||
|
float targetX = SHIRRAK_RANGED_POSITION.GetPositionX() + cos(angle) * spreadRadius;
|
||||||
|
float targetY = SHIRRAK_RANGED_POSITION.GetPositionY() + sin(angle) * spreadRadius;
|
||||||
|
|
||||||
|
float distToSpot = bot->GetExactDist2d(targetX, targetY);
|
||||||
|
|
||||||
|
if (distToSpot > 4.0f)
|
||||||
|
{
|
||||||
|
float dX = targetX - bot->GetPositionX();
|
||||||
|
float dY = targetY - bot->GetPositionY();
|
||||||
|
|
||||||
|
float moveDist = std::min(2.0f, distToSpot);
|
||||||
|
float moveX = bot->GetPositionX() + (dX / distToSpot) * moveDist;
|
||||||
|
float moveY = bot->GetPositionY() + (dY / distToSpot) * moveDist;
|
||||||
|
|
||||||
|
return MoveTo(bot->GetMapId(), moveX, moveY, bot->GetPositionZ(), false, false,
|
||||||
|
false, false, MovementPriority::MOVEMENT_COMBAT, true, false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
31
src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.h
Normal file
31
src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSACTIONS_H
|
||||||
|
#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSACTIONS_H
|
||||||
|
|
||||||
|
#include "AttackAction.h"
|
||||||
|
#include "MovementActions.h"
|
||||||
|
#include "AuchenaiCryptsTriggers.h"
|
||||||
|
|
||||||
|
// Shirrak the Dead Watcher
|
||||||
|
|
||||||
|
class ShirrakTankPositionBossAction : public AttackAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShirrakTankPositionBossAction(PlayerbotAI* botAI) : AttackAction(botAI, "shirrak tank position boss") {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShirrakFleeFocusFireAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShirrakFleeFocusFireAction(PlayerbotAI* botAI) : MovementAction(botAI, "shirrak flee focus fire") {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShirrakRangedKeepDistanceAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShirrakRangedKeepDistanceAction(PlayerbotAI* botAI) : MovementAction(botAI, "shirrak ranged keep distance") {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
34
src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsActionContext.h
Normal file
34
src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsActionContext.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSACTIONCONTEXT_H
|
||||||
|
#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSACTIONCONTEXT_H
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "Action.h"
|
||||||
|
#include "AuchenaiCryptsActions.h"
|
||||||
|
|
||||||
|
class TbcDungeonAuchenaiCryptsActionContext : public NamedObjectContext<Action>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TbcDungeonAuchenaiCryptsActionContext() : NamedObjectContext<Action>(false, true)
|
||||||
|
{
|
||||||
|
creators["shirrak tank position boss"] =
|
||||||
|
&TbcDungeonAuchenaiCryptsActionContext::shirrak_tank_position_boss;
|
||||||
|
|
||||||
|
creators["shirrak flee focus fire"] =
|
||||||
|
&TbcDungeonAuchenaiCryptsActionContext::shirrak_flee_focus_fire;
|
||||||
|
|
||||||
|
creators["shirrak ranged keep distance"] =
|
||||||
|
&TbcDungeonAuchenaiCryptsActionContext::shirrak_ranged_keep_distance;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
|
||||||
|
static Action* shirrak_tank_position_boss(
|
||||||
|
PlayerbotAI* botAI) { return new ShirrakTankPositionBossAction(botAI); }
|
||||||
|
|
||||||
|
static Action* shirrak_flee_focus_fire(
|
||||||
|
PlayerbotAI* botAI) { return new ShirrakFleeFocusFireAction(botAI); }
|
||||||
|
|
||||||
|
static Action* shirrak_ranged_keep_distance(
|
||||||
|
PlayerbotAI* botAI) { return new ShirrakRangedKeepDistanceAction(botAI); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
35
src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsTriggerContext.h
Normal file
35
src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsTriggerContext.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSTRIGGERCONTEXT_H
|
||||||
|
#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSTRIGGERCONTEXT_H
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "TriggerContext.h"
|
||||||
|
#include "AuchenaiCryptsTriggers.h"
|
||||||
|
|
||||||
|
class TbcDungeonAuchenaiCryptsTriggerContext : public NamedObjectContext<Trigger>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Shirrak the Dead Watcher
|
||||||
|
TbcDungeonAuchenaiCryptsTriggerContext()
|
||||||
|
{
|
||||||
|
creators["shirrak tank position boss"] =
|
||||||
|
&TbcDungeonAuchenaiCryptsTriggerContext::shirrak_tank_position_boss;
|
||||||
|
|
||||||
|
creators["shirrak flee focus fire"] =
|
||||||
|
&TbcDungeonAuchenaiCryptsTriggerContext::shirrak_flee_focus_fire;
|
||||||
|
|
||||||
|
creators["shirrak ranged keep distance"] =
|
||||||
|
&TbcDungeonAuchenaiCryptsTriggerContext::shirrak_ranged_keep_distance;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
// Shirrak the Dead Watcher
|
||||||
|
static Trigger* shirrak_tank_position_boss(
|
||||||
|
PlayerbotAI* botAI) { return new ShirrakTankPositionBossTrigger(botAI); }
|
||||||
|
|
||||||
|
static Trigger* shirrak_flee_focus_fire(
|
||||||
|
PlayerbotAI* botAI) { return new ShirrakFleeFocusFireTrigger(botAI); }
|
||||||
|
|
||||||
|
static Trigger* shirrak_ranged_keep_distance(
|
||||||
|
PlayerbotAI* botAI) { return new ShirrakRangedKeepDistanceTrigger(botAI); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
#include "AuchenaiCryptsMultipliers.h"
|
||||||
|
#include "AuchenaiCryptsActions.h"
|
||||||
|
#include "AuchenaiCryptsTriggers.h"
|
||||||
|
#include "MovementActions.h"
|
||||||
|
#include "ReachTargetActions.h"
|
||||||
|
#include "FollowActions.h"
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
|
||||||
|
// Shirrak the Dead Watcher
|
||||||
|
|
||||||
|
// Flee from Focus Fire and dont run back in
|
||||||
|
float ShirrakFleeFocusFireMultiplier::GetValue(Action* action)
|
||||||
|
{
|
||||||
|
if (!AI_VALUE2(Unit*, "find target", "shirrak the dead watcher"))
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
std::list<Creature*> creatureList;
|
||||||
|
bot->GetCreatureListWithEntryInGrid(creatureList, static_cast<uint32>(AuchenaiCryptsIDs::NPC_FOCUS_FIRE), 20.0f);
|
||||||
|
|
||||||
|
for (Creature* flare : creatureList)
|
||||||
|
{
|
||||||
|
if (flare && flare->IsAlive())
|
||||||
|
{
|
||||||
|
if (dynamic_cast<CastReachTargetSpellAction*>(action))
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
float currentDistance = bot->GetDistance2d(flare);
|
||||||
|
constexpr float safeDistance = 12.0f;
|
||||||
|
constexpr float buffer = 5.0f;
|
||||||
|
|
||||||
|
if (currentDistance < safeDistance + buffer && (
|
||||||
|
dynamic_cast<CombatFormationMoveAction*>(action) ||
|
||||||
|
dynamic_cast<ShirrakRangedKeepDistanceAction*>(action) ||
|
||||||
|
dynamic_cast<FleeAction*>(action) ||
|
||||||
|
dynamic_cast<FollowAction*>(action) ||
|
||||||
|
dynamic_cast<ReachTargetAction*>(action) ||
|
||||||
|
dynamic_cast<AvoidAoeAction*>(action)))
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSMULTIPLIERS_H
|
||||||
|
#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSMULTIPLIERS_H
|
||||||
|
|
||||||
|
#include "Multiplier.h"
|
||||||
|
|
||||||
|
class ShirrakFleeFocusFireMultiplier : public Multiplier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShirrakFleeFocusFireMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "shirrak flee focus fire") {}
|
||||||
|
float GetValue(Action* action) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
#include "AuchenaiCryptsTriggers.h"
|
||||||
|
#include "AuchenaiCryptsStrategy.h"
|
||||||
|
#include "AuchenaiCryptsMultipliers.h"
|
||||||
|
|
||||||
|
void TbcDungeonAuchenaiCryptsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
|
{
|
||||||
|
// Shirrak The Dead Watcher
|
||||||
|
triggers.push_back(new TriggerNode("shirrak tank position boss", {
|
||||||
|
NextAction("shirrak tank position boss", ACTION_RAID + 1) }));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode("shirrak flee focus fire", {
|
||||||
|
NextAction("shirrak flee focus fire", ACTION_EMERGENCY + 10) }));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode("shirrak ranged keep distance", {
|
||||||
|
NextAction("shirrak ranged keep distance", ACTION_RAID + 1) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TbcDungeonAuchenaiCryptsStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||||
|
{
|
||||||
|
multipliers.push_back(new ShirrakFleeFocusFireMultiplier(botAI));
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSSTRATEGY_H
|
||||||
|
#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSSTRATEGY_H
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "Strategy.h"
|
||||||
|
#include "Multiplier.h"
|
||||||
|
|
||||||
|
class TbcDungeonAuchenaiCryptsStrategy : public Strategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TbcDungeonAuchenaiCryptsStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||||
|
|
||||||
|
virtual std::string const getName() override { return "tbc-ac"; }
|
||||||
|
|
||||||
|
virtual void InitTriggers(std::vector<TriggerNode*> &triggers) override;
|
||||||
|
virtual void InitMultipliers(std::vector<Multiplier*> &multipliers) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
#include "Playerbots.h"
|
||||||
|
#include "AuchenaiCryptsTriggers.h"
|
||||||
|
#include "AiObject.h"
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
|
||||||
|
// Shirrak the Dead Watcher
|
||||||
|
|
||||||
|
bool ShirrakTankPositionBossTrigger::IsActive()
|
||||||
|
{
|
||||||
|
return botAI->IsTank(bot) &&
|
||||||
|
AI_VALUE2(Unit*, "find target", "shirrak the dead watcher");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShirrakFleeFocusFireTrigger::IsActive()
|
||||||
|
{
|
||||||
|
if (!AI_VALUE2(Unit*, "find target", "shirrak the dead watcher"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::list<Creature*> creatureList;
|
||||||
|
bot->GetCreatureListWithEntryInGrid(creatureList, static_cast<uint32>(AuchenaiCryptsIDs::NPC_FOCUS_FIRE), 20.0f);
|
||||||
|
|
||||||
|
for (Creature* flare : creatureList)
|
||||||
|
{
|
||||||
|
if (flare && flare->IsAlive())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShirrakRangedKeepDistanceTrigger::IsActive()
|
||||||
|
{
|
||||||
|
return botAI->IsRanged(bot) &&
|
||||||
|
AI_VALUE2(Unit*, "find target", "shirrak the dead watcher");
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSTRIGGERS_H
|
||||||
|
#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSTRIGGERS_H
|
||||||
|
|
||||||
|
#include "Trigger.h"
|
||||||
|
#include "GenericTriggers.h"
|
||||||
|
#include "DungeonStrategyUtils.h"
|
||||||
|
|
||||||
|
enum class AuchenaiCryptsIDs : uint32
|
||||||
|
{
|
||||||
|
// Shirrak The Dead Watcher
|
||||||
|
NPC_FOCUS_FIRE = 18374,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShirrakTankPositionBossTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShirrakTankPositionBossTrigger(PlayerbotAI* botAI) : Trigger(botAI, "shirrak tank position boss") {}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShirrakFleeFocusFireTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShirrakFleeFocusFireTrigger(PlayerbotAI* botAI) : Trigger(botAI, "shirrak flee focus fire") {}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShirrakRangedKeepDistanceTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShirrakRangedKeepDistanceTrigger(PlayerbotAI* botAI) : Trigger(botAI, "shirrak ranged keep distance") {}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -2,6 +2,7 @@
|
|||||||
#define _PLAYERBOT_DUNGEONSTRATEGYCONTEXT_H
|
#define _PLAYERBOT_DUNGEONSTRATEGYCONTEXT_H
|
||||||
|
|
||||||
#include "Strategy.h"
|
#include "Strategy.h"
|
||||||
|
#include "AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.h"
|
||||||
#include "UtgardeKeep/Strategy/UtgardeKeepStrategy.h"
|
#include "UtgardeKeep/Strategy/UtgardeKeepStrategy.h"
|
||||||
#include "Nexus/Strategy/NexusStrategy.h"
|
#include "Nexus/Strategy/NexusStrategy.h"
|
||||||
#include "AzjolNerub/Strategy/AzjolNerubStrategy.h"
|
#include "AzjolNerub/Strategy/AzjolNerubStrategy.h"
|
||||||
@ -44,7 +45,7 @@ class DungeonStrategyContext : public NamedObjectContext<Strategy>
|
|||||||
// ...
|
// ...
|
||||||
|
|
||||||
// Burning Crusade
|
// Burning Crusade
|
||||||
// ...
|
creators["tbc-ac"] = &DungeonStrategyContext::tbc_ac; // Auchindoun: Auchenai Crypts
|
||||||
|
|
||||||
// Wrath of the Lich King
|
// Wrath of the Lich King
|
||||||
creators["wotlk-uk"] = &DungeonStrategyContext::wotlk_uk; // Utgarde Keep
|
creators["wotlk-uk"] = &DungeonStrategyContext::wotlk_uk; // Utgarde Keep
|
||||||
@ -65,6 +66,7 @@ class DungeonStrategyContext : public NamedObjectContext<Strategy>
|
|||||||
creators["wotlk-fos"] = &DungeonStrategyContext::wotlk_fos; // The Forge of Souls
|
creators["wotlk-fos"] = &DungeonStrategyContext::wotlk_fos; // The Forge of Souls
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
static Strategy* tbc_ac(PlayerbotAI* botAI) { return new TbcDungeonAuchenaiCryptsStrategy(botAI); }
|
||||||
static Strategy* wotlk_uk(PlayerbotAI* botAI) { return new WotlkDungeonUKStrategy(botAI); }
|
static Strategy* wotlk_uk(PlayerbotAI* botAI) { return new WotlkDungeonUKStrategy(botAI); }
|
||||||
static Strategy* wotlk_nex(PlayerbotAI* botAI) { return new WotlkDungeonNexStrategy(botAI); }
|
static Strategy* wotlk_nex(PlayerbotAI* botAI) { return new WotlkDungeonNexStrategy(botAI); }
|
||||||
static Strategy* wotlk_an(PlayerbotAI* botAI) { return new WotlkDungeonANStrategy(botAI); }
|
static Strategy* wotlk_an(PlayerbotAI* botAI) { return new WotlkDungeonANStrategy(botAI); }
|
||||||
|
|||||||
@ -134,7 +134,7 @@ bool IckAndKrickAction::PoisonNova(bool poisonNova, Unit* boss)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IckAndKrickAction::ExplosiveBarrage(bool explosiveBarrage, Unit* boss)
|
bool IckAndKrickAction::ExplosiveBarrage(bool /*explosiveBarrage*/, Unit* boss)
|
||||||
{
|
{
|
||||||
std::vector<Unit*> orbs;
|
std::vector<Unit*> orbs;
|
||||||
Unit* closestOrb = nullptr;
|
Unit* closestOrb = nullptr;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ float IckAndKrickMultiplier::GetValue(Action* action)
|
|||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GarfrostMultiplier::GetValue(Action* action)
|
float GarfrostMultiplier::GetValue(Action* /*action*/)
|
||||||
{
|
{
|
||||||
Unit* boss = AI_VALUE2(Unit*, "find target", "garfrost");
|
Unit* boss = AI_VALUE2(Unit*, "find target", "garfrost");
|
||||||
if (!boss)
|
if (!boss)
|
||||||
|
|||||||
6
src/Ai/Dungeon/TbcDungeonActionContext.h
Normal file
6
src/Ai/Dungeon/TbcDungeonActionContext.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _PLAYERBOT_TBCDUNGEONACTIONCONTEXT_H
|
||||||
|
#define _PLAYERBOT_TBCDUNGEONACTIONCONTEXT_H
|
||||||
|
|
||||||
|
#include "AuchenaiCrypts/AuchenaiCryptsActionContext.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
6
src/Ai/Dungeon/TbcDungeonTriggerContext.h
Normal file
6
src/Ai/Dungeon/TbcDungeonTriggerContext.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _PLAYERBOT_TBCDUNGEONTRIGGERCONTEXT_H
|
||||||
|
#define _PLAYERBOT_TBCDUNGEONTRIGGERCONTEXT_H
|
||||||
|
|
||||||
|
#include "AuchenaiCrypts/AuchenaiCryptsTriggerContext.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
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