Compare commits

...

404 Commits

Author SHA1 Message Date
Yunfan Li
6003dbc1b5 Directory reorganization 2025-05-07 00:06:31 +08:00
Yunfan Li
0d170f5370 Fix inventory clear on init quests (#1266) 2025-05-05 15:07:51 +02:00
Type1Error
f55e95da9d fix(#1250): Fix movement animation desync after CC effects This fixes a bug where playerbots fail to display proper movement animations after crowd control effects wear off. When affected by movement-restricting abilities (e.g., Net-o-Matic Projector), bots would abruptly snap between positions instead of transitioning smoothly with walking or running animations. (#1264)
Fix: Better handling of CC state transitions in bot movement:
    - Added wasMovementRestricted to track CC status
    - Enhanced UpdateMovementState() to detect and react to CC ending
    - Triggered movement flag update to fix animation desync

This ensures proper client-server movement synchronization and resolves the visual bug where bots appeared to jump or skip positions. The fix restores the correct movement animation state, replicating the effect previously achieved with the reset or summon commands.
2025-05-05 15:07:16 +02:00
Icemansparks
0574ac5eff feature - (#1100) Linking of "trusted" accounts to allow altbot-control apart from own account or guild (#1267)
* Add table to store the security keys for accounts.

* Add table to store relationships between accounts.

* Add a new configuration option to enable or disable trusted account bots.

* add checks for linked accounts

* Handle account linking and chat commands

* fix uppercase typo

* change query & fix chatcommandtable

* add missing functions to header

* move account linking to updates dir

* moved table creation to correct updates folder

* use playerbots db instead of character db

* fix db

* fix install?

* remove duplicated logic and add hashing to stored securityKey

* add object before call

* change chat variable

* rename SQL file for correct execution order

* add  header include for ubuntu compatibility

* remove old sql
2025-05-05 15:06:29 +02:00
Noscopezz
b69ebfbb3c ICC GS fix (#1261)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.

* ICC minor update

GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle if the room so that bots don't spread out too much which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP

* ICC LK minor update

Commented out z axis bypass since it was fixed with recent core updates.

Bots no longer fall thru buggy platforms so its no longer needed which in return makes valkyrs works as they should.

* ICC LM & LDW Improved

LM

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Simplified trigger for spike action, since attack logic is handled by skull RTI now.

Bots (tanks) will mark spikes with skull RTI, which will make bots instantly switch to Spike targets. If no spike is present, the boss will be marked.

Added logic that will make non-tank bots move away from LM to a fixed position behind LM if they happened to be in front of LM (No more insta kills with cleave).
If LM is casting Bone Storm, bots will ignore the above logic and do max dps.

LDW

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Bots (tanks) will mark adds with skull RTI, which will make bots instantly switch to adds targets. If no spike is present, the boss will be marked, which will help with keeping allies alive when they get mind controlled by LDW.

Moved 2nd phase position deeper into the room and reduced boss hp trigger to 95%, which will keep tanks where they should be during 1st phase (sometimes the boss dropped below 98% and tanks would ping pong around the room).

Ranged bots will now spread closer to each other now and will ignore spreading if they are 2 far or 2 close to the boss so they can properly reposition.

These changes should also fix recent bugs with bots not casting/standing still on LM and LDW.

* ICC DBS Improve

Replaced attack action with RTI. (Improved DPS)

Ranged bots will move away from blood beast if targeted by it now.

* ICC Sindragosa and LK Improve

Sindragosa

Improved tomb los for frost bombs. Bots will now mark tomb with moon rti to avoid killing it too soon. (If they still attack the tomb, simply reset and after bombs are over, simply attack the tomb to kill or mark with a skull.)
Main Tank will reset mystic buffet stacks now to avoid tank swapping since it's really unreliable which will make sindy less frustrating to kill (other bots will need to do mechanics properly by hiding behind ice tombs).

LK

Necrotic plague action

Bots will now check before moving to the Shambling if they are in front of the Shambling to avoid getting one shoted by shockwave.
Improved multiplier, which will now properly handle dispelling of necrotic plague.

Winter phase action

Bots will properly move behind adds to avoid getting one shoted by shamblings or raging spirits.
If there is a hunter in the grouphunter will focus on spheres; if not, any ranged DPS will focus spheres.

Adds action

Bots will now be in proper positions during the 1st phase, and when the off tank is done collecting shamblings, it will move away from the group.
Bots (non-tanks) will move behind the shambling if they are in front of it to avoid getting one shoted in the 1st phase.
Restored action for checking if bots are at ground level, since they were still sometimes glitching through the floor (valkrys will be able to carry bots and drop them off the edge if not killed in time).
Improved defile calculations for 10 man and 25 man raids since defile was growing differently for 10 and 25, which would make bots in 25 man move very far away from somewhat small defile puddle.
Bots will now properly CC any valkyr that wasn't CC'd, and they won't freak out anymore if multiple valkyrs are present. (They can't tell which valkyr is holding bots/ players, so we should command an attack on valkyrs that are holding someone.)
Bots will now run away from Vile Spirits if they are targeted by them during the last phase.

* ICC 25HC ldw shades fix

Fixed bots could not detect shade if there were multiple present

* ICC trigger optimization

Optimized trigger and action for:

KineticBomb
OozePuddle

* ICC LK Improve

Improved Shadow Trap, Winter phase and 1st phase.

Bots will now have fixed positions for 1st phase if no shadow trap is present.

Tanks will now take care of taunting adds during winter phase. (Assist tank will collect adds and bring them to main tank, main tank will take over the adds so we have minimal chance of adds rotating towards the raid)

Fixed shadow trap detection.

* ToC dungeon update

Added TOC dungeon strategies for 1st encounter.

Other encounters are pretty easy and straightforward so they do not require strategies. They can be all done with follow, reset, summon, attack, skull icon etc...

Bots (A/H) will automatically check if they have lance equiped or in inventory. If they don't have lance they will pick it up from nearest lance stand and equip it.

Bots will mount nearest mount if they have lance equipped.

Once mounted they will keep Defend aura at 3 stacks (top priority).
In fight they will cast charge if more than 5f away, they will cast shield break if target has Defended aura active and they will use Thrust if they cant use anything else.
In short they will melt any target and enemies wont stand a chance keeping their defend aura up.

Once champions are defeated bot will automatically equip best weapon they have in inventory (weapon that was swapped with lance)

* ICC minor update

LM

Bots will now move in smaller increments to get behind boss
They will still move towards fixed position, but as soon they are not in front of boss, they will stop moving and do other actions.

GS

Fixed cannon trigger, now will return true if cannon is 100f from bots.
It used to return true all the time.

* ToC added Eadric strat

bots will look away during radiance cast

* ICC LK minor fix

fixed crash in icclichkingsaddsaction

* ICC GS fix

While encountering edge case when playing horde, the logic was to detect mages, there are usually 2 around, but the longer the fight last the bigger the chance that cannons would kill all the mages thus once we kill the mage that was casting deep freeze bots could not execute action that would return them back to the ship, so the boss had the time to nuke them one by one.
Even tanks have hard time surviving the boss.
I have changed it now (both A/H) so that we keep track of the enemy boss (which is hard if not impossible to kill as main trigger) and we are keeping track of the  mage that is actually casting deep freeze, we mark it with skull, and now as soon the mage is dead, bots will remove the mark so there is 0 confusion about what to do next on their side, and they will come back asap.
2025-05-04 15:37:19 +02:00
NoxMax
2649cc0ad5 Comment fix (#1263)
Reflecting changes made a while back about changing the default active bots from 10% to 100% 9fb2b51f16
2025-05-04 15:37:01 +02:00
Noscopezz
1cae1b389e ToC dungeon strategies (#1259)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.

* ICC minor update

GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle if the room so that bots don't spread out too much which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP

* ICC LK minor update

Commented out z axis bypass since it was fixed with recent core updates.

Bots no longer fall thru buggy platforms so its no longer needed which in return makes valkyrs works as they should.

* ICC LM & LDW Improved

LM

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Simplified trigger for spike action, since attack logic is handled by skull RTI now.

Bots (tanks) will mark spikes with skull RTI, which will make bots instantly switch to Spike targets. If no spike is present, the boss will be marked.

Added logic that will make non-tank bots move away from LM to a fixed position behind LM if they happened to be in front of LM (No more insta kills with cleave).
If LM is casting Bone Storm, bots will ignore the above logic and do max dps.

LDW

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Bots (tanks) will mark adds with skull RTI, which will make bots instantly switch to adds targets. If no spike is present, the boss will be marked, which will help with keeping allies alive when they get mind controlled by LDW.

Moved 2nd phase position deeper into the room and reduced boss hp trigger to 95%, which will keep tanks where they should be during 1st phase (sometimes the boss dropped below 98% and tanks would ping pong around the room).

Ranged bots will now spread closer to each other now and will ignore spreading if they are 2 far or 2 close to the boss so they can properly reposition.

These changes should also fix recent bugs with bots not casting/standing still on LM and LDW.

* ICC DBS Improve

Replaced attack action with RTI. (Improved DPS)

Ranged bots will move away from blood beast if targeted by it now.

* ICC Sindragosa and LK Improve

Sindragosa

Improved tomb los for frost bombs. Bots will now mark tomb with moon rti to avoid killing it too soon. (If they still attack the tomb, simply reset and after bombs are over, simply attack the tomb to kill or mark with a skull.)
Main Tank will reset mystic buffet stacks now to avoid tank swapping since it's really unreliable which will make sindy less frustrating to kill (other bots will need to do mechanics properly by hiding behind ice tombs).

LK

Necrotic plague action

Bots will now check before moving to the Shambling if they are in front of the Shambling to avoid getting one shoted by shockwave.
Improved multiplier, which will now properly handle dispelling of necrotic plague.

Winter phase action

Bots will properly move behind adds to avoid getting one shoted by shamblings or raging spirits.
If there is a hunter in the grouphunter will focus on spheres; if not, any ranged DPS will focus spheres.

Adds action

Bots will now be in proper positions during the 1st phase, and when the off tank is done collecting shamblings, it will move away from the group.
Bots (non-tanks) will move behind the shambling if they are in front of it to avoid getting one shoted in the 1st phase.
Restored action for checking if bots are at ground level, since they were still sometimes glitching through the floor (valkrys will be able to carry bots and drop them off the edge if not killed in time).
Improved defile calculations for 10 man and 25 man raids since defile was growing differently for 10 and 25, which would make bots in 25 man move very far away from somewhat small defile puddle.
Bots will now properly CC any valkyr that wasn't CC'd, and they won't freak out anymore if multiple valkyrs are present. (They can't tell which valkyr is holding bots/ players, so we should command an attack on valkyrs that are holding someone.)
Bots will now run away from Vile Spirits if they are targeted by them during the last phase.

* ICC 25HC ldw shades fix

Fixed bots could not detect shade if there were multiple present

* ICC trigger optimization

Optimized trigger and action for:

KineticBomb
OozePuddle

* ICC LK Improve

Improved Shadow Trap, Winter phase and 1st phase.

Bots will now have fixed positions for 1st phase if no shadow trap is present.

Tanks will now take care of taunting adds during winter phase. (Assist tank will collect adds and bring them to main tank, main tank will take over the adds so we have minimal chance of adds rotating towards the raid)

Fixed shadow trap detection.

* ToC dungeon update

Added TOC dungeon strategies for 1st encounter.

Other encounters are pretty easy and straightforward so they do not require strategies. They can be all done with follow, reset, summon, attack, skull icon etc...

Bots (A/H) will automatically check if they have lance equiped or in inventory. If they don't have lance they will pick it up from nearest lance stand and equip it.

Bots will mount nearest mount if they have lance equipped.

Once mounted they will keep Defend aura at 3 stacks (top priority).
In fight they will cast charge if more than 5f away, they will cast shield break if target has Defended aura active and they will use Thrust if they cant use anything else.
In short they will melt any target and enemies wont stand a chance keeping their defend aura up.

Once champions are defeated bot will automatically equip best weapon they have in inventory (weapon that was swapped with lance)

* ICC minor update

LM

Bots will now move in smaller increments to get behind boss
They will still move towards fixed position, but as soon they are not in front of boss, they will stop moving and do other actions.

GS

Fixed cannon trigger, now will return true if cannon is 100f from bots.
It used to return true all the time.

* ToC added Eadric strat

bots will look away during radiance cast

* ICC LK minor fix

fixed crash in icclichkingsaddsaction
2025-05-03 21:02:49 +02:00
Cryo81
707210f6a5 fixing multiple 'unused variable' warnings (#1224) 2025-05-01 21:00:54 +02:00
Noscopezz
6fc02a4429 ICC LK Improve (#1256)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.

* ICC minor update

GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle if the room so that bots don't spread out too much which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP

* ICC LK minor update

Commented out z axis bypass since it was fixed with recent core updates.

Bots no longer fall thru buggy platforms so its no longer needed which in return makes valkyrs works as they should.

* ICC LM & LDW Improved

LM

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Simplified trigger for spike action, since attack logic is handled by skull RTI now.

Bots (tanks) will mark spikes with skull RTI, which will make bots instantly switch to Spike targets. If no spike is present, the boss will be marked.

Added logic that will make non-tank bots move away from LM to a fixed position behind LM if they happened to be in front of LM (No more insta kills with cleave).
If LM is casting Bone Storm, bots will ignore the above logic and do max dps.

LDW

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Bots (tanks) will mark adds with skull RTI, which will make bots instantly switch to adds targets. If no spike is present, the boss will be marked, which will help with keeping allies alive when they get mind controlled by LDW.

Moved 2nd phase position deeper into the room and reduced boss hp trigger to 95%, which will keep tanks where they should be during 1st phase (sometimes the boss dropped below 98% and tanks would ping pong around the room).

Ranged bots will now spread closer to each other now and will ignore spreading if they are 2 far or 2 close to the boss so they can properly reposition.

These changes should also fix recent bugs with bots not casting/standing still on LM and LDW.

* ICC DBS Improve

Replaced attack action with RTI. (Improved DPS)

Ranged bots will move away from blood beast if targeted by it now.

* ICC Sindragosa and LK Improve

Sindragosa

Improved tomb los for frost bombs. Bots will now mark tomb with moon rti to avoid killing it too soon. (If they still attack the tomb, simply reset and after bombs are over, simply attack the tomb to kill or mark with a skull.)
Main Tank will reset mystic buffet stacks now to avoid tank swapping since it's really unreliable which will make sindy less frustrating to kill (other bots will need to do mechanics properly by hiding behind ice tombs).

LK

Necrotic plague action

Bots will now check before moving to the Shambling if they are in front of the Shambling to avoid getting one shoted by shockwave.
Improved multiplier, which will now properly handle dispelling of necrotic plague.

Winter phase action

Bots will properly move behind adds to avoid getting one shoted by shamblings or raging spirits.
If there is a hunter in the grouphunter will focus on spheres; if not, any ranged DPS will focus spheres.

Adds action

Bots will now be in proper positions during the 1st phase, and when the off tank is done collecting shamblings, it will move away from the group.
Bots (non-tanks) will move behind the shambling if they are in front of it to avoid getting one shoted in the 1st phase.
Restored action for checking if bots are at ground level, since they were still sometimes glitching through the floor (valkrys will be able to carry bots and drop them off the edge if not killed in time).
Improved defile calculations for 10 man and 25 man raids since defile was growing differently for 10 and 25, which would make bots in 25 man move very far away from somewhat small defile puddle.
Bots will now properly CC any valkyr that wasn't CC'd, and they won't freak out anymore if multiple valkyrs are present. (They can't tell which valkyr is holding bots/ players, so we should command an attack on valkyrs that are holding someone.)
Bots will now run away from Vile Spirits if they are targeted by them during the last phase.

* ICC 25HC ldw shades fix

Fixed bots could not detect shade if there were multiple present

* ICC trigger optimization

Optimized trigger and action for:

KineticBomb
OozePuddle

* ICC LK Improve

Improved Shadow Trap, Winter phase and 1st phase.

Bots will now have fixed positions for 1st phase if no shadow trap is present.

Tanks will now take care of taunting adds during winter phase. (Assist tank will collect adds and bring them to main tank, main tank will take over the adds so we have minimal chance of adds rotating towards the raid)

Fixed shadow trap detection.
2025-05-01 20:59:03 +02:00
bash
0e8a19b2fa check if already exist before apply (#1254) 2025-05-01 01:14:51 +02:00
Noscopezz
20e8ad21d5 ICC BQL crash fix and trigger/action optimization (#1252)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.

* ICC minor update

GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle if the room so that bots don't spread out too much which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP

* ICC LK minor update

Commented out z axis bypass since it was fixed with recent core updates.

Bots no longer fall thru buggy platforms so its no longer needed which in return makes valkyrs works as they should.

* ICC LM & LDW Improved

LM

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Simplified trigger for spike action, since attack logic is handled by skull RTI now.

Bots (tanks) will mark spikes with skull RTI, which will make bots instantly switch to Spike targets. If no spike is present, the boss will be marked.

Added logic that will make non-tank bots move away from LM to a fixed position behind LM if they happened to be in front of LM (No more insta kills with cleave).
If LM is casting Bone Storm, bots will ignore the above logic and do max dps.

LDW

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Bots (tanks) will mark adds with skull RTI, which will make bots instantly switch to adds targets. If no spike is present, the boss will be marked, which will help with keeping allies alive when they get mind controlled by LDW.

Moved 2nd phase position deeper into the room and reduced boss hp trigger to 95%, which will keep tanks where they should be during 1st phase (sometimes the boss dropped below 98% and tanks would ping pong around the room).

Ranged bots will now spread closer to each other now and will ignore spreading if they are 2 far or 2 close to the boss so they can properly reposition.

These changes should also fix recent bugs with bots not casting/standing still on LM and LDW.

* ICC DBS Improve

Replaced attack action with RTI. (Improved DPS)

Ranged bots will move away from blood beast if targeted by it now.

* ICC Sindragosa and LK Improve

Sindragosa

Improved tomb los for frost bombs. Bots will now mark tomb with moon rti to avoid killing it too soon. (If they still attack the tomb, simply reset and after bombs are over, simply attack the tomb to kill or mark with a skull.)
Main Tank will reset mystic buffet stacks now to avoid tank swapping since it's really unreliable which will make sindy less frustrating to kill (other bots will need to do mechanics properly by hiding behind ice tombs).

LK

Necrotic plague action

Bots will now check before moving to the Shambling if they are in front of the Shambling to avoid getting one shoted by shockwave.
Improved multiplier, which will now properly handle dispelling of necrotic plague.

Winter phase action

Bots will properly move behind adds to avoid getting one shoted by shamblings or raging spirits.
If there is a hunter in the grouphunter will focus on spheres; if not, any ranged DPS will focus spheres.

Adds action

Bots will now be in proper positions during the 1st phase, and when the off tank is done collecting shamblings, it will move away from the group.
Bots (non-tanks) will move behind the shambling if they are in front of it to avoid getting one shoted in the 1st phase.
Restored action for checking if bots are at ground level, since they were still sometimes glitching through the floor (valkrys will be able to carry bots and drop them off the edge if not killed in time).
Improved defile calculations for 10 man and 25 man raids since defile was growing differently for 10 and 25, which would make bots in 25 man move very far away from somewhat small defile puddle.
Bots will now properly CC any valkyr that wasn't CC'd, and they won't freak out anymore if multiple valkyrs are present. (They can't tell which valkyr is holding bots/ players, so we should command an attack on valkyrs that are holding someone.)
Bots will now run away from Vile Spirits if they are targeted by them during the last phase.

* ICC 25HC ldw shades fix

Fixed bots could not detect shade if there were multiple present

* ICC trigger optimization

Optimized trigger and action for:

KineticBomb
OozePuddle
2025-04-30 10:49:35 +02:00
St0ny
c1cbef40d7 Name fix (#1248)
Update and rename 2025_04_26.sql to 2025_04_26_00.sql
2025-04-28 22:16:39 +02:00
St0ny
1e93d14152 Add index on playerbots_random_bots to reduce deadlocks (#1247)
This commit adds a missing composite index on the `playerbots_random_bots` table
(`owner`, `bot`, `event`) to improve database performance during high playerbot
activity.

Adding this index significantly reduces the occurrence of deadlocks when multiple
threads access the random bots table simultaneously.

The change is 100% backward-compatible and does not affect existing data or
functionality.
2025-04-27 23:07:22 +02:00
EricksOliveira
fc9555b7d4 Travel: Fixed crash when trying to travel in maps with no nodes (#1171) 2025-04-27 12:52:48 +02:00
EricksOliveira
6d24db6999 Introduction of the SafeLearn(spellId) lambda that checks if the bot … (#1226)
* Introduction of the SafeLearn(spellId) lambda that checks if the bot already knows the spell before learning it.

This PR adds a safety check to the mount skill learning process in PlayerbotFactory::InitSkills, using a SafeLearn lambda to prevent the bot from trying to learn spells it already has. This fixes error messages like Duplicate entry when using the .bot init command.

* Check the bank and avoid error

* .

* fix
2025-04-27 12:50:48 +02:00
kadeshar
d8436b8270 - Added generic boss aura triggers and actions (#1242)
- Added Freya strategy
- Added or updated aura resistance strategies for ulduar
2025-04-27 12:48:16 +02:00
EricksOliveira
34a888978e Fix: Prevent concurrent bot initializations during .playerbot init= commands (#1227)
A simple RAII mechanism with std::unordered_set<ObjectGuid> to track GUIDs of init bots.

Ensures that multiple threads or calls do not execute PlayerbotFactory::Randomize() logic at the same time for the same bot.
2025-04-27 12:47:02 +02:00
NotCronky
a5e0e6f5cf Update LfgActions.cpp (#1225) 2025-04-27 12:43:56 +02:00
kadeshar
96d9b346c1 Crash fix for teleport action (#1245)
* - Crash fix for teleport action

* - Revert logic
2025-04-27 12:39:14 +02:00
Noscopezz
ca4897360f ICC 25HC LDW shade fix (#1241)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.

* ICC minor update

GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle if the room so that bots don't spread out too much which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP

* ICC LK minor update

Commented out z axis bypass since it was fixed with recent core updates.

Bots no longer fall thru buggy platforms so its no longer needed which in return makes valkyrs works as they should.

* ICC LM & LDW Improved

LM

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Simplified trigger for spike action, since attack logic is handled by skull RTI now.

Bots (tanks) will mark spikes with skull RTI, which will make bots instantly switch to Spike targets. If no spike is present, the boss will be marked.

Added logic that will make non-tank bots move away from LM to a fixed position behind LM if they happened to be in front of LM (No more insta kills with cleave).
If LM is casting Bone Storm, bots will ignore the above logic and do max dps.

LDW

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Bots (tanks) will mark adds with skull RTI, which will make bots instantly switch to adds targets. If no spike is present, the boss will be marked, which will help with keeping allies alive when they get mind controlled by LDW.

Moved 2nd phase position deeper into the room and reduced boss hp trigger to 95%, which will keep tanks where they should be during 1st phase (sometimes the boss dropped below 98% and tanks would ping pong around the room).

Ranged bots will now spread closer to each other now and will ignore spreading if they are 2 far or 2 close to the boss so they can properly reposition.

These changes should also fix recent bugs with bots not casting/standing still on LM and LDW.

* ICC DBS Improve

Replaced attack action with RTI. (Improved DPS)

Ranged bots will move away from blood beast if targeted by it now.

* ICC Sindragosa and LK Improve

Sindragosa

Improved tomb los for frost bombs. Bots will now mark tomb with moon rti to avoid killing it too soon. (If they still attack the tomb, simply reset and after bombs are over, simply attack the tomb to kill or mark with a skull.)
Main Tank will reset mystic buffet stacks now to avoid tank swapping since it's really unreliable which will make sindy less frustrating to kill (other bots will need to do mechanics properly by hiding behind ice tombs).

LK

Necrotic plague action

Bots will now check before moving to the Shambling if they are in front of the Shambling to avoid getting one shoted by shockwave.
Improved multiplier, which will now properly handle dispelling of necrotic plague.

Winter phase action

Bots will properly move behind adds to avoid getting one shoted by shamblings or raging spirits.
If there is a hunter in the grouphunter will focus on spheres; if not, any ranged DPS will focus spheres.

Adds action

Bots will now be in proper positions during the 1st phase, and when the off tank is done collecting shamblings, it will move away from the group.
Bots (non-tanks) will move behind the shambling if they are in front of it to avoid getting one shoted in the 1st phase.
Restored action for checking if bots are at ground level, since they were still sometimes glitching through the floor (valkrys will be able to carry bots and drop them off the edge if not killed in time).
Improved defile calculations for 10 man and 25 man raids since defile was growing differently for 10 and 25, which would make bots in 25 man move very far away from somewhat small defile puddle.
Bots will now properly CC any valkyr that wasn't CC'd, and they won't freak out anymore if multiple valkyrs are present. (They can't tell which valkyr is holding bots/ players, so we should command an attack on valkyrs that are holding someone.)
Bots will now run away from Vile Spirits if they are targeted by them during the last phase.

* ICC 25HC ldw shades fix

Fixed bots could not detect shade if there were multiple present
2025-04-25 10:46:25 +02:00
blinkysc
52f704dc79 Merge pull request #1235 from liyunfan1223/revert-1125-patch-17
Revert "Add possible crash fix when summoning an invalid bot"
2025-04-24 11:13:48 -05:00
blinkysc
3d6f925cca Revert "Add possible crash fix when summoning an invalid bot (#1125)"
This reverts commit 495269bfa0.
2025-04-24 11:04:18 -05:00
kadeshar
bf54f74359 - Added Kologarn Rubble slowdown strategy (#1220) 2025-04-22 13:28:51 +02:00
Cryo81
04b8b76362 ilvl calculation fixed warfury use case (#1222)
* War fury detection fixed in GetEquipGearScore.

* fixing indentation

---------

Co-authored-by: Julien MAS <julien.mas81@gmail.com>
2025-04-22 12:32:54 +02:00
Cryo81
07e4dec70d Warning fix + ilvl function fix (#1210)
* 1 variable order warning fixed
70 unused variable warning fixed

* Fixed GetEquipGearScore function

---------

Co-authored-by: Julien MAS <julien.mas81@gmail.com>
2025-04-20 14:26:42 +08:00
Noscopezz
eb3fa56829 ICC Sindragosa and LK Improve (#1216)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.

* ICC minor update

GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle if the room so that bots don't spread out too much which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP

* ICC LK minor update

Commented out z axis bypass since it was fixed with recent core updates.

Bots no longer fall thru buggy platforms so its no longer needed which in return makes valkyrs works as they should.

* ICC LM & LDW Improved

LM

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Simplified trigger for spike action, since attack logic is handled by skull RTI now.

Bots (tanks) will mark spikes with skull RTI, which will make bots instantly switch to Spike targets. If no spike is present, the boss will be marked.

Added logic that will make non-tank bots move away from LM to a fixed position behind LM if they happened to be in front of LM (No more insta kills with cleave).
If LM is casting Bone Storm, bots will ignore the above logic and do max dps.

LDW

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Bots (tanks) will mark adds with skull RTI, which will make bots instantly switch to adds targets. If no spike is present, the boss will be marked, which will help with keeping allies alive when they get mind controlled by LDW.

Moved 2nd phase position deeper into the room and reduced boss hp trigger to 95%, which will keep tanks where they should be during 1st phase (sometimes the boss dropped below 98% and tanks would ping pong around the room).

Ranged bots will now spread closer to each other now and will ignore spreading if they are 2 far or 2 close to the boss so they can properly reposition.

These changes should also fix recent bugs with bots not casting/standing still on LM and LDW.

* ICC DBS Improve

Replaced attack action with RTI. (Improved DPS)

Ranged bots will move away from blood beast if targeted by it now.

* ICC Sindragosa and LK Improve

Sindragosa

Improved tomb los for frost bombs. Bots will now mark tomb with moon rti to avoid killing it too soon. (If they still attack the tomb, simply reset and after bombs are over, simply attack the tomb to kill or mark with a skull.)
Main Tank will reset mystic buffet stacks now to avoid tank swapping since it's really unreliable which will make sindy less frustrating to kill (other bots will need to do mechanics properly by hiding behind ice tombs).

LK

Necrotic plague action

Bots will now check before moving to the Shambling if they are in front of the Shambling to avoid getting one shoted by shockwave.
Improved multiplier, which will now properly handle dispelling of necrotic plague.

Winter phase action

Bots will properly move behind adds to avoid getting one shoted by shamblings or raging spirits.
If there is a hunter in the grouphunter will focus on spheres; if not, any ranged DPS will focus spheres.

Adds action

Bots will now be in proper positions during the 1st phase, and when the off tank is done collecting shamblings, it will move away from the group.
Bots (non-tanks) will move behind the shambling if they are in front of it to avoid getting one shoted in the 1st phase.
Restored action for checking if bots are at ground level, since they were still sometimes glitching through the floor (valkrys will be able to carry bots and drop them off the edge if not killed in time).
Improved defile calculations for 10 man and 25 man raids since defile was growing differently for 10 and 25, which would make bots in 25 man move very far away from somewhat small defile puddle.
Bots will now properly CC any valkyr that wasn't CC'd, and they won't freak out anymore if multiple valkyrs are present. (They can't tell which valkyr is holding bots/ players, so we should command an attack on valkyrs that are holding someone.)
Bots will now run away from Vile Spirits if they are targeted by them during the last phase.
2025-04-20 14:25:21 +08:00
kadeshar
bc2b83e759 Resistance usage to ulduar strategy (#1212)
* - Added resistance usage to ulduar strategy

* - Fixed resistance strategies to affect only first required raid member
2025-04-20 14:23:36 +08:00
Jered
9be4b26424 Feat/onyxia raid strategy init (#1182)
* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* feat: init onyxia raid strategy

* Feat/onyxia raid strategy init fix (#1)

* feat: init onyxia raid strategy

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix

* feat: ony raid strategy init fix
2025-04-20 14:23:14 +08:00
EricksOliveira
27e3b802b7 Fix: Prevents bots from learning spells twice (#1211)
* Fix: Prevents bots from learning spells twice

Added bot->HasSpell() check before calling bot->learnSpell() to ensure the bot does not learn spells it already has.

This avoids redundant behavior, possible unnecessary logging, and inconsistencies in learning spells trained with SPELL_EFFECT_LEARN_SPELL.

* Possible fix
2025-04-18 23:04:35 +02:00
Paolo
7737f9ab72 Add additional trading options (#1186)
* Add addclass bots to trading list, differentiate between buying and selling.

* typos

* Try calling playerguid

* point IsAddclassBot to IsRandomBot

* typo

* Fix through IsAddClassbot

* Working Version

* Minor typos.
2025-04-17 11:52:14 +08:00
bash
2f549295d5 Added more defense programming (#1195) 2025-04-17 11:51:42 +08:00
kadeshar
9c816b682a Kologarn strategy (#1205)
* - Added triggers and action for kologarn fight

* - code refactoring

* - Added nature resistance aura for kologarn
2025-04-17 11:50:38 +08:00
Noscopezz
b5fa15dcd8 ICC LM, LDW & DBS Improve (#1202)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.

* ICC minor update

GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle if the room so that bots don't spread out too much which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP

* ICC LK minor update

Commented out z axis bypass since it was fixed with recent core updates.

Bots no longer fall thru buggy platforms so its no longer needed which in return makes valkyrs works as they should.

* ICC LM & LDW Improved

LM

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Simplified trigger for spike action, since attack logic is handled by skull RTI now.

Bots (tanks) will mark spikes with skull RTI, which will make bots instantly switch to Spike targets. If no spike is present, the boss will be marked.

Added logic that will make non-tank bots move away from LM to a fixed position behind LM if they happened to be in front of LM (No more insta kills with cleave).
If LM is casting Bone Storm, bots will ignore the above logic and do max dps.

LDW

Removed Attack Action since it was buggy and replaced it with RTI. (Improved DPS)

Bots (tanks) will mark adds with skull RTI, which will make bots instantly switch to adds targets. If no spike is present, the boss will be marked, which will help with keeping allies alive when they get mind controlled by LDW.

Moved 2nd phase position deeper into the room and reduced boss hp trigger to 95%, which will keep tanks where they should be during 1st phase (sometimes the boss dropped below 98% and tanks would ping pong around the room).

Ranged bots will now spread closer to each other now and will ignore spreading if they are 2 far or 2 close to the boss so they can properly reposition.

These changes should also fix recent bugs with bots not casting/standing still on LM and LDW.

* ICC DBS Improve

Replaced attack action with RTI. (Improved DPS)

Ranged bots will move away from blood beast if targeted by it now.
2025-04-17 11:50:09 +08:00
EricksOliveira
6ae96f19b9 Big update InviteToGroupAction.cpp (#1154)
* Group improvement: Bots will no longer auto-invite players who have DND enabled.

* Group fix: Bots will no longer invite self-bots to groups with dnd enabled.

* Invite fix: Bots will no longer invite DnD players from their guild.

* Guild group invite improvement: Lower level guildmembers may now invite higher level players to help them out.

* Crash fix: Bots inviting players into a group that are being teleported.

* Invite fix: Bots will no longer automatically convert to raid when inviting real players.

* Group fix: Bots now properly group up automatically again.

* Group fix: Bots no longer invite themselves to groups from the guild.

* Fix

* Fix build

* New Fix

* .

* ..
2025-04-11 23:42:29 +02:00
SaW
287875c436 Set Lockpicking Skill (#1140)
On init and on maintenance
2025-04-11 19:29:07 +02:00
Yunfan Li
19447c3914 Enable new rpg strategy by default (#1192)
* Add RandomBotMinLevelChance

* Save mana only for healer

* Disable addclass dk for low level player

* Target selection and debuff cast with less players in group

* Change default rpg strategy and bots count in config

* Logs clean up

* Improve init=auto

* Remove login logs after initialization

* Rndbots stats for quest

* Prediction chase in reach combat

* Poor & Normal items ensurence for init=auto
2025-04-11 20:31:38 +08:00
Yunfan Li
0d19f298da Loot packet fix (#1190) 2025-04-10 21:00:05 +08:00
kadeshar
fe519854a4 - Added skipping disperse tactic while bot is in stay stance (#1180) 2025-04-08 20:55:07 +08:00
Yunfan Li
3f52563ca7 Move LoadFromDB from player session to world session (#1173) 2025-04-08 20:54:51 +08:00
Yunfan Li
cd5b15ddc1 Fix keyring for low level bots (#1177) 2025-04-08 10:11:07 +08:00
Yunfan Li
2f3f8d565c Make battleground join / arena join / loot money session packet (#1178)
* Make battleground / arena join session packet

* Loot money

* Avoid aoe crash
2025-04-08 10:11:03 +08:00
tomcoffingiii
2fced71069 Update RaidIccActions.cpp - (#1174)
Add logic to gracefully handle bots falling off platform during LK phase 2 fight
2025-04-07 17:05:52 +08:00
EricksOliveira
3d743ccab3 Crash fix: Bots now properly turn their corpse into bones when resurrected so they don't have a second corpse after dying and releasing again. (#1165) 2025-04-04 21:56:56 +08:00
EricksOliveira
7446d0b1d4 Summon improvement: Selfbot no longer complains about being unable to… (#1166)
* Summon improvement: Selfbot no longer complains about being unable to summon to itself.

* Fix build

* .
2025-04-04 21:56:22 +08:00
kadeshar
dccbccc090 - Added Biting Cold cheat (#1131) 2025-03-31 22:47:30 +08:00
EricksOliveira
a50dc87dbc Fixed crash in MoveFromWhirlwindAction::Execute function (#1150)
* Fixed crash in MoveFromWhirlwindAction::Execute function

This PR fixes a crash in the MoveFromWhirlwindAction::Execute function in NexusActions.cpp. The error occurred when accessing boss->GetPosition() without checking whether boss was a valid pointer. The fix adds a nullptr check before calculating the distance, preventing invalid accesses and ensuring the stability of the action execution.

* Fix comment
2025-03-31 22:47:13 +08:00
Yunfan Li
7676fd6427 Fix multithread issue on LFG and group leave (#1143) 2025-03-31 22:46:27 +08:00
Revision
21020b4564 Merge pull request #1153 from NoxMax/NoxMax-patch-1
playerbots.conf.dist comment fixed
2025-03-31 01:34:51 +02:00
NoxMax
31de2a0f32 playerbots.conf.dist comment fixed
Fixed comment for BotActiveAlone, now that its default value has been changed from 10% to 100%
2025-03-30 14:27:37 -06:00
EricksOliveira
3faa3c639a This update adds null pointer checks and extra validations to the AttackAnythingAction::isUseful() method, preventing invalid accesses that could cause crashes. (#1135)
Checking bots and botAI before method calls.

Validating targets and confirming if they are still in the world (IsInWorld()).

Adding debug logs (LOG_DEBUG) to make it easier to identify issues.
2025-03-29 10:58:57 +01:00
EricksOliveira
ad8c42d81b Crash fix: Bots inviting teleported players. (#1142) 2025-03-29 10:57:24 +01:00
Paolo
917c96a281 Add config option for RND bot trading. (#1132)
* Add config option for RNDbot trading.
2025-03-28 16:10:49 +01:00
EricksOliveira
495269bfa0 Add possible crash fix when summoning an invalid bot (#1125) 2025-03-28 16:08:40 +01:00
EricksOliveira
d2204d41e2 Fix crash in trade status action (#1123)
* Fix crash in trade status action
2025-03-28 16:08:05 +01:00
mostlynick3
50200584d1 Correct UseMeetingStoneAction to only apply on meeting stone portals 2025-03-28 16:01:09 +01:00
EricksOliveira
8f92fbade3 BG crash fix: Fixed a crash when the bot was marked as being inside a battleground but had no battleground. (#1122) 2025-03-26 20:48:36 +08:00
Yunfan Li
d9da6d942d Make make a full check before questgiver choose such as reputation (#1109) 2025-03-26 20:47:46 +08:00
kadeshar
feb7bb8a8b Added Vault of Archavon strategy with Emalon tactics (#1117) 2025-03-25 13:28:53 +01:00
EricksOliveira
105b16358f BG: Crash fix when bots are trying to determine the eye flagcarrier when the battleground no longer exists (#1119) 2025-03-25 13:27:13 +01:00
EricksOliveira
08b77acd8d Chat: Fix index out of bounds crash in case verb_pos equals zero (#1115)
Prevents invalid accesses to the word[] array, preventing possible crashes.

Improves the message selection logic in bot chat.

Fixes an error in the switch-case structure, ensuring that all possible messages are used correctly.
2025-03-24 21:57:39 +08:00
avirar
c83cf0706a ItemUsageValue: Handle items that create required items (#1091)
* Updated IsItemUsefulForQuest to handle items that create required quest items

* Debug output

* Removed unneeded botAI->

* Debug output in Calculate

* -> not .

* Comprehensive debug output for quest usage

* Corrected logic for lootable items when sync quest is enabled

* #include "LootObjectStack.h"

* Corrected call to IsItem

* Removed debug statements

* Reimplement ItemCount >= RequiredItemCount

* Modified CanLoot to loot all items when loot source is an item in their bags

* Set loot target when sending Open packet
2025-03-24 21:47:25 +08:00
mostlynick3
47ffe37519 ICC - Implement Val'kyr grabbing bots and dropping (#1098)
* ICC - Implement Val'kyr grabbing bots and dropping
2025-03-24 11:26:21 +01:00
Yunfan Li
e319334b03 Fix frost nova crash (#1106) 2025-03-22 13:59:32 +08:00
Noscopezz
76830796e9 ICC minor update (#1104)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.

* ICC minor update

GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle if the room so that bots don't spread out too much which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP

* ICC LK minor update

Commented out z axis bypass since it was fixed with recent core updates.

Bots no longer fall thru buggy platforms so its no longer needed which in return makes valkyrs works as they should.
2025-03-21 20:20:25 +08:00
kadeshar
9ddc71a9d7 - Changed Eye of Eternity healers selection (#1102)
- Added Iron Assembly strategies for normal mode
- Improved Hodir Biting Cold strategy
2025-03-21 20:19:59 +08:00
SaW
28be2b13c3 Optimize Mountaction: Movement Logic with Early Return for Matching F… (#1099)
* Optimize Mountaction: Movement Logic with Early Return for Matching Forms or Speed

Added a missing check, so if both master and bot are in matching forms or master is mounted with corresponding speed, early return as there is nothing to do.

This improves logic, actions, and prevents some strange movement behavior when both master and bot already are in travel form.
2025-03-20 19:53:56 +01:00
kadeshar
3d6d454337 Stay strategy improvement (#1072)
* - Stay Strategy work in combat and with RTSC

* - Fixed summon with stay strategy

* - Added new stay strategy support for chat commands
2025-03-20 10:53:16 +01:00
Yunfan Li
f039e88393 Fix faction count calculation error (#1085)
* Fix faction count on add randombots

Co-authored-by: kadeshar <kadeshar@gmail.com>

* Fix class balance issue with periodic login and logout

---------

Co-authored-by: kadeshar <kadeshar@gmail.com>
2025-03-17 19:40:03 +01:00
Yunfan Li
015d6605a6 Fix move npc action (#1087) 2025-03-17 23:52:41 +08:00
avirar
c4a4d3a9e6 Rogue bots can unlock items in their bags and in the trade window (#1055) 2025-03-17 15:10:33 +01:00
kadeshar
c93bf38463 - Fixed checking MaxAddedBots (#1083) 2025-03-17 15:47:48 +08:00
xSparky911x
54c8909ddb add ability to add or remove character with same name as account (#1070)
* add ability to add or remove character with same name as account

* seperate bot add and bot addacount so that characters with same name as an account doesn't add all toons from that account but adds the character instead if so desired
2025-03-16 12:45:42 +08:00
Yunfan Li
0fabf174c0 Fix rpg game objects quest accept and reward (#1080) 2025-03-15 17:50:00 +01:00
Yunfan Li
38912d4a8a Auto do quest feature (new rpg strategy) (#1034)
* New rpg startup speed up and refactor

* New rpg do quest

* Fix invalid height in quest poi

* Add quest accept and reward limitation

* New rpg quest improvement

* Organize quest log, reward quests and fix grind target

* Quest dropped statistic and remove redundant code

* Decrease grind relevance lower than loot

* Fix new rpg drop quest

* Go to reward quest instead of innkeeper when quest completed

* Fix incorrect logic in do quest reward

* Fix reset quests in factory

* Fix crash on grind target value

Co-authored-by: SaW <swerkhoven@outlook.com>

* Fix a minor error in DoCompletedQuest

* Let bots get rid of impossible quests faster

* Increase loot fluency (especially for caster)

* Remove seasonal quests from auto accept

* Enhance quest accept condition check

* Add questgiver check (limit acceptation of quest 7946)

* Questgiver check and localization

* Near npc fix

* Fix quest item report

* Add lowPriorityQuest set for quests can not be done

* Improve gameobjects loot

* Do complete quest

* FIx move far to teleport check

* Accept or reward quest from game objects

* Fix possible crash in rpg game objects

* Fix ChooseNpcOrGameObjectToInteract crash

---------

Co-authored-by: SaW <swerkhoven@outlook.com>
2025-03-14 21:31:33 +08:00
SaW
88356bb507 Prevent crash on update SQL (#1076)
Delete entries before adding to avoid duplicates.
2025-03-14 08:40:55 +01:00
kadeshar
e1f11fa2f2 - Code refactoring in RaidUlduarActions (#1065) 2025-03-08 12:42:08 +01:00
Yunfan Li
24efa7efa2 General improvement on init and strats (#1064)
* Potions strats and potions init

* Druid and shaman spell in low level

* Ammo init improvement

* Rogue low level

* Fix melee attack action (for caster with no mana)

* Disable pet spells that reduce dps

* Talents improvement

* Remove CanFreeMove check

* Reduce penalty for non-dagger weapon for rogue
2025-03-08 12:36:06 +01:00
Revision
7dff970e37 Merge pull request #1063 from kadeshar/freya-strategies
Freya strategies
2025-03-06 22:36:43 +01:00
kadeshar
7c49a7b681 - Added tactic for Freya Nature bomb
- Added tactic for Freya Eonar's gift
2025-03-06 19:06:27 +01:00
SaW
4f43600e7a Silence error if preferred mounts SQL table playerbots_preferred_mounts does not exist (#1062)
* Fix error spam if DB does not exist
2025-03-06 15:03:23 +01:00
avirar
f7f949eda4 Item Usage and Loot Roll (#1059)
* Better Disenchant and final AH usage

* CalculateRollVote instead of just needing on items allowed by StoreLootAction::IsLootAllowed
2025-03-06 13:39:33 +01:00
xSparky911x
92d63c7cbc fix classbots autogear not working when altbots autogear turned off (#1060)
* fix classbots autogear not working when altbots autogear turned off
2025-03-06 13:31:46 +01:00
SaW
b9747fdd69 Reinstate cached preferred mounts (#1058) 2025-03-05 17:24:54 +01:00
valsan-azerty-boi
a4fe45afbb Fix server crash when bots apply strategies on a custom naxx raid (#1052) 2025-03-04 20:35:36 +01:00
SaW
bf22f20997 Fix: Bots not mounting in BG's anymore (#1056)
Bots didn't stop as they were supposed to, leading to some issues.
2025-03-04 13:42:41 +01:00
SaW
13a4dde643 Avoids the possible incorrect swimming state when bots coming ashore (#1051)
Improves the check for when in/under water, avoiding the possible incorrect swimming state when bots coming ashore (shortly swimming in air).
2025-03-03 15:10:47 +01:00
SaW
fe21dfe48e Fix/Feature: Bots can use travel/flight Shapeshift where appropriate (#1042) 2025-03-03 15:10:35 +01:00
avirar
9edddc5b26 Hunter equip bug (#1050) 2025-03-03 15:09:47 +01:00
Yunfan Li
d8cb75d376 Fix m_CastItem in CastSpell (#1047)
Fixed issues where some items and spells bypass item level requirement or use incorrect item level.
2025-03-02 20:20:51 +01:00
SaW
098950ceea Fix SpecialSpells to be correctly applied (#1044) 2025-03-01 22:42:58 +01:00
SaW
9fbf60d812 Resolve most warnings - PlayerbotAI (#1025)
Resolve most warnings - PlayerbotAI

---------

Co-authored-by: blinkysc <37940565+blinkysc@users.noreply.github.com>
2025-03-01 14:19:07 +01:00
Yunfan Li
fbfcbbcddc EnablePeriodicOnlineOffline config and modify CalculateTotalAccountCount (#1043)
* EnablePeriodicOnlineOffline config

* Add Comments on PeriodicOnlineOfflineRatio
2025-03-01 21:05:43 +08:00
Yunfan Li
9ff0e8e94d ChatHelper link localization (#1036) 2025-03-01 11:18:05 +08:00
Dennis
e540875b9c dynamically load database names for cleanup queries (#1040)
* dynamically load database names for cleanup queries
2025-02-28 18:39:28 +01:00
Yunfan Li
a3e305fbed Improve XP rate config (#1035) 2025-02-28 01:05:08 +01:00
blinkysc
67d805f700 Cleanup Database More (#1032)
* Resolve conflicts

* format
2025-02-27 14:34:26 +08:00
blinkysc
17672bd5b5 Properly cleanup database with playerbot delete (#1027)
Properly cleanup appropriate databases when AiPlayerbot.DeleteRandomBotAccounts is set to 1
2025-02-26 19:19:11 +01:00
SaW
20a69db45a Githubactions - Cancel workflow fix (#1029)
Fix: Cancels the obsolete tasks as desired.
2025-02-26 18:57:31 +01:00
SaW
c697b81404 Githubactions - Cancel workflow on new commits in the same PR (#1028) 2025-02-26 16:44:44 +01:00
avirar
3a4e8e729b Allow bots to enter all TBC dungeons (rep/keys/quest attunements) (#1014)
Update will allow any adequately leveled bot to queue for all random and specific TBC dungeons. Normal and Heroic modes that require attunement or keys will be accessible by bots.

InitReputation: Level 70+ Bots will receive Honored rank for all the required factions needed for Heroic keys to function. I've placed the calls to InitRep before InitMounts, I feel we can do something with that in the future. Randomised rep values might allow bots to obtain other mounts?
InitKeyring: All bots receive all non-rep required keys (Shattered Halls Key, Shadow Labyrinth Key, Key to the Arcatraz), and bots with the required rep (Honored) get the other keys.
InitAttunementQuests: Level 60+ bots complete the Caverns of Time and Magister's Terrace attunement quests.
Updated acore_playerbots SQL; playerbots_dungeon_suggestion_definition; max_level increased to 73 (from 70) for all TBC Heroics and Magister's Terrace nomal. Allows more level appropriate bots to join.
2025-02-26 15:55:16 +01:00
SaW
2766d553c7 Maintenance command to retain defined special spells (#1024)
fixes a bug that caused the maintenance command to have bots lose the special spells
2025-02-26 13:32:26 +01:00
kadeshar
4968245471 - Fixed Hodir strategy bugs (#1015) 2025-02-24 20:11:29 +01:00
Yunfan Li
95c2ba9105 Permission check and readability improvements (#997)
* AiFactory check by spell instead of level

* Ignore group security for guild invitation
2025-02-23 20:09:59 +01:00
SaW
114eeb3b37 Fix chat and beautify server promo box (#1008)
* Fix chat and beautify server promo box
* Remove all unnecessary hooks

---------

Co-authored-by: sudlud <sudlud@users.noreply.github.com>
2025-02-23 13:29:19 +01:00
sudlud
326637c93b add enabled hook lists for performance improvement (#1004) 2025-02-22 23:38:26 +01:00
SaW
a28e2bbb4b Disable Hire command (#1003)
Not correctly implemented at this time, will cause crash and other issues, as it would change the bot to the requester's account.
2025-02-22 23:37:53 +01:00
Yunfan Li
62e0235e73 Scripts and sessions update to align with acore (#987) 2025-02-22 12:08:53 +08:00
SaW
a44650c7f6 Include pvp as default non-combat strat for alt/class bots (#1001) 2025-02-22 10:59:18 +08:00
Yunfan Li
4b1febc62a Minor improvments on logs, stats weights and aoe distance calculation (#995)
* StatsCollector for paladin spell

* Remove error log on MoveFromGroup

* Log and timer for CreateRandomBots

* Improve aoe trigger distance calculation

* Reduce spirit weights for heal priest and paladin
2025-02-22 10:57:33 +08:00
avirar
a0278f1efb Hunter ammo equip bug and other issues with BuyAction.cpp (#986)
Resolves #947

Equip logic was failing as projectiles were never returning ITEM_USAGE_EQUIP in ItemUsageValue.cpp, added two cases where equip is returned:

If no ammo is currently set
If new ammo has higher DPS than old/currently equipped ammo
While testing this using "b [itemlink]" and "b vendor" to purchase arrows I noticed some issues with BuyAction.cpp and have resolved them:

Bots will now perform the "equip upgrades" action for any bought item that has an equip usage
When using "b vendor" to buy all useful items from vendors within interaction distance, it now sorts the list of available items by calculated item score and buys the highest scoring item (if it is higher than the currently equipped item) for each slot. It should not buy multiple items for the same slot anymore, saving gold/emblems/etc.
"b vendor" will now only attempt to buy 1 of each item. Consumable and projectile item types can be bought up to 10 times per execution as long as it is still useful to buy the item in each iteration of the for loop. All items were following this behaviour previously and since the equip command was only given after the for loop it would buy 10 of an item before triggering it wasn't useful to buy more.
And finally, resolved issues where a bot runs out of ammo mid-fight:

Re-enabled combat and non-combat "no ammo" strategies to perform "equip upgrades" action.
Modified GenericTriggers.cpp; AmmoCountTrigger::IsActive to return true when the bot has ammo but it is not equipped yet.
2025-02-21 18:32:10 +01:00
Yunfan Li
e33c61e90a Fixes on naxxramas heigan and thaddius (#994)
* Fix naxx thaddius

* Fix naxx heigan strats
2025-02-21 17:53:07 +01:00
Yunfan Li
0a76fc1d5f Better tank target selection (#996) 2025-02-21 16:20:33 +01:00
SaW
419e96e5aa Revert expireActionTime (#991)
* Revert expireActionTime

* Revert expireActionTime

* Revert RemoveExpired

* Revert RemoveExpired

* Revert RemoveExpired

* Revert Action expiration
2025-02-21 11:32:00 +08:00
SaW
61333a02bf Avoid creating accounts if both maxRandom & ClassBots are set to zero (#984)
Fix for https://github.com/liyunfan1223/mod-playerbots/issues/978
2025-02-19 09:46:28 +01:00
Yunfan Li
bb729e35b9 Fix stuck on knockback, enhance movement & flee and trap weave strats (#980)
* Hunter trap weave strats

* Do not allow actions to stack

* Remove trap weave by default

* Refactor on Engine

Co-authored-by: SaW <swerkhoven@outlook.com>

* Remove unused funcs in Queue

* Remove ExpireActionTime config

---------

Co-authored-by: SaW <swerkhoven@outlook.com>
2025-02-18 22:55:44 +08:00
SaW
6353c86b53 Change "Initializing guilds..." from INFO to DEBUG (#982)
To avoid it being needlessly spammed in the console.
2025-02-18 11:59:13 +01:00
kadeshar
050cc24e9c Hodir tactics (#977)
* - Added tactic for Hodir Biting Cold ability

* - Added tactic for Hodir Flash Freeze
- Modified tactic for Hodir Biting Cold
2025-02-17 22:22:46 +08:00
SaW
58a596a40e Only invoke InitGuild when randomBotGuildCount > 0 (#975)
* Only invoke InitGuild when randomBotGuildCount > 0

* Moved Random bot guild count/delete to more appropriate section of config.
2025-02-16 13:42:15 +01:00
kadeshar
6749a4257b - Added protection for unparsable data in worldposition contructor (#974) 2025-02-15 17:18:34 +01:00
SaW
624e48068e Autocalc Accounts - take rotation into account (#971)
* Takes bot rotation into account and adjust accordingly when enabled as it requires to be higher than MaxRandomBots to function properly.
* Correct default config to reflect that bots pool size for rotation should be higher than MaxRandomBots
* Revert space at start of all lines.
2025-02-14 23:31:26 +01:00
Revision
dfcfe46865 Replace tabs with spaces (#973) 2025-02-14 20:12:02 +01:00
Yunfan Li
49b046f36c Allow addclass bots that are not in a real guild (#970) 2025-02-14 18:45:17 +01:00
SaW
4793644a15 Auto calculate RandomBotAccountCount by default (#964)
* Remove RandomBotAccountCount requirement

* Remove RandomBotAccountCount

* Remove randomBotAccountCount

* Remove randomBotAccountCount

* Update playerbots.conf.dist

* Style

* Set RotationPoolSize to 20 to work with the bot amount defaults

* Update PlayerbotAIConfig.cpp: Sync with default config

* Set +1 where appropriate

* Acc patch (#73)

* Account for TBC
* Still made it possible to change manually if desired

* uint32 randomBotAccountCount;

* Update Playerbots.cpp
2025-02-14 22:03:53 +08:00
SaW
c2caf3c564 Re-instate random bots guilds (#969)
I believe this should have been enabled again at some point.
2025-02-14 21:48:10 +08:00
kadeshar
bf195efaea - Fixed loading WorldPosition from string to fix RTSC points loading (#965)
- Restored loading from playerbots_db_store
- Added deletion before saving to playerbots_db_store
2025-02-13 11:39:20 +01:00
Sascha
ab7acfbdfc edit to announcement (#967)
* German full translation

With the power of ChatGPT i translated all chatter texts into German locale.
Insterted the German texts into text_loc3.
Everything else should stay unchenged.

* forgot headline

* Edit to announcement

fits better into the AC MotD and looks much better
2025-02-13 11:37:36 +01:00
Yunfan Li
f10e3c0fb1 Add announcement on server initialization and character login (#963)
Add announcement on server initialization and character login.

For repack distribution and public server host, avoid unintentional violations of AGPLv3.0 license.
2025-02-12 17:06:18 +01:00
SaW
6cb1599b52 CheckMountStateAction refactor Final (#960)
- Fix for the issue that bots occasionally moved awkward when mounted inside BG's
- Removed redundant mount data retrieval
- Removed redundant extra check on if carrying a flag (already covered in isUseful)
- Removed no longer necessary code
- Combined some conditions as having them separate made little sense anymore
- Moved checking carrying flag into the BG logic
2025-02-11 11:39:29 +01:00
Sascha
d7b3843024 German full translation (#961)
* German full translation

With the power of ChatGPT i translated all chatter texts into German locale.
Insterted the German texts into text_loc3.
Everything else should stay unchenged.
2025-02-10 22:57:24 +01:00
Yunfan Li
2c224d3121 Add LimitTalentsExpansion config (#954) 2025-02-09 21:50:04 +08:00
kadeshar
08008a3155 Worldbuff startup fix (#951)
* - [Performance] Fixed world buff loading from config file

* - [Refactoring] Changed mathod name
2025-02-08 12:31:06 +01:00
Noscopezz
db33cecf36 ICC minor update (#950)
GS

Bots will mark mage with skull rti

Rotface

Fixed bots glitching thru walls and floors (added check if position is valid before moving)

PP

Bots will mark volatile ooze with skull rti now which will help them focus it and kill asap (usefull for heroic when both volatile ooze and gas cloud are present at the same time)

VDW

Added default group position in the middle of the room so that bots don't spread out too much, which will force them to focus supressers more

Fixed Boss healers not keeping themself alive when low on HP
2025-02-07 18:45:26 +01:00
Yunfan Li
14bdc0ec5a Always allow addclass bots login and init (#946)
* Change the way to check addclass bots and allow adding them by characters name

* Always addclass bots login and init

* Comments and message
2025-02-05 12:56:37 +08:00
SaW
308c0b437e BattleGrounds: Refactor and Fix bots re-spawning when graveyard meanwhile gets lost (#937)
* Update ReleaseSpiritAction.cpp

* Update ReleaseSpiritAction.cpp

* Update ReleaseSpiritAction.cpp

* Update ReleaseSpiritAction.cpp

* Update ReleaseSpiritAction.h

* Update ReleaseSpiritAction.h

* Update ReleaseSpiritAction.cpp

* Update ReleaseSpiritAction.cpp

* Update ReleaseSpiritAction.cpp

* Refactor (#68)

* Refactored ReleaseSpiritAction.cpp

* Ref ReleaseSpiritAction.h

* Restore comment
2025-02-04 13:30:35 +01:00
Noscopezz
fb683b3846 ICC Sindragosa minor improve (#943)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically

* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.

* ICC BPC major update, fix and improve

Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading(ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.

* ICC BQL/VDW major update + minor fixes/improvements

LDW improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid). Druid will be assigned to raid healing if no druid present then some other random heal class. Added rotations for druid healers if they end up healing the boss. Raid healers will not use portals anymore. Healers will come to the ground now after using portals (they were stuck in air)

* ICC LK minor update

PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase

* ICC minor Sindy improve

Reduced position tolerances and forced movement for beacon and non beacon positions which will make bots move to spot that they actually need to be at instead of randomly running to sindragosa or beaconed players.
2025-02-04 19:42:09 +08:00
Yunfan Li
9bbe183763 Improve random accounts creation (#942)
* Duplicate name check and improve name cache

* Sync wait for the first time creation of random bots
2025-02-03 16:39:45 +01:00
achyles222
1c2ec60e6b Added Frostfire spec for fire mage (#936) 2025-02-03 19:48:41 +08:00
Yunfan Li
fef67081ec Improve login and init permission for rndbots and addclass bots (#930)
* Improve login and init permission for rndbots and addclass-bots

* Add AllowAcountBots config

* Update config description
2025-02-03 19:46:49 +08:00
SaW
f5a8b3017e BattleGround: Fix bot's already cast (ranged) spells to be redirected to bot's ghost on death (#934)
* Update ReleaseSpiritAction.h - add bg_release_time

* Update ReleaseSpiritAction.cpp

* Update ReleaseSpiritAction.cpp - Move LOG_DEBUG

Correct LOG_DEBUG position.

* Reliable fix (#67)

Reliable fix

* Reduced wait time from 8 to 6 min

* Update comment
2025-02-02 01:39:57 +01:00
SaW
e07a9e194a MSA Improvement Part 2 (#66) (#933)
Reduce iterations.
2025-02-01 20:23:25 +01:00
Noscopezz
6719d61ae0 ICC LK minor update (#931)
PP

Removed pre stacking for ranged when volatile ooze spawn (they will kill it much faster now and only stack if someone actually gets targeted by ooze)

LK

Hunters will use trnaq shot to remove enrage from shamblings

Improved valkyr cc

Minimized ping-ponging during winter phase
2025-01-31 17:48:33 +01:00
Atidote
a8a31a2e2f French full translation (#918) 2025-01-30 17:09:03 +01:00
Noscopezz
bdf8c6cc14 ICC BQL/VDW major update + minor fixes/improvements (#929)
LDW
Improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS
Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS
Ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut
Ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL
Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW
Boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid).
Druids will be assigned to raid healing if no druid present then some other random heal class.
Added rotations for druid healers if they end up healing the boss.
Raid healers will not use portals anymore.
Healers will come to the ground now after using portals (they were stuck in air)
2025-01-30 17:07:01 +01:00
blinkysc
d770e0a9a0 fix(BotAI/BattleGrounds) Bots AI improved based around capture points (#927)
* Less Flag Derp

* Comments
2025-01-30 14:16:59 +01:00
avirar
27b86f8b1f Eye of the Storm changes (#924)
* EoTS: Changed FC logic to use MoveNear while not in combat

Similar to WSG commit from a few days ago

* Changed action priorities in EotS to ACTION_MOVE + x

* Adjusted EotS flag carrier objective selection

Random chance reduced from 1/2 to 1/3
Distance threshold before objective switch is considered reduced to 15.0yds
2025-01-30 14:16:34 +01:00
avirar
0c8785d8d1 Resolved issues with herb gathering (#926)
* Check game objects loot tables and determine if loot is valid

* Removed LOS checks since they already occur and removed enemy near node check

* Dismount if mounted, decresed interaction distance, added looting delay

* Decreased interaction distance

* oops, wrong file

* Check game objects loot tables and determine if loot is valid
2025-01-30 00:29:17 +01:00
avirar
247c67e449 CheckMountStateAction: Added SPELL_AURA_TRANSFORM and IsInDisallowedMountForm (#923)
Resolved issue where bots are transformed (e.g Deathbringer's Will trinket) and would stand still attempting to mount, still allows mounting when the transform allows it (e.g Pirate Costume, Transporter Malfunction)
2025-01-29 12:37:24 +01:00
avirar
249aaf69e4 Arena team type is included in the LOG_INFO output (#925) 2025-01-29 10:39:17 +01:00
Noscopezz
e248fdc9e6 ICC BPC major update, fix and improve (#920)
Fixed main tank sometimes not tanking both bosses (vala and talda)

Improved marking of current prince

Empowered vortex: bots will now spread out when it is being cast, instead of always spreading (ranged). This will make melee also spread better now since bots will calculate and move to optimal positions.

Added Kinetic bomb handling.
Hunters will take care of bombs, if no hunter is present then any ranged dps will take care of kinetic bombs.
2025-01-28 21:25:11 +01:00
SaW
f52f999c09 Refactor of the CheckMountStateAction class (#919)
* Update CheckMountStateAction.cpp

The refactoring focused on improving readability, reducing redundancy, and optimizing performance where possible.

* Update CheckMountStateAction.h

* Update CheckMountStateAction.cpp

* Update CheckMountStateAction.cpp

* Update CheckMountStateAction.cpp

* Update CheckMountStateAction.h

* Fix lowest level mount from config

* Properly fix

* Reduced masterInShapeshiftForm lookups to 1

Reduced masterInShapeshiftForm lookups to 1

* Fix for missing useFastGroundMountAtMinLevel

* Final commit: Ensure max 99 speed in BG
2025-01-28 09:08:21 +01:00
Noscopezz
a8d8f37019 ICC Festergut 10 man fix (#915)
* ICC Festergut 10 Man fix

There was a rare case in 10 Man when 2 tanks would get spores which made them both stack at melee spot. Now the code will check if any of the spored player is main tank, if it is, it will stay at melee and other spores will go at ranged spot since off tank doesn't really need to stand near main tank all the time.
2025-01-26 21:04:48 +01:00
Yunfan Li
e571694a88 Reset added rndbots on server restart to automatically apply configuration changes (#913)
* Refactor RandomPlayerbotMgr and delete add value on restart server

* Remove reset tips in conf file
2025-01-26 12:06:29 +01:00
Yunfan Li
05db6f67b4 Add stuck fallback for rpg move far (#914) 2025-01-26 12:03:34 +01:00
Noscopezz
44734db421 ICC improve Rotface (#911)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25

* ICC fixed missing A/H buff

Fixed missing ICC buff for A and H

Buff will only be present when logged on and in ICC, once any bot or player leave ICC the buff is gone to prevent abuse.

This will make ICC easier now and with recent DPS update and movement improvement bots will now actully do decent dps and even greater healing.

Ally buff
https://www.wowhead.com/wotlk/spell=73828/strength-of-wrynn

Horde buff
https://www.wowhead.com/wotlk/spell=73822/hellscreams-warsong

* revert last change

revert buff

* ICC improve Rotface

Bots will now mark Rotface with skull icon, which will make them focus boss instead of oozes automatically
2025-01-25 21:09:44 +01:00
SaW
7287d14dc6 Update formation info to reflect chaos as default (#910)
As the default formation was recently switched to chaos.
2025-01-25 20:04:47 +01:00
SaW
2ebeb244ec Fix bot swimming behavior at the surface and in shallow waters (#908)
- Fix for Bots don't swim properly near the surface #903
- Prevents bots teleporting/warping to the surface when in (shallow) waters.
2025-01-25 16:30:47 +01:00
Yunfan Li
f0d4273e4a Improve gear initialization (#909)
* Druid and paladin rotation

* Improve spell effect collector for gear init

* Fix mount and hit stat calculator
2025-01-25 14:07:36 +01:00
Jay
84e24306fc Update README.md (#899)
Updated the Docker section to instruct users to use docker-compose.override.yml instead. Additionally added :ro at the end of the volumes mountpoint for modules, and gives a short example of how to use config settings as environment variables.
2025-01-24 19:12:45 +01:00
blinkysc
0c2f14d97f Refactor Bot engine Queue (#895)
* Update Queue.cpp

* Update Queue.h
2025-01-24 19:09:12 +01:00
jublinq
9e967b7784 Add undead-rogue to rndbots (#901) 2025-01-24 19:08:37 +01:00
kadeshar
7563ab0c79 Fixed swimming value calculation (#897) 2025-01-23 23:41:24 +01:00
Noscopezz
08e331371d ICC sindy Improve (#896)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved

* ICC improve Sindy

Bots will now choose non beacon position based on difficulty, 10/25
2025-01-23 21:44:53 +01:00
avirar
f27624aa6e Removed mount action in "protect fc" + reduced support bot chance (#892) 2025-01-23 11:42:31 +01:00
avirar
1e9fd1607a Tweaked Alterac Valley so bots kill final bosses (#886)
* Updated AV strategy so only 2 towers need to be down before final boss

* Adjusted role assignments for AV: less defenders, more forward attackers

* Added strategy for team has flag in WSG

team has flag triggers bg protect fc action @ 75 priority

* Updated protectFC function with MoveNear instead of follow
2025-01-22 16:45:09 +01:00
SaW
4e7d00b1a3 BG: restore !bot->IsInWorld() check (#891)
* Update RandomPlayerbotMgr.cpp

* Restore !bot->IsInWorld()
2025-01-22 16:44:44 +01:00
SaW
d3e3372121 BG: Final fix against potential inconsistencies
* Check both bgInstanceCount / bgInstances.size

to help counter against possible inconsistencies

* Final fix against inconsistencies
2025-01-22 14:12:38 +01:00
Noscopezz
2574b66527 ICC fixes GS, PP, BQL, SINDY (#885)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc

* ICC fixes GS, PP; BQL, SINDY

Minor fixes, bite action improved
2025-01-22 10:35:25 +01:00
SaW
c6a332a729 Fix over-queuing in BG's (#887)
* Fix overqueue

* Update RandomPlayerbotMgr.cpp

* Restore if self-bot

* Update RandomPlayerbotMgr.cpp
2025-01-22 10:33:51 +01:00
Yunfan Li
f6cc3f6e40 Improve ICC spread and fix Valithria trigger (#884)
* Temp fix valithria find target

* Improve spread with FleePosition

* Fix Valithria trigger
2025-01-21 20:24:06 +01:00
AzoraNova
b0ca0e8595 Additional Chatter Lines to ai_playerbot_texts.sql (#864)
I've updated ai_playerbot_texts.sql and added over 900+ new lines for the bots to use in-game, including a mix of humorous and standard lines, along with a nod to the classic Barrens chat. This update is designed to make the game feel more immersive by providing the Playerbots Module with more dialogue options as you play.
2025-01-20 22:24:44 +08:00
SaW
be21018f0c Feature: Have bots auto join/start all supported BG's (if enabled) (#877)
* Update RandomPlayerbotMgr.cpp

* Update playerbots.conf.dist

* Update PlayerbotAIConfig.h

* Update PlayerbotAIConfig.cpp

* Update playerbots.conf.dist

* Update playerbots.conf.dist

* Updated information

* Update RandomPlayerbotMgr.cpp

Avoid reverting https://github.com/liyunfan1223/mod-playerbots/pull/870/files

* Update playerbots.conf.dist

set capitals on Random

* Final update on settings documentation

* Update playerbots.conf.dist

* Fix bots loving to do BG's a bit too much

* Final fix bots over-queuing

* pt2 - Limit over-queuing to ~1 instance

Try and prevent over-queuing to a max of 1 instance.

* Add new queue instead of instance if necessary

* Update RandomPlayerbotMgr.cpp

* Final commit

* Update RandomPlayerbotMgr.cpp

* Fix timer

* Updated docu

* Update playerbots.conf.dist

* Update RandomPlayerbotMgr.cpp

Set BgCheckTimer to 45 as it is sufficient.
2025-01-20 14:21:35 +01:00
Paulo
2025fa4dea Streamline and 'fancify' README.md (#882)
* chore(CORE/Readme): Streamline readme and add icon

* chore(CORE/Readme): Remove unused example readme

* chore(CORE/Readme): Tweak README header

---------

Co-authored-by: Paulo Oliveira <paulo.oliveira@framestore.com>
2025-01-20 14:18:46 +01:00
Yunfan Li
e6be50d2e1 Merge pull request #880 from liyunfan1223/improve_dps
Improve DPS rotation
2025-01-20 15:50:45 +08:00
Yunfan Li
e09b871d94 Increase ammo count for hunter 2025-01-19 23:08:42 +08:00
Yunfan Li
8854f7e9b2 Unholy dk gltphs update 2025-01-19 23:07:59 +08:00
Yunfan Li
7eabe47a62 Frost mage ice barrier health trigger 2025-01-19 23:07:48 +08:00
Yunfan Li
89941ada48 Magic focus magic on party 2025-01-19 22:39:34 +08:00
Yunfan Li
4c1469fc58 Fix possible mem leak on vigilance 2025-01-19 21:48:41 +08:00
Yunfan Li
099d4bdd22 Fix shaman enchant inv type 2025-01-19 21:46:54 +08:00
Yunfan Li
3a9fc170c5 Leave group instead of disband group 2025-01-19 20:13:59 +08:00
Yunfan Li
bc33851189 Mage improvement (fire mage aoe) 2025-01-19 20:06:10 +08:00
Yunfan Li
7dcf13875e Merge pull request #879 from liyunfan1223/fix_crash_talk
Fix talk crash by correcting "nearest game objects"
2025-01-19 17:53:03 +08:00
Yunfan Li
a0e955d14b Fix comments 2025-01-19 17:10:11 +08:00
Yunfan Li
812702ea25 Hunter wolf pet config and modify config file layout for activities 2025-01-19 17:10:11 +08:00
Yunfan Li
f096975f90 Fix estimated life time with dead group member 2025-01-19 17:10:11 +08:00
Yunfan Li
462e99ec30 Fix triggered charged buff check 2025-01-19 17:10:11 +08:00
Yunfan Li
c2a023afa2 Leave group on login instead of disband group if group is invalid 2025-01-19 17:10:11 +08:00
Yunfan Li
265f969656 Improve and fix unholy dk rune triggers 2025-01-19 17:10:10 +08:00
Yunfan Li
006e0a03c8 Improvement hunter track and spell 2025-01-19 17:10:10 +08:00
Yunfan Li
3523a65ff8 Improvement on warlock life tap glyph 2025-01-19 17:10:10 +08:00
Yunfan Li
9f34d4a7f7 Fix talk crash by correcting "nearest game objects" 2025-01-19 13:04:30 +08:00
achyles222
106b36b498 Added ability to specify bot target for spell casting (#874) 2025-01-18 20:28:20 +01:00
Noscopezz
e27c28b125 LK HC update (#876)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change

* LK 10HC update

Added Shadow trap logic
(if they stand in it, not a big deal since bots wont get yeeted only players will)
When harvest soul, only player will be in another dimension (you must survive)

**Sindy and LK can be done, but I must dissapoint purist, at my skill level I could not achieve to do HC without using summon or other "cheat" bot functions.

Other bosses are all doable now in 10hc
2025-01-18 18:04:26 +01:00
SaW
89590860fb Performance: Refactored a bunch of functions in Playerbot ai (#865)
* Update PlayerbotAI.h

* Refactored a number of functions in PlayerbotAI.cpp

* Update PlayerbotAI.cpp

* Update PlayerbotAI.cpp - update for commit done

Take
568592f188
into account.

* Missing check for aurEff

* Update PlayerbotAI.cpp

nvm...

* Update PlayerbotAI.cpp

GetAura

* Update PlayerbotAI.cpp

Simplified/Optimized sPlayerbotAIConfig->dynamicReactDelay logic for in-combat.

* Update PlayerbotAI.cpp

Dubass fix

* Update PlayerbotAI.cpp

Fix bots leaving dungeon group,. again.

* Update PlayerbotAI.cpp

* Update PlayerbotAI.cpp - order correction

...Required for proper pet behavior.

* Update PlayerbotAI.cpp - UpdateAIGroupMembership()

Final refactor of helper function as all now works as required.

* Update PlayerbotAI.cpp

FindItemInInventory

* Update PlayerbotAI.h

Added helper functions, correct public -> private
2025-01-15 22:49:41 +01:00
Noscopezz
a24a4c0865 10HC until PP (#872)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase

* 10HC update until PP

LK defile improved for 10nm (bots sometimes stood 2 close to defile until it grew few times)

Improved rotface for HC

PP remade for 10HC.
Gas cloud is now properly kited
Fixed a rare case of server crash when there were ooze and gas cloud alive at same time.
Bots will move around puddles according to its size now.
Bots that get unboud plague will simply move away from raid and die thus loosing it from raid.
Volatile ooze improved stacking.
Fixed ranged sometimes glitching thru walls when spreading out from other members.

10HC PP is now doable but its hard without summoning (summoning break gascloud and ooze targets so its easier to do). You need to watch boss so you dont phase 2 soon otherwise you will get 2x ooze and cloud which is almoust always a wipe. If abo is not played near perfection bots will struggle with oozes and gas clouds if they are not slowed on time. Always save energy to slow gas cloud since it will wipe the group if it reach its target.
Bots will sometimes stand in puddle, just command them to move and they will figure out what to do.

todo (proper malleable handling)

* Up until Sindy 10HC

BPC added shadow prison handling, bots stop moving if more than 12 stack, tanks more than 18
Improved spreading logic

VDW
fixed issue where bots in portal wold move at half speed compared to real player

* fixed accidental change
2025-01-15 22:48:08 +01:00
Yunfan Li
bf4deff717 Fix playerbots database request queue stacking (#870)
* Clear added random bots on server start

* Remove duplicate set login event

* Remove login event value

* Remove deletion of add event value
2025-01-14 20:30:06 +01:00
kadeshar
7a71cd57f9 - [Paladin] added crusader aura support (#867) 2025-01-14 16:25:33 +01:00
Yunfan Li
568592f188 Minor fixes to spell and mount init (#863)
* Make summon imp non-temporary

* Remove horse mount from troll

* Set facing to during spell casting

* Allow rpg status command

* Init unarmed skill and fix skill clear

* Cast delay after interrupt spell
2025-01-12 18:03:27 +01:00
Noscopezz
4311dabe24 LK update (#862)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all

* LK Update

Refined defile logic
Added 3 points for ranged and melee in winter phase (east, west, south when facing throne)
fixed frost spheres targeting (hunter will focus them)
Atm bots will reset z axis if they fall underground or if they get teleported by lk
Better positioning in 1st phase
2025-01-10 23:35:06 +01:00
SaW
72db64ba84 Refactored Engine::DoNextAction (#854)
Update Engine.cpp
2025-01-10 18:52:20 +01:00
blinkysc
8f37a0cdd4 Update PVP Restricted Area (#858)
* Update PVP Restricted Area 

Add Lights Breach to PVP restricted list

* Add Ebon Watch PVP Restricted Area
2025-01-10 18:42:12 +01:00
Yunfan Li
46534e3abe Fix/Enhance warlock pet spells (#860) 2025-01-10 18:41:56 +01:00
Dreathean
6695415170 Update bug_report.md (#861)
Added additional information requested
2025-01-10 18:41:18 +01:00
valsan-azerty-boi
07158f3b30 Delete superfluous semicolon in conf (#856) 2025-01-08 20:23:37 +01:00
Yunfan Li
39b2651919 Merge pull request #850 from liyunfan1223/fix_follow_master
Follow master instead of group master in formation
2025-01-08 23:31:26 +08:00
Yunfan Li
3d31a7e15d Merge pull request #853 from valsan-azerty-boi/ft/conf-min-lvl-mount
Feat: Mount level for bot configurable instead of hardcoded
2025-01-08 21:25:29 +08:00
blinkysc
9f9ecd2626 Update PVP areas (#855)
Added Mudsprocket (aka bloodbath) and Wyrmrest temple in Area ID's to PvpProhibitedAreaIds
2025-01-07 20:58:08 +01:00
Noscopezz
7471987518 Gunship fix (#846)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits

* GS fixed bots not returning to their ship for A and H

Bots will return back to ship after killing mage

* PP gas cloud kiting improved

PP gas cloud kiting improved

* BPC targeting fixed

Bots will mark valid prince with skull RTI now

* BQL added melee spread in air pahse

BQL added melee spread

* VDW healing rotation improved

Healers will now use strong heals and hots

* Fixed Necrotic Plague

Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all
2025-01-06 15:35:24 +01:00
valsan-azerty-boi
f95e812d26 add bot mount in conf 2025-01-05 21:55:13 +01:00
Yunfan Li
9293e5b1dd Follow master instead of group master in formation 2025-01-04 23:43:59 +08:00
Yunfan Li
a5787a0200 Merge pull request #849 from liyunfan1223/revert-844-paladin_blessings2
Revert "Paladins use Greater Blessings"
2025-01-04 21:31:46 +08:00
Yunfan Li
b0b3fef222 Revert "Paladins use Greater Blessings" 2025-01-04 21:24:12 +08:00
Yunfan Li
7c8c20b365 Merge pull request #845 from liyunfan1223/lfg_leave
Remove from group when no real player in lfg group
2025-01-04 18:36:49 +08:00
Yunfan Li
a62fa3e1c4 Merge pull request #844 from avirar/paladin_blessings2
Paladins use Greater Blessings
2025-01-04 18:36:01 +08:00
Yunfan Li
d3868e7af7 Remove from group when no real player in lfg group 2025-01-04 16:41:02 +08:00
Yunfan Li
01c257005e Merge pull request #842 from liyunfan1223/lfg_leave_group
Fix LFG leave group and several minor issues
2025-01-04 16:12:12 +08:00
avirar
7392c5551a BuffTrigger instead of OnParty 2025-01-04 18:51:23 +11:00
avirar
39a1fd25d2 Arcane Brilliance 2025-01-04 18:45:38 +11:00
avirar
bc4842d9b2 Arcane Brilliance 2025-01-04 18:45:23 +11:00
avirar
3899ebd4a9 Arcane Brilliance 2025-01-04 18:45:12 +11:00
avirar
626cf44ad5 OnParty 2025-01-04 18:18:37 +11:00
avirar
34210e0508 Prayer of Fortitude 2025-01-04 18:16:33 +11:00
avirar
4eb302b95e Prayer of Fortitude 2025-01-04 18:16:24 +11:00
avirar
9acf163564 Gift/Mark of the Wild 2025-01-04 17:32:53 +11:00
avirar
058a34e216 Gift/Mark of the Wild 2025-01-04 17:32:50 +11:00
avirar
2461cb3742 Gift/Mark of the Wild 2025-01-04 17:32:46 +11:00
avirar
2679b851d4 Add to Paladin default strats 2025-01-04 16:16:42 +11:00
avirar
91712de394 Created bgreater strat and trigger/action contexts 2025-01-04 15:36:16 +11:00
avirar
f1282cfbe7 Create PaladinBuffGreaterBlessingStrategy 2025-01-04 15:35:23 +11:00
avirar
b24fa24c7b Create PaladinBuffGreaterBlessingStrategy 2025-01-04 15:35:10 +11:00
avirar
951b246970 Create CastGreaterBlessingAction 2025-01-04 15:34:54 +11:00
avirar
2951e76052 Create CastGreaterBlessingAction 2025-01-04 15:34:45 +11:00
avirar
8f71551fb7 Create CastGreaterBlessingTrigger 2025-01-04 15:34:30 +11:00
avirar
104f486630 Create CastGreaterBlessingTrigger 2025-01-04 15:34:17 +11:00
avirar
c0132f7551 Create BlessingManager.h 2025-01-04 14:59:51 +11:00
avirar
7895e2ebf3 Create BlessingManager.cpp 2025-01-04 14:37:19 +11:00
Noscopezz
16d06c4832 ICC Strategy (doable 10/25NM) (#789)
* ICC PP WIP

WIP

* added mutated plague for PP

* BPC added (kinetic and boss targeting need to be done by player)

OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own.
Tested only on 10NM, should work on 25NM

* Tank pos. correction

* BQL, ranged spread, link, flame, bite, tanking tested 10NM

to do (better fire spread, hc tacti, melee spread when in air)

* LDW improved

improved shadow logic, ranged spread for easier shadow handling

* dbs update, fixed teleporting

Bots should only go and teleport to the mage that is actually below zero now

* DBS ranged fix

Ranged should spread more quickly and freak out less

* Festergut && DBS

fixed ranged spread (both)
fixed spore logic (fester)

* Rotface fix

Improved big ooze tanking (static pos, todo kiting)
ooze explosion spread mechanic fix
ooze pool fix
Player needs to mark rotface with skull icon, oterwise bots try to attack oozes

* BQL fixed for 25nm

todo: better melee logic in air phase, better melee flame spread

* VDW, Sister Svalna, Sindy update

Sister Svalna, bots can pickup spears and throw at svalna when she has shield up

VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer)
todo (focus on supressers, add healer rotations, atm they use quickest spell they can)

Sindragosa
Added tank boss manipulation (boss orientation and position)
bots detect (buffet, unchained magic and chilled to the bone and act accordingly)
bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot)
Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count.
Player should tell bots with skull rti if they should kill tomb or focus boss.
todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss)

Removed some debug messages, improved LM spike action (nearest bots also try to help kill it)

Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it)

dbs improved tank switch

I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man
25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps

* LK Update (doable)

LK added

Improved tank switching for all bosses

Fixed PP gas cloud kiting
Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass

BPC  fixed OT sometimes not tanking kele
kinectic bombs todo (for now player should take care of them)

Sindragosa fixed rare case when she is in air phase but tombs went to last phase position

LK
Bots can handle necrotic
Bots can handle adds
Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way.

Defile should be watched by player and once it was cast just summon bots to you
Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done

**Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you)

all in all LK  is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots)

Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot

I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps,  if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals)

* fixed changes made by mistake

fix

* Malleable fix (simple spread mechanic)

Malleable mechanic added (simple spread for now)
Gas cloud fixed (Bots sometimes got stuck between puddle and kite location)

* Defile Update

Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them)

Melee bots should be able to stand behind/to the flank of shambling/spirits
2025-01-03 19:15:16 +01:00
avirar
fa02cdb369 Allow use of more portal game objects (#840)
* EoE and Naxx Portals

* Added Orb of Naxxramas objects and use GAMEOBJECT_TYPE_GOOBER

* Fixed missing ! in HasEffect(SPELL_EFFECT_TELEPORT_UNITS) check

Commented out old code in case it is needed in the future for edge case portal objects.
2025-01-03 16:07:56 +01:00
avirar
739a0df44c Warrior strategy update (#838)
* Enraged regen at critial health

* Enraged regen action context

* Enraged regen on critical health trigger

* Enraged regen on critical health trigger

* Added logic for Arms to use Retaliation

* Added logic for Arms to use Retaliation

* Used correct class enums for !players

* Retaliation on medium health

* Removed temp line

* Added check for attacker->GetVictim() != bot

* Adjusted triggers for emergency actions

* Added Shattering Throw logic

* Added Shattering Throw logic

* Added Shattering Throw logic

* Added Shattering Throw logic

* Added Shattering Throw logic

* Added Shattering Throw logic

* Fixed ActionNode for Shattering Throw

* Added debug logging

* More debug logs

* Better debug logs

* Adjusted range on action

* Adjusted priorities

* More logging

* Update WarriorActions.cpp

* Update WarriorActions.h

* Changed trigger name for differentiation

* Updated to new shattering throw trigger name

* Update WarriorTriggers.h with new ST name

* Update ArmsWarriorStrategy.cpp

* Changed priority

* Shattering Throw and Retaliation stance reqs

Battlestance needed for Shattering Throw and Retaliation

* Created isUseful for Shattering Throw

* Created isUseful for Shattering Throw

* GetTarget instead of GetTargetValue

* Changed to GetTarget instead of GetTargetValue

* Commented out Execute function

* Commented out Execute function

* isPossible was failing, created basic isPossible

IsImmuneToSpell was returning true for Shattering Throw

2 DAYS! :(

* isPossible was failing, created basic isPossible

* Added some more isPossible checks

* Update WarriorActions.cpp

* Missing )

* Missing !

* Removed logging

* Removed logging

* Clean up

* Cleanup

* Corrected logic for Rogue's Expose Armor trigger

Logic was checking the Rogue, not the Rogue's target, for Sunder Armor before casting Expose Armor.
2025-01-03 16:06:47 +01:00
avirar
c59c0cc802 Added logic for early ranged/thrown weapon equipping (#839)
Ranged weapons get caught up in the ITEM_CLASS_WEAPON logic but aren't handled. Added an early check and equip for ranged INVTYPE_
2025-01-03 16:06:06 +01:00
bash
b16a44c711 [performance] smart scaling configurable (#834) 2025-01-02 19:02:06 +01:00
avirar
823f9e87a6 Prevent Warriors using Charge during Ionar Disperse and Loken Lightning Nova (#836) 2025-01-02 16:34:51 +01:00
Yunfan Li
30437bd28f Improve inactive grind status 2025-01-01 21:10:05 +08:00
Yunfan Li
9d34a58435 Improve rpg movement and grind 2025-01-01 20:41:40 +08:00
Yunfan Li
da1c3effb7 Fix movement after spell cast 2025-01-01 20:41:08 +08:00
Yunfan Li
3b7415e819 Shaman totems enhancement 2025-01-01 20:40:48 +08:00
Yunfan Li
6b8e906e39 Fix LFG leave group 2025-01-01 20:40:39 +08:00
Yunfan Li
c5994e2961 Merge pull request #832 from liyunfan1223/move_backwards
Move backwards when enemy too close
2024-12-31 23:43:41 +08:00
Yunfan Li
1b5c6ba06a Fix FleeAction 2024-12-31 21:53:31 +08:00
Yunfan Li
cc5a3e4c76 Add backwards paramater on MoveAway (apply only on FleeAction) 2024-12-31 20:56:25 +08:00
Yunfan Li
8dc5bdb4c1 Reduce move far attempts for performance 2024-12-31 20:51:09 +08:00
SaW
10a45fcbde Put IsValidAttackTarget check on both bots and their pets (#833)
* Prevent PetAttackAction on invalid targets

* Prevent AttackAction on invalid targets in general
2024-12-30 19:21:38 +01:00
Yunfan Li
fd53a8570b Merge branch 'master' into move_backwards 2024-12-30 20:28:37 +08:00
Yunfan Li
6afd8399e1 Merge pull request #830 from avirar/arms_warrior_tweak
DPS Warrior action priorities
2024-12-30 20:21:27 +08:00
avirar
fd7b82d170 Lowered Heroic Strike for Prot spec too
Also added Devastate as a medium rage ability after Shield Slam.
2024-12-30 13:58:34 +11:00
avirar
2d89c66b51 Merge branch 'liyunfan1223:master' into arms_warrior_tweak 2024-12-30 10:37:12 +11:00
avirar
f1a1562ae9 Merged Fury tweaks into Arms branch for unified PR 2024-12-30 10:36:55 +11:00
avirar
a8baa213d6 Merged Fury tweaks into Arms branch to unify PR 2024-12-30 10:34:01 +11:00
avirar
64b5cb833a Merged Fury tweaks into Arms branch 2024-12-30 10:32:49 +11:00
avirar
6842505c88 Update ArmsWarriorStrategy.cpp 2024-12-30 09:51:47 +11:00
avirar
c7dd947a7a Update GenericWarriorStrategy.cpp 2024-12-30 09:34:43 +11:00
avirar
5c8283d40a Prot warriors cast vigilance when in a group (#825)
* Add Vigilance

* Vigilance

* Update WarriorTriggers.h

* Update TankWarriorStrategy.cpp

* Update WarriorAiObjectContext.cpp

* Update WarriorTriggers.cpp

* Update WarriorTriggers.h

* Update WarriorTriggers.cpp

Check for existence of Vigilance in raid already

* Update WarriorActions.cpp

Check for existence of Vigilance in raid already
Apply to tanks, then highest gearscore DPS.

* Update WarriorActions.cpp

* Update WarriorActions.cpp

* Update WarriorActions.cpp

* Update WarriorActions.cpp

* Added logout

Bots keep assigning it to me and not maintank? Added logging to clarify

* Update WarriorActions.cpp

* Update WarriorActions.cpp

* Update WarriorActions.cpp

* Update WarriorActions.cpp

* Update WarriorTriggers.cpp

* Update WarriorTriggers.cpp

* Update WarriorTriggers.cpp

* Update WarriorActions.cpp

* Update WarriorActions.cpp

* Update WarriorTriggers.cpp

* Update WarriorActions.cpp

* Update WarriorActions.cpp

* Removed Logs

* Removed logs

* Added check for spell in trigger

* Update WarriorTriggers.cpp

* !member->IsAlive()

* !member->IsAlive()
2024-12-29 21:47:22 +01:00
kadeshar
a6d1697267 Oculus - fix flying/attacking drake (#827)
* - fixed bug with duplicated action name "fly drake"

* - fixed bug with duplicated action name "drake attack"

* - fixed eoe strategy after bugfixes
2024-12-29 21:44:35 +01:00
Yunfan Li
79a5fdd7c1 Make backwards movement for flee 2024-12-29 23:21:03 +08:00
avirar
9432b265ea Update GenericWarriorStrategy.cpp 2024-12-29 17:14:38 +11:00
avirar
b9c96e80c3 Added medium aoe trigger for SS/BS combo 2024-12-29 16:52:54 +11:00
avirar
a6ceaa5565 Update ArmsWarriorStrategy.cpp 2024-12-29 16:28:48 +11:00
avirar
c253a32039 Update GenericWarriorStrategy.cpp 2024-12-29 16:09:32 +11:00
avirar
9f1b9df9d1 Update ArmsWarriorStrategy.cpp 2024-12-29 15:55:04 +11:00
avirar
6eef410689 Missing ) 2024-12-29 15:47:38 +11:00
avirar
85efe3fbbd Adjusted priorities 2024-12-29 15:45:19 +11:00
avirar
68b48ce573 Adjusted priorities 2024-12-29 15:45:10 +11:00
avirar
920b3c7b08 Lowered Heroic Strike priority 2024-12-29 15:00:55 +11:00
avirar
adc0d6e72c Worldbuff feral druid bear/cat logic (#816)
* Add logic to separate cat and bear druid buffs

Check for Thick Hide (16929) talent, use regular buffs if found, use new fourth row if not.

* Added cat druid buffs (ArP food, AP flask)

* Update playerbots.conf.dist

* Refined logic for feral druids

* Use rank 3 of Thick Hide and GetActiveSpec

* Update WorldBuffAction.cpp

* Added DK Blood DPS buffs

AP Flask, STR food

* Added logic for DPS Blood DKs
2024-12-28 15:27:31 +01:00
Yunfan Li
1ed6645119 Fix rpg move far (#822)
* Fix rpg move far

* Don't go innkeeper with diff zone
2024-12-27 18:11:39 +01:00
Revision
2b758c9624 Merge pull request #817 from nl-saw/defchaosform
Poll results: Change default formation to Chaos
2024-12-27 17:46:26 +01:00
Yunfan Li
d1690b2605 Merge pull request #795 from avirar/razorscale_final
Ulduar-Razorscale strategy
2024-12-27 22:26:32 +08:00
Yunfan Li
1c22a9a9ff Add ratio config for alliance and horde rndbots (#818) 2024-12-25 20:42:35 +01:00
SaW
2f78db81e3 Change default formation to Chaos
This as it looks more natural than the default near.
2024-12-24 16:46:51 +01:00
avirar
85370cd30d Merge branch 'liyunfan1223:master' into razorscale_final 2024-12-24 14:49:42 +11:00
SaW
d9f9d980cf Fix various formations - Issue #749 (#807)
* Fix various formations

* Refactor Formation::GetFollowAngle()

* Update Formations.cpp

* Refactored Formation::GetFollowAngle()

Final refactor of Formation::GetFollowAngle()

 - By combining the group member iteration, unnecessary loops are avoided.
- Clearer Structure: The code is more readable, with fewer redundant operations.
- Better Maintainability: Comments and logical grouping make it easier to modify or extend the function in the future.

* Logic order improvement
2024-12-22 23:08:47 +01:00
kadeshar
e5f1b862dd [Bugfix] (#809)
- reverted changes in need world buff trigger
2024-12-22 12:46:11 +01:00
avirar
6cc5298819 Update RaidUlduarTriggers.cpp 2024-12-22 19:50:58 +11:00
avirar
f9d945ce33 Adjusted priority for fuse armor 2024-12-22 19:49:37 +11:00
avirar
11c9ee4d72 Removed Static declarations for role assignment cooldowns 2024-12-22 19:48:02 +11:00
avirar
c265a5e018 Refined assignment cooldowns and logic for bot tanks 2024-12-22 19:46:59 +11:00
avirar
900a922d34 Added logic for bots to offtank
Bot tanks will mark targets and establish themselves as main tank when necessary, announcing when ever re-assignment occurs
2024-12-22 19:45:51 +11:00
avirar
b897593d76 Update RaidUlduarBossHelper.cpp 2024-12-22 15:19:49 +11:00
avirar
4694de7ce0 Update RaidUlduarBossHelper.cpp 2024-12-22 15:17:34 +11:00
avirar
b42a40b8f4 Role assignment cooldown mapped per bot 2024-12-22 15:00:04 +11:00
avirar
67bc4a8e8f Allowed tank bots to reassign roles if human main tank is affected by fused armor 2024-12-22 13:37:42 +11:00
avirar
5c63e6faf3 Allowed tank bots to reassign roles if human main tank is affected by fused armor 2024-12-22 13:37:37 +11:00
avirar
a6de87f6fc Allowed tank bots to reassign roles if human main tank is affected by fused armor 2024-12-22 13:37:33 +11:00
avirar
39c6fb8daa Resolved issues with IsRealPlayer and GET_PLAYERBOT_AI 2024-12-22 13:05:14 +11:00
avirar
f72a6bf53b Still fixing bot say 2024-12-22 11:15:57 +11:00
avirar
eacce5adf3 Fixed bot say 2024-12-22 10:54:19 +11:00
avirar
10fd4fb014 Update RaidUlduarBossHelper.cpp 2024-12-22 10:29:07 +11:00
avirar
27441e9369 Update RaidUlduarBossHelper.cpp 2024-12-22 09:47:39 +11:00
avirar
de14e4e2e3 Merge branch 'liyunfan1223:master' into razorscale_final 2024-12-22 09:33:20 +11:00
avirar
e71c5e4e91 Bots say when giving main tank to a real player as request player taunt 2024-12-22 09:32:35 +11:00
SaW
848401be67 Make bots use mounts when player is in travel form as well (#806)
Addition to https://github.com/liyunfan1223/mod-playerbots/pull/805
2024-12-21 17:22:06 +01:00
Revision
7ccc18c7d6 Merge pull request #804 from kadeshar/worldbuff-strategy
Added worldbuff strategy
2024-12-21 14:50:00 +01:00
SaW
8c36d0988b 5-8 percent performance increase when when botActiveAlone is 100% and smartScale disabled (#803)
Diff-wise. By moving the when botActiveAlone is 100% and smartScale disabled return to the very top.
2024-12-21 13:48:07 +01:00
SaW
99dd094a5b Feature: Bots use flying mounts when player has flight form (#805)
* Make bots use flying mounts when player goes into flight form

* add && !bot->InBattleground() check

* Final commit
2024-12-21 13:33:47 +01:00
kadeshar
eef41ab3b7 Added worldbuff strategy 2024-12-20 23:04:22 +01:00
Yunfan Li
beabe5c701 Merge pull request #799 from liyunfan1223/fix_joinlfg
Fix JoinLFG crash
2024-12-20 17:18:16 +08:00
bash
83369478c3 Minor updates after patches (#801)
only freeze bots during init when not in combat
2024-12-19 21:26:28 +01:00
Revision
2e83283983 Merge pull request #800 from liyunfan1223/remove_warrior_mark_rti
Remove mark rti strats for tank warrior
2024-12-19 20:38:14 +01:00
Yunfan Li
1ccde41fea Remove mark rti strats for tank warrior 2024-12-19 22:58:26 +08:00
Yunfan Li
360dc27c9c Comment for threadsafe 2024-12-19 22:50:59 +08:00
Yunfan Li
4e64745861 Fix JoinLFG crash 2024-12-19 22:44:54 +08:00
bash
ea1ec98645 Revert "Make AutoScaleActivity further configurable (#766)" (#798)
This reverts commit 66f0cf27d3.
2024-12-19 00:41:33 +01:00
SaW
66f0cf27d3 Make AutoScaleActivity further configurable (#766)
Make AutoScaleActivity configurable
2024-12-18 23:21:50 +01:00
avirar
a1b4681c58 Resolved issues with rndbots and equipmentPersistence (#778)
* Update PlayerbotFactory.cpp

* Update PlayerbotFactory.cpp

* Added !incremental checks for talent/gear init
2024-12-18 18:32:01 +01:00
SaW
570787ff16 Improve check to work in custom defines zones as well (#797) 2024-12-18 18:29:35 +01:00
avirar
7c8563ef7d Update RaidUlduarTriggers.h 2024-12-18 16:20:06 +11:00
avirar
a8d42fbe03 Update RaidUlduarTriggers.cpp 2024-12-18 16:18:58 +11:00
avirar
09f648eb9f Update RaidUlduarTriggerContext.h 2024-12-18 16:17:41 +11:00
avirar
42156f5306 Update RaidUlduarStrategy.cpp 2024-12-18 16:17:02 +11:00
avirar
556c9186f2 Moved ULDUAR_MAP_ID definition outside RazorscaleBossHelper
RazorscaleBossHelper::ULDUAR_MAP_ID
2024-12-18 16:15:36 +11:00
avirar
1e5e38dcc2 Update RaidUlduarBossHelper.h 2024-12-18 16:14:57 +11:00
avirar
4d7fba0dcc Create RaidUlduarBossHelper.cpp 2024-12-18 16:09:58 +11:00
avirar
67591ffdb3 Update RaidUlduarActions.h 2024-12-18 16:07:34 +11:00
avirar
e2ec637882 Update RaidUlduarActions.cpp 2024-12-18 16:05:51 +11:00
avirar
0dccc9ea50 Implemented Razorscale logic 2024-12-18 16:00:45 +11:00
SaW
3dd92b7fd8 Fix bots attacking others despite being in a prohibited zone - Issue 227 (#793)
* Fix bots attacking despite being in a prohibited zone

* Protect pets as well and move logic to not skip IsFriendlyTo

* Fix prohibited typo

* Update AttackAction.cpp
2024-12-17 23:31:38 +01:00
Yunfan Li
2e4db37c4d Merge pull request #791 from avirar/stop_attacking_argent_tournament_dummy_targets
Prevent bots attacking dummy targets at the Argent Tournament Grounds
2024-12-17 20:48:36 +08:00
Yunfan Li
fd1b8089af Merge pull request #792 from xSparky911x/master
fix typo in requested config value
2024-12-17 20:48:12 +08:00
Yunfan Li
42404ac403 Merge pull request #759 from liyunfan1223/new_rpg_strats
New rpg strategy
2024-12-17 20:43:38 +08:00
xSparky911x
e54fc0fb46 fix typo in requested config value 2024-12-17 03:36:19 -06:00
avirar
649e55dd84 Prevent bots attacking dummy Targets at the Argent Tournament Grounds
There was existing code to ignore practice targets (anything with Dummy in the name) so I've just added the names of practice targets located in the tournament grounds:

Charge Target
Melee Target
Ranged Target

I considered just using the phrase "Target", but it is too generic and there are 246 creature_template names containing Target.
2024-12-17 12:35:49 +11:00
Bobblybook
418a0c4be2 Merge pull request #786 from Bobblybook/master
EoE cleanup
2024-12-16 17:49:35 +11:00
Bobblybook
d031bffb54 Merge branch 'master' of https://github.com/Bobblybook/mod-playerbots 2024-12-16 17:47:58 +11:00
Bobblybook
c6a0b012e8 EoE cleanup 2024-12-16 17:47:44 +11:00
xSparky911x
cbadb5765f Prevent autogear on player alt bots (#772)
* prevent autogear on player alt bots

* update chat message to match other message format

* add config option with default set to 1

* replace end of file blank line

* remove extra space
2024-12-15 23:37:13 +01:00
Revision
9fed6bc73a Fixed config options (#785) 2024-12-15 22:55:39 +01:00
Bobblybook
80d0ac4bdd Merge pull request #779 from Bobblybook/master
EoE Implementation (WIP)
2024-12-16 08:29:27 +11:00
bash
19cda1068d botActiveAlone; added new botActiveAlone confguration option (#783) 2024-12-15 20:04:24 +01:00
Gabriel Comeau
183bf7ae8e Allow bots to trade conjured items (#781)
Since they didn't have any sell value you couldn't get a bot to give you a healthstone or conjured food/water.  This change allows them to be traded to you without altering any of the other logic for bot trades.
2024-12-15 20:03:46 +01:00
bash
ea944aeefa added additional botActiveAlone confguration options (#780) 2024-12-15 19:18:36 +01:00
Yunfan Li
a9e33bbcae Increase pet attack priority 2024-12-16 00:53:07 +08:00
Yunfan Li
677ee83e45 Update locs level 2024-12-15 22:30:24 +08:00
Yunfan Li
f45d03f62b Merge pull request #777 from avirar/titans_grip_weapon_type_restrictions
Enhanced dual wield/titan grip equip logic
2024-12-15 21:39:03 +08:00
Yunfan Li
45629cb3df Starter location collection 2024-12-15 21:36:26 +08:00
Bobblybook
a9ff1dbc5e Merge branch 'master' into master 2024-12-15 23:47:38 +11:00
Bobblybook
af6eb61d33 Prelim EoE completion 2024-12-15 23:37:56 +11:00
Yunfan Li
a91aa3e392 New rpg bug fix that preventing bots from long distance movement 2024-12-15 16:46:44 +08:00
SaW
453fa4b4f5 Fix reload command security (#774) 2024-12-14 17:55:06 +01:00
Yunfan Li
9b41798eee Fix get zone id 2024-12-14 22:35:24 +08:00
Yunfan Li
a5d1d7579d EnableNewRpgStrategy switch for initialization 2024-12-14 21:46:33 +08:00
Yunfan Li
2656b2d0d9 Update starter position 2024-12-14 16:23:33 +08:00
Yunfan Li
df5b10c9ad Revert classes folder 2024-12-14 16:23:13 +08:00
avirar
d77dbb65e5 Enhanced dual wield logic in EquipItem
Implemented logic to ensure the strongest weapon is always placed in the main hand for dual-wielding or Titan Grip-capable bots.
When equipping a new weapon, the code now compares the new weapon’s score with the currently equipped main-hand and off-hand weapons.
If the new weapon is the strongest, it goes into the main hand. The previous main-hand weapon may be moved to the off-hand if it is allowed (e.g., not a main-hand-only weapon) and provides a performance improvement.
Titan Grip conditions are accounted for, allowing valid two-handed weapons (2H axes, maces, swords) to be placed in the off-hand as well.
2024-12-14 18:52:57 +11:00
avirar
0c16f308db Update EquipAction.cpp 2024-12-14 18:41:32 +11:00
avirar
34c0759c90 Update EquipAction.cpp 2024-12-14 18:28:28 +11:00
avirar
f8da773ce1 Update EquipAction.cpp 2024-12-14 18:21:28 +11:00
avirar
a9eb41600d Update EquipAction.cpp 2024-12-14 18:07:02 +11:00
avirar
ea9bd18102 Enhanced dual-wield logic
Description of Changes:

    Implemented logic to ensure the strongest weapon is always placed in the main hand for dual-wielding or Titan Grip-capable bots.
    When equipping a new weapon, the code now compares the new weapon’s score with the currently equipped main-hand and off-hand weapons.
    If the new weapon is the strongest, it goes into the main hand. The previous main-hand weapon may be moved to the off-hand if it is allowed (e.g., not a main-hand-only weapon) and provides a performance improvement.
    Titan Grip conditions are accounted for, allowing valid two-handed weapons (2H axes, maces, swords) to be placed in the off-hand as well.
2024-12-14 17:57:16 +11:00
avirar
5962dc3d0c Update ItemUsageValue.cpp 2024-12-14 17:23:48 +11:00
Yunfan Li
be71872112 Update far move to prevent invalid movement 2024-12-14 02:33:52 +08:00
Yunfan Li
912ef6d56f Increase reach melee relevance 2024-12-14 01:43:38 +08:00
Yunfan Li
1f8d0d244c Update starter position 2024-12-14 01:33:39 +08:00
Yunfan Li
2171493d5e Update GO_INNKEEPER prob 2024-12-13 20:20:13 +08:00
Yunfan Li
e7416db7dc Modify file structure 2024-12-13 20:14:25 +08:00
Yunfan Li
a7496b3eb5 Merge branch 'master' into new_rpg_strats 2024-12-13 18:51:55 +08:00
Yunfan Li
f26cebb518 Update rpg status probability 2024-12-11 23:00:03 +08:00
Yunfan Li
c436781d39 Merge pull request #767 from liyunfan1223/crash_fix_bg
[Crash fix] Fix race condition on BattlegroundData
2024-12-10 21:52:07 +08:00
Yunfan Li
0cfae2673f [Crash fix] Fix race condition on BattlegroundData 2024-12-10 20:22:52 +08:00
Yunfan Li
69fe9a2d81 Reduce near npc range distance 2024-12-10 20:20:19 +08:00
Yunfan Li
31f82cc322 locsPerLevelCache faction filter 2024-12-08 15:53:46 +08:00
Yunfan Li
98701a6f66 Modify starter position (add flightmaster) 2024-12-08 15:47:34 +08:00
Yunfan Li
4644fd8459 Minor spell enhancement 2024-12-07 12:57:18 +08:00
Yunfan Li
6d82b134d1 Merge branch 'master' into new_rpg_strats 2024-12-06 20:39:51 +08:00
Revision
f096c2089f Add a config option for dropping obsolete quests (#745) 2024-12-06 08:45:41 +01:00
kadeshar
8c84026116 - added spec configuration for world buffs (#761)
- added world buffs to configuration file
- fixed NeedWorldBuffTrigger
2024-12-05 19:29:52 +01:00
Yunfan Li
e7f0ee16f7 Merge pull request #757 from noisiver/support-newer-master
Support newer master
2024-12-05 22:13:54 +08:00
Yunfan Li
0fa548593f Improve performance by ZoneHasRealPlayers and MoveFarTo 2024-12-04 23:26:58 +08:00
Yunfan Li
618358aa13 Improve near npc move 2024-12-03 23:30:09 +08:00
Yunfan Li
87e8c05b20 Innkeeper position and windows compile error 2024-12-03 22:57:39 +08:00
Bobblybook
f20e5d76d1 Eye of Eternity skeleton 2024-12-03 21:13:28 +11:00
kadeshar
437f816b15 - fixed attack rti target action (#758) 2024-12-03 10:59:11 +01:00
Yunfan
5c3591ae5a Update random bots level stats 2024-12-02 15:28:30 +08:00
Yunfan
5ca7c71920 Logs and rpg status for new rpg strats 2024-12-02 11:48:51 +08:00
Yunfan
bb3328670b Remove redundant logs (set to debug level) 2024-12-02 11:42:31 +08:00
Revision
fe896c1d3d Use another helper and revert one instance HasPlayerFlag 2024-12-02 00:28:08 +01:00
Revision
f0ccb0a371 Fix compiler errors and switch to using available helpers 2024-12-02 00:16:06 +01:00
kadeshar
9e20eb452d - fixed mark rti bug (#755) 2024-12-01 23:11:01 +01:00
kadeshar
7291fae5b3 Warlock soulstone action (#753)
* - added warlock soulstone action

* - added master as soulstone target
2024-12-01 22:33:03 +01:00
Bobblybook
b7c2fe9947 Obsidian Sanctum implementation (#752)
OS+2 implemented.
- Kill Vesperon before fight
- Mark Main Tank in raid interface

Offtank still needs a bit of work, and dps needs to stop running around once they're safe. But it's usable currently.
I think this should probably work for OS+1 and OS+0 with no changes but I was more concerned about implementing +2.
2024-12-01 22:26:35 +01:00
Yunfan Li
dba84da6f3 [New Rpg] Implement GO_INNKEEPER and NEAR_NPC status 2024-12-02 00:35:23 +08:00
Bobblybook
657bb9a6da Obsidian Sanctum implementation
OS+2 implemented.
- Kill Vesperon before fight
- Mark Main Tank in raid interface

Offtank still needs a bit of work, and dps needs to stop running around once they're safe. But it's usable currently.
I think this should probably work for OS+1 and OS+0 with no changes but I was more concerned about implementing +2.
2024-12-02 00:25:36 +11:00
Yunfan Li
83c407f1c6 Merge pull request #747 from Raz0r1337/master
fix small typo and remove double logging
2024-12-01 11:47:24 +08:00
Yunfan Li
21684a051d Merge pull request #751 from noisiver/update-character-online
Change statement to a newly created one
2024-12-01 11:45:42 +08:00
Revision
4f06019436 Change statement to a newly created one 2024-11-30 17:09:49 +01:00
Yunfan Li
0fd894176b [New Rpg] New rpg start up (add GO_GRIND and NEAR_RANDOM status) 2024-11-30 23:48:29 +08:00
Sascha
f54dbcdc54 Update playerbots.conf.dist
these loggers already exist in the worldserver.conf
these duplicate entries interfere with each other
2024-11-29 13:06:57 +01:00
Sascha
b39e7304cb Update playerbots.conf.dist
small indentation error fixed
2024-11-29 13:00:35 +01:00
Revision
3e449fff73 Merge pull request #742 from avirar/inCombatErrorTypo
When bots try to equip armour while in combat they say "I am not in combat"
2024-11-27 15:16:20 +01:00
bash
c0b185935b database update data folder location (#741)
added acore_playerbots update script
2024-11-25 23:44:39 +01:00
avirar
37e5e3942d Update InventoryChangeFailureAction.cpp
Corrected bot output for EQUIP_ERR_NOT_IN_COMBAT which is returned when the bot is in combat and cannot perform the equip action. Bot would previously say "I am not in combat", it will now say "I am in combat"
2024-11-26 08:54:39 +11:00
Yunfan Li
e6feccb5aa Merge pull request #740 from liyunfan1223/core_sync_241125
Naxx core sync
2024-11-25 23:20:15 +08:00
Yunfan Li
d9dc25a15f Naxx core sync 2024-11-25 23:05:20 +08:00
Revision
f925db1ca4 Fix print about invalid format (#739) 2024-11-24 22:09:04 +01:00
bash
eb583de6aa Increased updateInterval booster time (#732)
from botAmounts * 0.13 to 0.15
2024-11-19 00:25:18 +01:00
1045 changed files with 27263 additions and 6483 deletions

View File

@@ -7,29 +7,30 @@ assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Bug Description**
A clear and concise description of what the bug is. If the bug is a crash, a crash log must be posted or the issue will be removed.
**Commit hash**
**Commit Hash**
The hash of the current commit.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**How To Reproduce Bug**
Detailed steps to reproduce the behavior.
**Expected behavior**
**Expected Behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Modules**
Please list all modules used as many are known to cause conflicts with Playerbots.
**Additional context**
**Playerbot Settings**
Number of bots, scaling settings, etc if performance related.
**System**
OS: [e.g. Windows, Linux]
Hardware: [e.g. CPU if performance related]
**Additional Context**
Add any other context about the problem here.

View File

@@ -6,6 +6,10 @@ on:
pull_request:
branches: [ "master" ]
concurrency:
group: "codestyle-${{ github.event.pull_request.number }}"
cancel-in-progress: true
jobs:
lint:
name: "clang-format-always-success"
@@ -27,4 +31,4 @@ jobs:
# Check if there are any formatting changes
git diff --exit-code
shell: bash
continue-on-error: true
continue-on-error: true

View File

@@ -6,6 +6,10 @@ on:
pull_request:
branches: [ "master" ]
concurrency:
group: "core-build-${{ github.event.pull_request.number }}"
cancel-in-progress: true
jobs:
build:
strategy:

View File

@@ -5,9 +5,9 @@ on:
pull_request:
branches: [ "master" ]
# concurrency:
# group: ${{ github.head_ref }} || concat(${{ github.ref }}, ${{ github.workflow }})
# cancel-in-progress: true
concurrency:
group: "macos-build-${{ github.event.pull_request.number }}"
cancel-in-progress: true
jobs:
macos-build:
@@ -42,4 +42,4 @@ jobs:
- name: Configure OS
run: source ./acore.sh install-deps
- name: Build
run: source ./apps/ci/mac/ci-compile.sh
run: source ./apps/ci/mac/ci-compile.sh

View File

@@ -5,6 +5,10 @@ on:
pull_request:
branches: [ "master" ]
concurrency:
group: "windows-build-${{ github.event.pull_request.number }}"
cancel-in-progress: true
jobs:
windows-build:
strategy:

110
README.md
View File

@@ -1,20 +1,38 @@
[English](README.md) | [Español](README_ES.md) | [中文](README_CN.md)
<p align="center">
<a href="https://github.com/liyunfan1223/mod-playerbots/blob/master/README.md">English</a>
|
<a href="https://github.com/liyunfan1223/mod-playerbots/blob/master/README_CN.md">中文</a>
</p>
<div align="center">
<img src="icon.png" alt="Playerbots Icon" width="700px">
</div>
<div align="center">
<img src="https://github.com/liyunfan1223/mod-playerbots/actions/workflows/macos_build.yml/badge.svg">
<img src="https://github.com/liyunfan1223/mod-playerbots/actions/workflows/core_build.yml/badge.svg">
<img src="https://github.com/liyunfan1223/mod-playerbots/actions/workflows/windows_build.yml/badge.svg">
</div>
# Playerbots Module
`mod-playerbots` is an [AzerothCore](https://www.azerothcore.org/) module that adds player-like bots to a server. The project is based off [IKE3's Playerbots](https://github.com/ike3/mangosbot). Features include:
Welcome to the Playerbots Module for AzerothCore, a work in progress project based on the IKE3 Playerbots. These Playerbots utilize actual player data, allowing you to interact with your own alts, form parties, level up characters, and much more.
- Bots that utilize real player data, allowing players to interact with their other characters, form parties, level up, and more;
- Random bots that wander through the world and behave like players, simulating the MMO experience;
- Bots capable of running raids and battlegrounds;
- Highly configurable settings to define how bots behave;
- Excellent performance, even when running thousands of bots.
If you encounter any errors or experience crashes, we kindly request that you report them as GitHub issues. Your valuable feedback will help us improve and enhance this project collaboratively.
**This project is still under development**. If you encounter any errors or experience crashes, we kindly request that you [report them as GitHub issues](https://github.com/liyunfan1223/mod-playerbots/issues/new?template=bug_report.md). Your valuable feedback will help us improve this project collaboratively.
You can also get more information in our [discord](https://discord.gg/NQm5QShwf9).
**Playerbots Module** has a **[Discord server](https://discord.gg/NQm5QShwf9)** where you can discuss the project.
## Installation
Please note that this module requires specific custom changes to AzerothCore. To ensure compatibility, you must compile it with a custom branch from my fork, which can be found here: [liyunfan1223/azerothcore-wotlk/tree/Playerbot](https://github.com/liyunfan1223/azerothcore-wotlk/tree/Playerbot).
### Classic Installation
To install this module, please refer to the AzerothCore Wiki for detailed instructions: [AzerothCore Installation Guide](https://www.azerothcore.org/wiki/installation).
We've provided a simple method to clone the module:
`mod-playerbots` requires a custom branch of AzerothCore to work: [liyunfan1223/azerothcore-wotlk/tree/Playerbot](https://github.com/liyunfan1223/azerothcore-wotlk/tree/Playerbot). To install the module, simply run:
```bash
git clone https://github.com/liyunfan1223/azerothcore-wotlk.git --branch=Playerbot
@@ -22,57 +40,69 @@ cd azerothcore-wotlk/modules
git clone https://github.com/liyunfan1223/mod-playerbots.git --branch=master
```
## Quick Start & Documentation
For more information, refer to the [AzerothCore Installation Guide](https://www.azerothcore.org/wiki/installation) and [Installing a Module](https://www.azerothcore.org/wiki/installing-a-module) pages.
For a quick start and an extensive overview of available addons, commands, and recommended configuration please refer to the [Playerbots Wiki](https://github.com/liyunfan1223/mod-playerbots/wiki).
### Docker Installation
Please be aware that documentation for some newly added commands is currently lacking as the project is still under development.
**Docker installation is considered experimental.** To install the module on a Docker installation, run:
## Progress
```bash
git clone https://github.com/liyunfan1223/azerothcore-wotlk.git --branch=Playerbot
cd azerothcore-wotlk/modules
git clone https://github.com/liyunfan1223/mod-playerbots.git --branch=master
```
The module primarily emphasizes the following key features, and we have implemented improvements in these areas:
Afterwards, create a `docker-compose.override.yml` file in the `azerothcore-wotlk` directory. This override file allows for mounting the modules directory to the `ac-worldserver` service which is required for it to run. Put the following inside and save:
- **Bots in World (Random bot):** We have enhanced the behavior of random bots to make them mimic real players more closely, creating a more authentic player server environment.
```yml
services:
ac-worldserver:
volumes:
- ./modules:/azerothcore/modules:ro
```
- **Bots in Raid:** We've empowered bots to conquer challenging raid content by implementing specific strategies for various bosses, making raid encounters more engaging. Additionally, we have enhanced bots' capabilities in various roles such as DPS, healing, and tanking, ensuring they contribute effectively to the success of raid groups.
Additionally, this override file can be used to set custom configuration settings for `ac-worldserver` and any modules you install as environment variables:
- **Bots in Battleground:** Bots are now capable of actively participating in battlegrounds alongside real players, adding depth and excitement to these PvP scenarios.
```yml
services:
ac-worldserver:
environment:
AC_RATE_XP_KILL: "1"
AC_AI_PLAYERBOT_RANDOM_BOT_AUTOLOGIN: "1"
volumes:
- ./modules:/azerothcore/modules:ro
```
- **Interation with Bots:** We have improved the interaction between real players and bots, enabling players to complete quests and level up with multiple characters while collaborating with the bot companions.
For example, to double the experience gain rate per kill, take the setting `Rate.XP.Kill = 1` from [woldserver.conf](https://github.com/liyunfan1223/azerothcore-wotlk/blob/Playerbot/src/server/apps/worldserver/worldserver.conf.dist), convert it to an environment variable, and change it to the desired setting in the override file to get `AC_RATE_XP_KILL: "2"`. If you wanted to disable random bots from logging in automatically, take the `AiPlayerbot.RandomBotAutologin = 1` setting from [playerbots.conf](https://github.com/liyunfan1223/mod-playerbots/blob/master/conf/playerbots.conf.dist) and do the same to get `AC_AI_PLAYERBOT_RANDOM_BOT_AUTOLOGIN: "0"`. For more information on how to configure Azerothcore, Playerbots, and other module settings as environment variables in Docker Compose, see the "Configuring AzerothCore in Containers" section in the [Install With Docker](https://www.azerothcore.org/wiki/install-with-docker) guide.
- **Player Progression Path:** We have designed an improved progression path for players, complemented by bots, to offer an alternative and engaging gameplay experience.
Before building, consider setting the database password. One way to do this is to create a `.env` file in the root `azerothcore-wotlk` directory using the [template](https://github.com/liyunfan1223/azerothcore-wotlk/blob/Playerbot/conf/dist/env.docker). This file also allows you to set the user and group Docker uses for the services in case you run into any permissions issues, which are the most common cause for Docker installation problems.
- **Stability:** Our efforts have focused on enhancing the overall stability of AzerothCore when using the Playerbots module. These improvements aim to prevent server crashes and ensure a smoother experience for all users.
Use `docker compose up -d --build` to build and run the server. For more information, including how to create an account and taking backups, refer to the [Install With Docker](https://www.azerothcore.org/wiki/install-with-docker) page.
- **Configuration:** We have introduced a range of configurable options to cater to players with varying requirements, allowing for a more personalized experience.
## Documentation
It's essential to note that there is still a significant amount of work to be done as we continue to enhance the project. We welcome everyone to contribute in various ways.
The [Playerbots Wiki](https://github.com/liyunfan1223/mod-playerbots/wiki) contains an extensive overview of addons, commands, and recommended configurations. Please note that documentation may be incomplete or out-of-date in some sections. Contributions are welcome.
## Addon
## Frequently Asked Questions
- **Why aren't my bots casting spells?** Please make sure that the necessary English DBC file (enUS) is present.
- **What platforms are supported?** We support Ubuntu, Windows, and macOS. Other Linux distros may work, but will not receive support.
- **Why isn't my source compiling?** Please [check the build status of our CI](https://github.com/liyunfan1223/mod-playerbots/actions). If the latest build is failing, rever to the last successful commit until we address the issue.
## Addons
Typically, bots are controlled via chat commands. For larger bot groups, this can be unwieldy. As an alternative, community members have developed client Add-Ons to allow controlling bots through the in-game UI. We recommend you check out their projects:
For enhanced control over the bots and to simplify command usage, you can also make use of available Playerbots addons:
- [Multibot](https://github.com/Macx-Lio/MultiBot) (by Macx-Lio)
- [Unbot Addon (zh)](https://github.com/liyunfan1223/unbot-addon) (Chinese version by Liyunfan)
- [Unbot Addon (en)](https://github.com/noisiver/unbot-addon/tree/english) (English version translated by @Revision)
## Frequently Asked Questions
**Bots can't cast spells**
- Please make sure that the necessary English DBC file (enUS) is present.
**Compilation error**
- We support for Ubuntu, Windows, and macOS.
- Continuous integration workflows have been established. You can review the build status in [GitHub Actions](https://github.com/liyunfan1223/mod-playerbots/actions).
- If the latest build status fails, please revert to the previous commit. We will address the issue ASAP.
## Acknowledgements
The code for this module is ported from [ZhengPeiRu21/mod-playerbots](https://github.com/ZhengPeiRu21/mod-playerbots) and [celguar/mangosbot-bots](https://github.com/celguar/mangosbot-bots). We extend our gratitude to @ZhengPeiRu21 and @celguar for the continued efforts in maintaining the module.
We also want to express our sincere appreciation to all individuals who have contributed to playerbot development. Your dedication and efforts have been instrumental in shaping this project, and we are thankful for your contributions.
`mod-playerbots` is is based off [ZhengPeiRu21/mod-playerbots](https://github.com/ZhengPeiRu21/mod-playerbots) and [celguar/mangosbot-bots](https://github.com/celguar/mangosbot-bots). We extend our gratitude to [@ZhengPeiRu21](https://github.com/ZhengPeiRu21) and [@celguar](https://github.com/celguar) for the continued efforts in maintaining the module.
Also, a thank you to the many contributors who've helped build this project:
<a href="https://github.com/liyunfan1223/mod-playerbots/graphs/contributors">
<img src="https://contrib.rocks/image?repo=liyunfan1223/mod-playerbots" />
</a>

View File

@@ -1,41 +0,0 @@
# MY_NEW_MODULE
## Description
This module allows to do this and this.
## How to use ingame
Do this and that.
![my_new_module screenshot](/screenshots/my_module.png?raw=true "my_new_module screenshot")
<!-- Video example - We can't embed videos on github, only on github.io pages. If you can, make an animated gif of your video instead (but it's not required) -->
[![Youtube Link](https://i.imgur.com/Jhrdgv6.png)](https://www.youtube.com/watch?v=T6UEX47mPeE)
## Requirements
My_new_module requires:
- AzerothCore v4.0.0+
## Installation
```
1) Simply `git clone` the module under the `modules` directory of your AzerothCore source or copy paste it manually.
2) Import the SQL manually to the right Database (auth, world or characters) or with the `db_assembler.sh` (if `include.sh` provided).
3) Re-run cmake and launch a clean build of AzerothCore.
```
## Edit the module's configuration (optional)
If you need to change the module configuration, go to your server configuration directory (where your `worldserver` or `worldserver.exe` is), copy `my_module.conf.dist` to `my_module.conf` and edit that new file.
## Credits
* [Me](https://github.com/YOUR_GITHUB_NAME) (author of the module): Check out my soundcloud - Join my discord
* AzerothCore: [repository](https://github.com/azerothcore) - [website](http://azerothcore.org/) - [discord chat community](https://discord.gg/PaqQRkd)

View File

@@ -5,57 +5,59 @@
###################################################################################################
# SECTION INDEX
# GENERAL SETTINGS
# PLAYERBOT SETTINGS
# GENERAL
# SUMMON OPTIONS
# GEAR
# LOOTING
# TIMERS
# DISTANCES
# THRESHOLDS
# QUESTS
# COMBAT
# CHEATS
# SPELLS
# PLAYERBOT RNDBOT SPECIFIC SETTINGS
# GENERAL
# LEVELS
# GEAR
# QUESTS
# SPELLS
# STRATEGIES
# TELEPORTS
# BATTLEGROUND & ARENA & PVP
# INTERVALS
# PREMADE SPECS
# INFORMATION
# WARRIOR
# PALADIN
# HUNTER
# ROGUE
# PRIEST
# DEATHKNIGHT
# SHAMAN
# MAGE
# WARLOCK
# DRUID
# RANDOM BOT DEFAULT TALENT SPEC
# WARRIOR
# PALADIN
# HUNTER
# ROGUE
# PRIEST
# DEATHKNIGHT
# SHAMAN
# MAGE
# WARLOCK
# DRUID
# PLAYERBOT SYSTEM SETTINGS
# DATABASE & CONNECTIONS
# DEBUG
# CHAT SETTINGS
# LOGS
# DEPRECIATED (TEMPORARY)
# PLAYERBOT SETTINGS
# GENERAL
# SUMMON OPTIONS
# MOUNT
# GEAR
# LOOTING
# TIMERS
# DISTANCES
# THRESHOLDS
# QUESTS
# COMBAT
# CHEATS
# SPELLS
# PLAYERBOT RNDBOT SPECIFIC SETTINGS
# GENERAL
# LEVELS
# GEAR
# QUESTS
# ACTIVITIES
# SPELLS
# STRATEGIES
# TELEPORTS
# BATTLEGROUND & ARENA & PVP
# INTERVALS
# PREMADE SPECS
# INFORMATION
# WARRIOR
# PALADIN
# HUNTER
# ROGUE
# PRIEST
# DEATHKNIGHT
# SHAMAN
# MAGE
# WARLOCK
# DRUID
# RANDOM BOT DEFAULT TALENT SPEC
# WARRIOR
# PALADIN
# HUNTER
# ROGUE
# PRIEST
# DEATHKNIGHT
# SHAMAN
# MAGE
# WARLOCK
# DRUID
# PLAYERBOT SYSTEM SETTINGS
# DATABASE & CONNECTIONS
# DEBUG
# CHAT SETTINGS
# LOGS
# DEPRECIATED (TEMPORARY)
#
#
#
@@ -67,7 +69,7 @@
###################################
# #
# GENERAL SETTINGS #
# GENERAL SETTINGS #
# #
###################################
@@ -79,13 +81,15 @@ AiPlayerbot.Enabled = 1
# Enable random bot system
AiPlayerbot.RandomBotAutologin = 1
# Random bot account
# Please ensure that RandomBotAccountCount is greater than (MaxRandomBots / 10 + AddClassAccountPoolSize)
AiPlayerbot.RandomBotAccountCount = 200
# Random bot count
AiPlayerbot.MinRandomBots = 50
AiPlayerbot.MaxRandomBots = 50
AiPlayerbot.MinRandomBots = 500
AiPlayerbot.MaxRandomBots = 500
# Random bot accounts
# If you are not using any expansion at all, you may have to set this manually, then
# please ensure that RandomBotAccountCount is at least greater than (MaxRandomBots / 10 + AddClassAccountPoolSize)
# default: 0 - Automatic
AiPlayerbot.RandomBotAccountCount = 0
# Delete all random bot accounts (reset randombots)
AiPlayerbot.DeleteRandomBotAccounts = 0
@@ -105,18 +109,14 @@ AiPlayerbot.DeleteRandomBotAccounts = 0
#
#
# Maximum number of bots added by one account
# The maximum number of bots that a player can control simultaneously
AiPlayerbot.MaxAddedBots = 40
# Maximum number of bots per class added by one account
AiPlayerbot.MaxAddedBotsPerClass = 40
# Enable/Disable create bot by addclass command (0 = GM only, 1 = enable)
# default: 1 (enable)
AiPlayerbot.AddClassCommand = 1
# Set the addclass command account pool size
# Addclass command uses a subset of accounts from RandomBotAccountCount
AiPlayerbot.AddClassAccountPoolSize = 50
# Bot group invitation permission level (0 = GM only, 1 = accept based on level, 2 = always accept)
@@ -126,13 +126,21 @@ AiPlayerbot.GroupInvitationPermission = 1
# auto-login all player alts as bots on player login
AiPlayerbot.BotAutologin = 0
# Allow login other players' characters as bots
# Default: 0 (disabled)
AiPlayerbot.AllowPlayerBots = 0
# Allow/deny bots from the player's account
AiPlayerbot.AllowAccountBots = 1
# Allow/deny bots from your guild
# Allow/deny bots in the player's guild
AiPlayerbot.AllowGuildBots = 1
# Allow linking accounts for shared alt-bot control
AiPlayerbot.AllowTrustedAccountBots = 1
# Random bot guild count
AiPlayerbot.RandomBotGuildCount = 20
# Delete all random bot guilds
AiPlayerbot.DeleteRandomBotGuilds = 0
# Randombots will invite nearby bots to guilds
AiPlayerbot.RandomBotGuildNearby = 0
@@ -199,6 +207,36 @@ AiPlayerbot.BotRepairWhenSummon = 1
#
####################################################################################################
####################################################################################################
# MOUNT
#
#
# Defines at what level a bot will naturally use its 60% ground mount
# note: was level 20 during WotLK, 30 during TBC, 40 during Vanilla
# default: 20
AiPlayerbot.UseGroundMountAtMinLevel = 20
# Defines at what level a bot will naturally use its 100% fast ground mount
# note: was level 40 during WotLK, 60 during Vanilla
# default: 40
AiPlayerbot.UseFastGroundMountAtMinLevel = 40
# Defines at what level a bot will naturally use its 150% fly mount
# note: was level 60 during WotLK, 70 during TBC
# default: 60
AiPlayerbot.UseFlyMountAtMinLevel = 60
# Defines at what level a bot will naturally use its 280% fast fly mount
# note: was level 70 during WotLK and TBC
# default: 70
AiPlayerbot.UseFastFlyMountAtMinLevel = 70
#
#
#
####################################################################################################
####################################################################################################
# GEAR
#
@@ -334,9 +372,9 @@ AiPlayerbot.AggroDistance = 22
#
#
# Set kill XP rate for bots (default: 1)
# Server XP Rate * AiPlayerbot.KillXPRate
AiPlayerbot.KillXPRate = 1
# Set XP rate for bots (default: 1.0)
# Server XP Rate * AiPlayerbot.PlayerbotsXPRate
AiPlayerbot.PlayerbotsXPRate = 1.0
# Health/Mana levels
AiPlayerbot.CriticalHealth = 25
@@ -368,6 +406,10 @@ AiPlayerbot.SyncQuestWithPlayer = 1
# Default: 0 (disabled)
AiPlayerbot.SyncQuestForPlayer = 0
# Bots will drop obsolete quests
# Default: 1 (enabled)
AiPlayerbot.DropObsoleteQuests = 1
#
#
#
@@ -420,6 +462,10 @@ AiPlayerbot.MaintenanceCommand = 1
# default: 1 (enable)
AiPlayerbot.AutoGearCommand = 1
# Enable/Disable autogear command on player alt bots
# Default: 1 (enable)
AiPlayerbot.AutoGearCommandAltBots = 1
# Equips quality limitation for auto gear command (1 = normal, 2 = uncommon, 3 = rare, 4 = epic, 5 = legendary)
# default: 3 (rare)
AiPlayerbot.AutoGearQualityLimit = 3
@@ -466,14 +512,6 @@ AiPlayerbot.RandomBotRandomPassword = 0
# Accounts to create for random bots
AiPlayerbot.RandomBotAccountPrefix = "rndbot"
# Enable/Disable rotation of bots (randomly select a bot from the bots pool to go online and rotate them periodically)
# Need to reset rndbot after changing the setting (.playerbot rndbot reset)
# default: 0 (disable, the online bots are fixed)
AiPlayerbot.EnableRotation = 0
# Bots pool size for rotation (should be less than RandomBotAccountCount * 10)
AiPlayerbot.RotationPoolSize = 500
AiPlayerbot.RandomBotMinLevel = 1
AiPlayerbot.RandomBotMaxLevel = 80
@@ -487,10 +525,31 @@ AiPlayerbot.PreQuests = 0
# Enable LFG for random bots
AiPlayerbot.RandomBotJoinLfg = 1
# Enable/Disable periodic online - offline to mimic the real-world scenario where not all players are online simultaneously
# When enabled, bots are randomly selected to go online or offline periodically from a larger set
# Default: 0 (disabled, the set of online bots remains fixed)
AiPlayerbot.EnablePeriodicOnlineOffline = 0
# Defines the ratio between the total number of bots (including offline ones) and the number of bots currently online (MaxRandomBots)
# This setting must greater than 1.0 and only applies when EnablePeriodicOnlineOffline
# Default: 2.0 (total number of bots is twice the number of MaxRandomBots)
AiPlayerbot.PeriodicOnlineOfflineRatio = 2.0
# Percentage ratio of alliance and horde
AiPlayerbot.RandomBotAllianceRatio = 50
AiPlayerbot.RandomBotHordeRatio = 50
# Disable death knight for bots login
# Need to reset rndbot after changing the setting (.playerbot rndbot reset)
AiPlayerbot.DisableDeathKnightLogin = 0
# Enable expansion limitation for talents and glyphs - ie: level <= 60 bot only uses talents
# available in vanilla, level <= 70 bot only uses talents available in TBC)
# Default: 0
AiPlayerbot.LimitTalentsExpansion = 0
# Configure random bots and addClass bot trading (0: Disabled, 1: Enabled, 2: Only buy, 3: Only Sell)
# Default: 1 (Enabled)
AiPlayerbot.EnableRandomBotTrading = 1
#
#
#
@@ -506,10 +565,13 @@ AiPlayerbot.DisableDeathKnightLogin = 0
AiPlayerbot.DisableRandomLevels = 0
# Set randombots starting level here if "AiPlayerbot.DisableRandomLevels" enabled
AiPlayerbot.RandombotStartingLevel = 5
AiPlayerbot.RandombotStartingLevel = 1
# Chance random bot has max level on first randomize (default 0.15)
AiPlayerbot.RandomBotMaxLevelChance = 0.15
# Chance random bot has min level on first randomize (default 0.1)
AiPlayerbot.RandomBotMinLevelChance = 0.1
# Chance random bot has max level on first randomize (default 0.1)
AiPlayerbot.RandomBotMaxLevelChance = 0.1
# Fix the level of random bot (won't level up by grinding)
# Default: 0 (disable)
@@ -568,6 +630,50 @@ AiPlayerbot.EquipmentPersistenceLevel = 80
# Default: 1 (enabled)
AiPlayerbot.AutoUpgradeEquip = 1
# Only set wolf pets for hunters to have higher damage (0 = disabled, 1 = enabled only for max-level, 2 = enabled)
# Default: 0 (disabled)
AiPlayerbot.HunterWolfPet = 0
#
#
#
####################################################################################################
####################################################################################################
# ACTIVITIES
#
#
# Specify percent of active bots
# The default is 100%, but would be automatically adjusted if botActiveAloneSmartScale
# is enabled. Regardless, this value is only applied to inactive areas where no real-players
# are detected. When real-players are nearby, friend, group, guild, BGs, instances etc,
# the value is always enforced to 100%
AiPlayerbot.BotActiveAlone = 100
# Force botActiveAlone when bot is ... of real player
AiPlayerbot.BotActiveAloneForceWhenInRadius = 150
AiPlayerbot.BotActiveAloneForceWhenInZone = 1
AiPlayerbot.BotActiveAloneForceWhenInMap = 0
AiPlayerbot.BotActiveAloneForceWhenIsFriend = 1
AiPlayerbot.BotActiveAloneForceWhenInGuild = 1
# SmartScale is enabled or not.
# The default is 1. When enabled (smart) scales the 'BotActiveAlone' value.
# (The scaling will be overruled by the BotActiveAloneForceWhen...rules)
#
# Limitfloor - when DIFF (latency) above floor, activity scaling is applied starting with 90%
# LimitCeiling - when DIFF (latency) above ceiling, activity is 0%;
#
# MinLevel - only apply scaling when level is above or equal to min(bot)Level
# MaxLevel - only apply scaling when level is lower or equal of max(bot)Level
#
AiPlayerbot.botActiveAloneSmartScale = 1
AiPlayerbot.botActiveAloneSmartScaleDiffLimitfloor = 50
AiPlayerbot.botActiveAloneSmartScaleDiffLimitCeiling = 200
AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel = 1
AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel = 80
#
#
#
@@ -588,6 +694,11 @@ AiPlayerbot.RandomBotGroupNearby = 0
# Default: 1 (enabled)
AiPlayerbot.AutoDoQuests = 1
# Random Bots will behave more like real players (exprimental)
# This option will override AutoDoQuests
# Default: 1 (enabled)
AiPlayerbot.EnableNewRpgStrategy = 1
# Quest items to leave (do not destroy)
AiPlayerbot.RandomBotQuestItems = "6948,5175,5176,5177,5178,16309,12382,13704,11000"
@@ -674,18 +785,56 @@ AiPlayerbot.AutoTeleportForLevel = 1
# Enable BG/Arena for random Bots
AiPlayerbot.RandomBotJoinBG = 1
# Enable Auto join BG - bots randomly join WSG and 2v2 Arena if server is not lagging
# Enable Auto join BG - have bots start BG's and Arenas on their own
AiPlayerbot.RandomBotAutoJoinBG = 0
# Required for RandomBotAutoJoinBG
# Currently you can select 1 bracket (level range) for bots to auto join.
# Brackets for warsong 0:10-19, 1:20-29, 2:30-39, 3:40-49 etc. Default: 7 (level 80)
# Brackets for rated arena: 0:10-14, 1:15-19 etc. Default: 14 (80-84)
# For lower level ranges to work in Rated Arena, custom code changes need to be made.
# Count = amount of games Bots auto fill. (Count 1 for WSG = 20 bots).
AiPlayerbot.RandomBotAutoJoinWarsongBracket = 7
# Required Configuration for RandomBotAutoJoinBG
#
# Known issue: When enabling a lot of brackats in combination with multiple instances,
# can lead to more instances created by bots than intended (over-queuing).
#
# This section controls the level brackets and
# automatic bot participation in battlegrounds and arenas.
#
# Brackets:
# - Specify the level ranges for bots to auto-join:
# - Warsong Gulch (WS): 0 = 10-19, 1 = 20-29, 2 = 30-39, ..., 7 = 80 (default: 7)
# - Rated Arena: 0 = 10-14, 1 = 15-19, ..., 14 = 80-84 (default: 14)
# - Multiple brackets can be specified as a comma-separated list (e.g., "0,2,5").
#
# Counts:
# - Specify the number of Battlegrounds to auto-fill per bracket.
# - For battlegrounds, Count is the number of bots per bracket. For example:
# - Warsong Gulch Count = 1 adds 20 bots (10 per team).
# - Ensure there are enough eligible bots to meet the specified counts.
#
# Arena Considerations:
# - Rated Arena brackets default to level 80-84 (bracket 14).
# - Custom code changes are required for lower-level arena brackets to function properly.
#
# Battleground bracket range possibilities:
# AiPlayerbot.RandomBotAutoJoinICBrackets = 0,1
# AiPlayerbot.RandomBotAutoJoinEYBrackets = 0,1,2
# AiPlayerbot.RandomBotAutoJoinAVBrackets = 0,1,2,3
# AiPlayerbot.RandomBotAutoJoinABBrackets = 0,1,2,3,4,5,6
# AiPlayerbot.RandomBotAutoJoinWSBrackets = 0,1,2,3,4,5,6,7
AiPlayerbot.RandomBotAutoJoinICBrackets = 1
AiPlayerbot.RandomBotAutoJoinEYBrackets = 2
AiPlayerbot.RandomBotAutoJoinAVBrackets = 3
AiPlayerbot.RandomBotAutoJoinABBrackets = 6
AiPlayerbot.RandomBotAutoJoinWSBrackets = 7
# Battlegrounds count (per bracket!):
AiPlayerbot.RandomBotAutoJoinBGICCount = 0
AiPlayerbot.RandomBotAutoJoinBGEYCount = 1
AiPlayerbot.RandomBotAutoJoinBGAVCount = 0
AiPlayerbot.RandomBotAutoJoinBGABCount = 1
AiPlayerbot.RandomBotAutoJoinBGWSCount = 1
# Arena configuration:
AiPlayerbot.RandomBotAutoJoinArenaBracket = 14
AiPlayerbot.RandomBotAutoJoinBGWarsongCount = 0
AiPlayerbot.RandomBotAutoJoinBGRatedArena2v2Count = 0
AiPlayerbot.RandomBotAutoJoinBGRatedArena3v3Count = 0
AiPlayerbot.RandomBotAutoJoinBGRatedArena5v5Count = 0
@@ -709,10 +858,10 @@ AiPlayerbot.RandomBotArenaTeamMinRating = 1000
AiPlayerbot.DeleteRandomBotArenaTeams = 0
# PvP Restricted Zones (bots don't pvp)
AiPlayerbot.PvpProhibitedZoneIds = "2255,656,2361,2362,2363,976,35,2268,3425,392,541,1446,3828,3712,3738,3565,3539,3623,4152,3988,4658,4284,4418,4436,4275,4323,4395,3703,4298"
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,139"
# PvP Restricted Areas (bots don't pvp)
AiPlayerbot.PvpProhibitedAreaIds = "976,35,392"
AiPlayerbot.PvpProhibitedAreaIds = "976,35,392,2268,4161,4010,4317,4312"
# Improve react speed in battleground and arena (may cause lag)
AiPlayerbot.FastReactInBG = 1
@@ -731,8 +880,8 @@ AiPlayerbot.FastReactInBG = 1
AiPlayerbot.RandomBotUpdateInterval = 20
AiPlayerbot.RandomBotCountChangeMinInterval = 1800
AiPlayerbot.RandomBotCountChangeMaxInterval = 7200
AiPlayerbot.MinRandomBotInWorldTime = 3600
AiPlayerbot.MaxRandomBotInWorldTime = 1209600
AiPlayerbot.MinRandomBotInWorldTime = 600
AiPlayerbot.MaxRandomBotInWorldTime = 28800
AiPlayerbot.MinRandomBotRandomizeTime = 7200
AiPlayerbot.MaxRandomBotRandomizeTime = 1209600
AiPlayerbot.RandomBotsPerInterval = 60
@@ -740,7 +889,7 @@ AiPlayerbot.MinRandomBotReviveTime = 60
AiPlayerbot.MaxRandomBotReviveTime = 300
AiPlayerbot.MinRandomBotTeleportInterval = 3600
AiPlayerbot.MaxRandomBotTeleportInterval = 18000
AiPlayerbot.RandomBotInWorldWithRotationDisabled = 31104000
AiPlayerbot.PermanantlyInWorldTime = 31104000
#
#
@@ -823,8 +972,8 @@ AiPlayerbot.PremadeSpecLink.2.2.80 = 050501-05-05232051203331302133231331
AiPlayerbot.PremadeSpecName.3.0 = bm pve
AiPlayerbot.PremadeSpecGlyph.3.0 = 42912,43350,42902,43351,43338,45732
AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112243100511351
AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112253100531351-015305021
AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112243110531051
AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112243120531251-025305101
AiPlayerbot.PremadeSpecName.3.1 = mm pve
AiPlayerbot.PremadeSpecGlyph.3.1 = 42912,43350,42914,43351,43338,45732
AiPlayerbot.PremadeSpecLink.3.1.60 = -025315101030013233125031051
@@ -858,16 +1007,16 @@ AiPlayerbot.PremadeHunterPetLink.2.20 = 21000203300002110221
AiPlayerbot.PremadeSpecName.4.0 = as pve
AiPlayerbot.PremadeSpecGlyph.4.0 = 45768,43379,45761,43380,43378,45766
AiPlayerbot.PremadeSpecLink.4.0.60 = 005323005350100520103331051
AiPlayerbot.PremadeSpecLink.4.0.80 = 005323005350100520103331051-005005005003-2
AiPlayerbot.PremadeSpecLink.4.0.60 = 005303104352100520103331051
AiPlayerbot.PremadeSpecLink.4.0.80 = 005303104352100520103331051-005005005003-2
AiPlayerbot.PremadeSpecName.4.1 = combat pve
AiPlayerbot.PremadeSpecGlyph.4.1 = 42962,43379,45762,43380,43378,42969
AiPlayerbot.PremadeSpecLink.4.1.60 = -0252051000035015223100501251
AiPlayerbot.PremadeSpecLink.4.1.80 = 00532000523-0252051000035015223100501251
AiPlayerbot.PremadeSpecName.4.2 = subtlety pve
AiPlayerbot.PremadeSpecGlyph.4.2 = 42967,43379,45764,43380,43378,45767
AiPlayerbot.PremadeSpecLink.4.2.60 = --5120122030321121050135031241
AiPlayerbot.PremadeSpecLink.4.2.80 = 0053231-2-5120222030321121050135231251
AiPlayerbot.PremadeSpecLink.4.2.60 = --5022012030321121350115031151
AiPlayerbot.PremadeSpecLink.4.2.80 = 30532010114--5022012030321121350115031151
#
#
@@ -911,7 +1060,7 @@ AiPlayerbot.PremadeSpecGlyph.6.1 = 45805,43673,43547,43544,43672,43543
AiPlayerbot.PremadeSpecLink.6.1.60 = -32003350332203012300023101351
AiPlayerbot.PremadeSpecLink.6.1.80 = -32002350352203012300033101351-230200305003
AiPlayerbot.PremadeSpecName.6.2 = unholy pve
AiPlayerbot.PremadeSpecGlyph.6.2 = 43542,43673,45804,43544,43672,43549
AiPlayerbot.PremadeSpecGlyph.6.2 = 43542,43673,43546,43544,43672,43549
AiPlayerbot.PremadeSpecLink.6.2.60 = --2301303050032151000150013131151
AiPlayerbot.PremadeSpecLink.6.2.80 = -320033500002-2301303050032151000150013133151
AiPlayerbot.PremadeSpecName.6.3 = double aura blood pve
@@ -964,6 +1113,10 @@ AiPlayerbot.PremadeSpecName.8.2 = frost pve
AiPlayerbot.PremadeSpecGlyph.8.2 = 42742,43339,50045,43364,43361,42751
AiPlayerbot.PremadeSpecLink.8.2.60 = --0533030313203100030152231151
AiPlayerbot.PremadeSpecLink.8.2.80 = 23002303110003--0533030313203100030152231351
AiPlayerbot.PremadeSpecName.8.3 = frostfire pve
AiPlayerbot.PremadeSpecGlyph.8.3 = 44684,44920,42751,43339,43364,45737
AiPlayerbot.PremadeSpecLink.8.3.60 = -2305032012303331053120300051
AiPlayerbot.PremadeSpecLink.8.3.80 = -2305032012303331053120311351-023303031
#
#
@@ -1022,6 +1175,58 @@ AiPlayerbot.PremadeSpecLink.11.3.80 = -553202032322010053100030310511-205503012
#
###################################################################################################
###################################
# #
# WORLD BUFFS #
# #
###################################
####################################################################################################
#
#
#
# Applies a permanent buff to all bots when not in combat simulating flasks, food, rune etc.
# WorldBuff.Faction.Class.Spec.MinLevel.MaxLevel
AiPlayerbot.WorldBuff.0.1.0.80.80 = 53760,57358 #WARRIOR ARMS
AiPlayerbot.WorldBuff.0.1.1.80.80 = 53760,57358 #WARRIOR FURY
AiPlayerbot.WorldBuff.0.1.2.80.80 = 53758,57356 #WARRIOR PROTECTION
AiPlayerbot.WorldBuff.0.2.0.80.80 = 60347,53749,57332 #PALADIN HOLY
AiPlayerbot.WorldBuff.0.2.1.80.80 = 53758,57356 #PALADIN PROTECTION
AiPlayerbot.WorldBuff.0.2.2.80.80 = 53760,57371 #PALADIN RETRIBUTION
AiPlayerbot.WorldBuff.0.3.0.80.80 = 53760,57325 #HUNTER BEAST
AiPlayerbot.WorldBuff.0.3.1.80.80 = 53760,57358 #HUNTER MARKSMANSHIP
AiPlayerbot.WorldBuff.0.3.2.80.80 = 53760,57367 #HUNTER SURVIVAL
AiPlayerbot.WorldBuff.0.4.0.80.80 = 53760,57325 #ROGUE ASSASINATION
AiPlayerbot.WorldBuff.0.4.1.80.80 = 53760,57358 #ROGUE COMBAT
AiPlayerbot.WorldBuff.0.4.2.80.80 = 53760,57367 #ROGUE SUBTLETY
AiPlayerbot.WorldBuff.0.5.0.80.80 = 53755,57327 #PRIEST DISCIPLINE
AiPlayerbot.WorldBuff.0.5.1.80.80 = 53755,57327 #PRIEST HOLY
AiPlayerbot.WorldBuff.0.5.2.80.80 = 53755,57327 #PRIEST SHADOW
AiPlayerbot.WorldBuff.0.6.0.80.80 = 53758,57356 #DEATH KNIGHT BLOOD
AiPlayerbot.WorldBuff.0.6.1.80.80 = 53760,57358 #DEATH KNIGHT FROST
AiPlayerbot.WorldBuff.0.6.2.80.80 = 53760,57358 #DEATH KNIGHT UNHOLY
AiPlayerbot.WorldBuff.0.6.3.80.80 = 53760,57371 #DEATH KNIGHT BLOOD DPS
AiPlayerbot.WorldBuff.0.7.0.80.80 = 53755,57327 #SHAMAN ELEMENTAL
AiPlayerbot.WorldBuff.0.7.1.80.80 = 53760,57325 #SHAMAN ENHANCEMENT
AiPlayerbot.WorldBuff.0.7.2.80.80 = 53755,57327 #SHAMAN RESTORATION
AiPlayerbot.WorldBuff.0.8.0.80.80 = 53755,57327 #MAGE ARCANE
AiPlayerbot.WorldBuff.0.8.1.80.80 = 53755,57327 #MAGE FIRE
AiPlayerbot.WorldBuff.0.8.2.80.80 = 53755,57327 #MAGE FROST
AiPlayerbot.WorldBuff.0.9.0.80.80 = 53755,57327 #WARLOCK AFFLICTION
AiPlayerbot.WorldBuff.0.9.1.80.80 = 53755,57327 #WARLOCK DEMONOLOGY
AiPlayerbot.WorldBuff.0.9.2.80.80 = 53755,57327 #WARLOCK DESTRUCTION
AiPlayerbot.WorldBuff.0.11.0.80.80 = 53755,57327 #DRUID BALANCE
AiPlayerbot.WorldBuff.0.11.1.80.80 = 53749,53763,57367 #DRUID FERAL BEAR
AiPlayerbot.WorldBuff.0.11.2.80.80 = 54212,57334 #DRUID RESTORATION
AiPlayerbot.WorldBuff.0.11.3.80.80 = 53760,57358 #DRUID FERAL CAT
#
#
#
###################################################################################################
###################################
# #
# RANDOM BOT DEFAULT TALENT SPEC #
@@ -1029,7 +1234,7 @@ AiPlayerbot.PremadeSpecLink.11.3.80 = -553202032322010053100030310511-205503012
###################################
####################################################################################################
#
#
#
#
@@ -1411,9 +1616,6 @@ AiPlayerbot.BroadcastChanceGuildManagement = 30000
# Example: AiPlayerbot.AllowedLogFiles = travelNodes.csv,travelPaths.csv,TravelNodeStore.h,bot_movement.csv,bot_location.csv
AiPlayerbot.AllowedLogFiles = ""
Appender.Playerbots=2,5,0,Playerbots.log,w
Logger.playerbots=5,Console Playerbots
#
#
#
@@ -1438,12 +1640,6 @@ AiPlayerbot.EnableGuildTasks = 0
# Enable dungeon suggestions in lower case randomly
AiPlayerbot.SuggestDungeonsInLowerCaseRandomly = 0
# Random bot guild count
AiPlayerbot.RandomBotGuildCount = 20
# Delete all random bot guilds
AiPlayerbot.DeleteRandomBotGuilds = 0
# Chance bot chooses RPG (Teleport to random camp for their level) instead of grinding
AiPlayerbot.RandomBotRpgChance = 0.20
@@ -1453,20 +1649,6 @@ AiPlayerbot.RandombotsWalkingRPG = 0
# Set randombots movement speed to walking only inside buildings
AiPlayerbot.RandombotsWalkingRPG.InDoors = 0
# Specify percent of active bots
# The default is 10. With 10% of all bots going active or inactive each minute. Regardless
# This value is only applied to inactive areas where no real-players are detected, when
# real-players are nearby, friend, group, guild, bg, instances etc the value is always
# enforced to 100%
AiPlayerbot.BotActiveAlone = 100
# Specify smart scaling is enabled or not.
# The default is 1. When enabled (smart) scales the 'BotActiveAlone' value.
# Only when botLevel is between WhenMinLevel and WhenMaxLevel.
AiPlayerbot.botActiveAloneSmartScale = 1
AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel = 1
AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel = 80
# Premade spell to avoid (undetected spells)
# spellid-radius, ...
AiPlayerbot.PremadeAvoidAoe = 62234-4

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
DROP TABLE IF EXISTS `playerbot_account_keys`;
CREATE TABLE `playerbot_account_keys` (
`account_id` INT PRIMARY KEY,
`security_key` VARCHAR(255) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB DEFAULT CHARSET=latin1;

View File

@@ -0,0 +1,9 @@
DROP TABLE IF EXISTS `playerbot_account_links`;
CREATE TABLE `playerbot_account_links` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`account_id` INT NOT NULL,
`linked_account_id` INT NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY `account_link` (`account_id`, `linked_account_id`)
) ENGINE=INNODB DEFAULT CHARSET=latin1;

View File

@@ -0,0 +1,11 @@
UPDATE `updates_include`
SET `path` = '$/data/sql/playerbots/updates'
WHERE `state` = 'RELEASED';
UPDATE `updates_include`
SET `path` = '$/data/sql/playerbots/custom'
WHERE `state` = 'CUSTOM';
UPDATE `updates_include`
SET `path` = '$/data/sql/playerbots/archive'
WHERE `state` = 'ARCHIVED';

View File

@@ -0,0 +1,4 @@
-- Update max_level for TBC Heroic dungeons in `playerbots_dungeon_suggestion_definition`
UPDATE `playerbots_dungeon_suggestion_definition`
SET `max_level` = 73
WHERE `id` IN (40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56);

View File

@@ -0,0 +1,22 @@
-- Delete existing entries from playerbots_travelnode, playerbots_travelnode_path, and playerbots_travelnode_link tables
DELETE FROM `playerbots_travelnode_link` WHERE `node_id` = 3780;
DELETE FROM `playerbots_travelnode_path` WHERE `node_id` = 3780;
DELETE FROM `playerbots_travelnode` WHERE `id` = 3780;
-- Insert new entries into playerbots_travelnode
INSERT INTO `playerbots_travelnode` (`id`, `name`, `map_id`, `x`, `y`, `z`, `linked`)
VALUES (3780, 'Highlord Mograine', 533, 2524.32, -2951.28, 245.633, 1);
-- Insert new entries into playerbots_travelnode_path
INSERT INTO `playerbots_travelnode_path` (`node_id`, `to_node_id`, `nr`, `map_id`, `x`, `y`, `z`)
VALUES
(3780, 472, 0, 533, 2524.32, -2951.28, 245.633),
(3780, 472, 1, 533, 2528.79, -2948.58, 245.633),
(3780, 757, 0, 533, 2524.32, -2951.28, 245.633),
(3780, 757, 1, 533, 2517.62, -2959.38, 245.636);
-- Insert new entries into playerbots_travelnode_link
INSERT INTO `playerbots_travelnode_link` (`node_id`, `to_node_id`, `type`, `object`, `distance`, `swim_distance`, `extra_cost`, `calculated`, `max_creature_0`, `max_creature_1`, `max_creature_2`)
VALUES
(3780, 472, 1, 0, 5.3221, 0, 0, 1, 83, 0, 0),
(3780, 757, 1, 0, 10.6118, 0, 0, 1, 83, 0, 0);

View File

@@ -0,0 +1,25 @@
-- ##########################################################
-- # Playerbots RandomBots Performance Update
-- # Add missing index to reduce Deadlocks
-- # Author: Raz0r1337 aka St0ny
-- # Date: 2025-04-26
-- ##########################################################
-- Check if the index already exists
SET @index_exists := (
SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'playerbots_random_bots'
AND INDEX_NAME = 'idx_owner_bot_event'
);
-- Conditionally create the index only if it doesn't exist
SET @ddl := IF(@index_exists = 0,
'ALTER TABLE `playerbots_random_bots` ADD INDEX `idx_owner_bot_event` (`owner`, `bot`, `event`);',
'SELECT "Index idx_owner_bot_event already exists.";'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@@ -0,0 +1,17 @@
DROP TABLE IF EXISTS `playerbot_account_links`;
CREATE TABLE `playerbot_account_links` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`account_id` INT NOT NULL,
`linked_account_id` INT NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY `account_link` (`account_id`, `linked_account_id`)
) ENGINE=INNODB DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `playerbot_account_keys`;
CREATE TABLE `playerbot_account_keys` (
`account_id` INT PRIMARY KEY,
`security_key` VARCHAR(255) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB DEFAULT CHARSET=latin1;

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -13,13 +13,17 @@
#include "ChatFilter.h"
#include "ChatHelper.h"
#include "Common.h"
#include "CreatureData.h"
#include "Event.h"
#include "Item.h"
#include "NewRpgInfo.h"
#include "NewRpgStrategy.h"
#include "PlayerbotAIBase.h"
#include "PlayerbotAIConfig.h"
#include "PlayerbotSecurity.h"
#include "PlayerbotTextMgr.h"
#include "SpellAuras.h"
#include "Util.h"
#include "WorldPacket.h"
class AiObjectContext;
@@ -388,6 +392,8 @@ public:
void HandleMasterOutgoingPacket(WorldPacket const& packet);
void HandleTeleportAck();
void ChangeEngine(BotState type);
void ChangeEngineOnCombat();
void ChangeEngineOnNonCombat();
void DoNextAction(bool minimal = false);
virtual bool DoSpecificAction(std::string const name, Event event = Event(), bool silent = false,
std::string const qualifier = "");
@@ -407,8 +413,8 @@ public:
static bool IsRanged(Player* player, bool bySpec = false);
static bool IsMelee(Player* player, bool bySpec = false);
static bool IsCaster(Player* player, bool bySpec = false);
static bool IsCombo(Player* player, bool bySpec = false);
static bool IsRangedDps(Player* player, bool bySpec = false);
static bool IsCombo(Player* player);
static bool IsMainTank(Player* player);
static uint32 GetGroupTankNum(Player* player);
bool IsAssistTank(Player* player);
@@ -418,7 +424,7 @@ public:
bool HasAggro(Unit* unit);
int32 GetGroupSlotIndex(Player* player);
int32 GetRangedIndex(Player* player);
int32 GetClassIndex(Player* player, uint8_t cls);
int32 GetClassIndex(Player* player, uint8 cls);
int32 GetRangedDpsIndex(Player* player);
int32 GetMeleeIndex(Player* player);
@@ -432,8 +438,9 @@ public:
std::vector<Player*> GetPlayersInGroup();
const AreaTableEntry* GetCurrentArea();
const AreaTableEntry* GetCurrentZone();
std::string GetLocalizedAreaName(const AreaTableEntry* entry);
static std::string GetLocalizedAreaName(const AreaTableEntry* entry);
static std::string GetLocalizedCreatureName(uint32 entry);
static std::string GetLocalizedGameObjectName(uint32 entry);
bool TellMaster(std::ostringstream& stream, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
bool TellMaster(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
bool TellMasterNoFacing(std::ostringstream& stream,
@@ -460,7 +467,10 @@ public:
bool PlayEmote(uint32 emote);
void Ping(float x, float y);
Item* FindPoison() const;
Item* FindAmmo() const;
Item* FindBandage() const;
Item* FindOpenableItem() const;
Item* FindLockedItem() const;
Item* FindConsumable(uint32 displayId) const;
Item* FindStoneFor(Item* weapon) const;
Item* FindOilFor(Item* weapon) const;
@@ -482,8 +492,8 @@ public:
virtual bool HasAuraToDispel(Unit* player, uint32 dispelType);
bool CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell = true, Item* itemTarget = nullptr,
Item* castItem = nullptr);
bool CanCastSpell(uint32 spellid, GameObject* goTarget, uint8 effectMask, bool checkHasSpell = true);
bool CanCastSpell(uint32 spellid, float x, float y, float z, uint8 effectMask, bool checkHasSpell = true,
bool CanCastSpell(uint32 spellid, GameObject* goTarget, bool checkHasSpell = true);
bool CanCastSpell(uint32 spellid, float x, float y, float z, bool checkHasSpell = true,
Item* itemTarget = nullptr);
bool HasAura(uint32 spellId, Unit const* player);
@@ -499,7 +509,8 @@ public:
bool IsInVehicle(bool canControl = false, bool canCast = false, bool canAttack = false, bool canTurn = false,
bool fixed = false);
uint32 GetEquipGearScore(Player* player, bool withBags, bool withBank);
uint32 GetEquipGearScore(Player* player);
//uint32 GetEquipGearScore(Player* player, bool withBags, bool withBank);
static uint32 GetMixedGearScore(Player* player, bool withBags, bool withBank, uint32 topN = 0);
bool HasSkill(SkillType skill);
bool IsAllowedCommand(std::string const text);
@@ -519,7 +530,7 @@ public:
bool IsAlt();
Player* GetGroupMaster();
// Returns a semi-random (cycling) number that is fixed for each bot.
uint32 GetFixedBotNumer(BotTypeNumber typeNumber, uint32 maxNum = 100, float cyclePerMin = 1);
uint32 GetFixedBotNumer(uint32 maxNum = 100, float cyclePerMin = 1);
GrouperType GetGrouperType();
GuilderType GetGuilderType();
bool HasPlayerNearby(WorldPosition* pos, float range = sPlayerbotAIConfig->reactDistance);
@@ -554,6 +565,7 @@ public:
void ResetJumpDestination() { jumpDestination = Position(); }
bool CanMove();
static bool IsRealGuild(uint32 guildId);
bool IsInRealGuild();
static std::vector<std::string> dispel_whitelist;
bool EqualLowercaseName(std::string s1, std::string s2);
@@ -572,15 +584,21 @@ public:
std::set<uint32> GetCurrentIncompleteQuestIds();
void PetFollow();
static float GetItemScoreMultiplier(ItemQualities quality);
static bool IsHealingSpell(uint32 spellFamilyName, flag96 spelFalimyFlags);
static SpellFamilyNames Class2SpellFamilyName(uint8 cls);
NewRpgInfo rpgInfo;
NewRpgStatistic rpgStatistic;
std::unordered_set<uint32> lowPriorityQuest;
private:
static void _fillGearScoreData(Player* player, Item* item, std::vector<uint32>* gearScore, uint32& twoHandScore,
bool mixed = false);
bool IsTellAllowed(PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
void UpdateAIGroupMembership();
Item* FindItemInInventory(std::function<bool(ItemTemplate const*)> checkItem) const;
void HandleCommands();
void HandleCommand(uint32 type, const std::string& text, Player& fromPlayer, const uint32 lang = LANG_UNIVERSAL);
bool _isBotInitializing = true;
bool _isBotInitializing = false;
protected:
Player* bot;

View File

@@ -120,16 +120,18 @@ bool PlayerbotAIConfig::Initialize()
randomGearQualityLimit = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomGearQualityLimit", 3);
randomGearScoreLimit = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomGearScoreLimit", 0);
randomBotMaxLevelChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotMaxLevelChance", 0.15f);
randomBotMinLevelChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotMinLevelChance", 0.1f);
randomBotMaxLevelChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotMaxLevelChance", 0.1f);
randomBotRpgChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotRpgChance", 0.20f);
iterationsPerTick = sConfigMgr->GetOption<int32>("AiPlayerbot.IterationsPerTick", 100);
allowAccountBots = sConfigMgr->GetOption<bool>("AiPlayerbot.AllowAccountBots", true);
allowGuildBots = sConfigMgr->GetOption<bool>("AiPlayerbot.AllowGuildBots", true);
allowTrustedAccountBots = sConfigMgr->GetOption<bool>("AiPlayerbot.AllowTrustedAccountBots", true);
randomBotGuildNearby = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGuildNearby", false);
randomBotInvitePlayer = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotInvitePlayer", false);
inviteChat = sConfigMgr->GetOption<bool>("AiPlayerbot.InviteChat", false);
allowPlayerBots = sConfigMgr->GetOption<bool>("AiPlayerbot.AllowPlayerBots", false);
randomBotMapsAsString = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotMaps", "0,1,530,571");
LoadList<std::vector<uint32>>(randomBotMapsAsString, randomBotMaps);
@@ -155,7 +157,7 @@ bool PlayerbotAIConfig::Initialize()
botAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.BotAutologin", false);
randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true);
minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 50);
maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 200);
maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 50);
randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", 20);
randomBotCountChangeMinInterval =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE);
@@ -173,8 +175,8 @@ bool PlayerbotAIConfig::Initialize()
maxRandomBotReviveTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE);
minRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR);
maxRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR);
randomBotInWorldWithRotationDisabled =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotInWorldWithRotationDisabled", 1 * YEAR);
permanantlyInWorldTime =
sConfigMgr->GetOption<int32>("AiPlayerbot.PermanantlyInWorldTime", 1 * YEAR);
randomBotTeleportDistance = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotTeleportDistance", 100);
randomBotsPerInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotsPerInterval", 60);
minRandomBotsPriceChangeInterval =
@@ -278,9 +280,21 @@ bool PlayerbotAIConfig::Initialize()
randomBotJoinBG = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotJoinBG", true);
randomBotAutoJoinBG = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutoJoinBG", false);
randomBotAutoJoinWarsongBracket = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinWarsongBracket", 14);
randomBotAutoJoinArenaBracket = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinArenaBracket", 7);
randomBotAutoJoinBGWarsongCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGWarsongCount", 0);
randomBotAutoJoinICBrackets = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotAutoJoinICBrackets", "0,1");
randomBotAutoJoinEYBrackets = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotAutoJoinEYBrackets", "0,1,2");
randomBotAutoJoinAVBrackets = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotAutoJoinAVBrackets", "0,1,2,3");
randomBotAutoJoinABBrackets = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotAutoJoinABBrackets", "0,1,2,3,4,5,6");
randomBotAutoJoinWSBrackets = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotAutoJoinWSBrackets", "0,1,2,3,4,5,6,7");
randomBotAutoJoinBGICCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGICCount", 0);
randomBotAutoJoinBGEYCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGEYCount", 0);
randomBotAutoJoinBGAVCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGAVCount", 0);
randomBotAutoJoinBGABCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGABCount", 0);
randomBotAutoJoinBGWSCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGWSCount", 0);
randomBotAutoJoinBGRatedArena2v2Count =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGRatedArena2v2Count", 0);
randomBotAutoJoinBGRatedArena3v3Count =
@@ -312,9 +326,12 @@ bool PlayerbotAIConfig::Initialize()
commandServerPort = sConfigMgr->GetOption<int32>("AiPlayerbot.CommandServerPort", 8888);
perfMonEnabled = sConfigMgr->GetOption<bool>("AiPlayerbot.PerfMonEnabled", false);
LOG_INFO("server.loading", "---------------------------------------");
LOG_INFO("server.loading", " Loading TalentSpecs ");
LOG_INFO("server.loading", "---------------------------------------");
useGroundMountAtMinLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.UseGroundMountAtMinLevel", 20);
useFastGroundMountAtMinLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.UseFastGroundMountAtMinLevel", 40);
useFlyMountAtMinLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.UseFlyMountAtMinLevel", 60);
useFastFlyMountAtMinLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.UseFastFlyMountAtMinLevel", 70);
LOG_INFO("server.loading", "Loading TalentSpecs...");
for (uint32 cls = 1; cls < MAX_CLASSES; ++cls)
{
@@ -399,22 +416,27 @@ bool PlayerbotAIConfig::Initialize()
worldBuffs.clear();
LOG_INFO("playerbots", "Loading Worldbuff...");
for (uint32 factionId = 0; factionId < 3; factionId++)
{
for (uint32 classId = 0; classId < MAX_CLASSES; classId++)
{
for (uint32 minLevel = 0; minLevel < MAX_LEVEL; minLevel++)
for (uint32 specId = 0; specId <= MAX_WORLDBUFF_SPECNO; specId++)
{
for (uint32 maxLevel = 0; maxLevel < MAX_LEVEL; maxLevel++)
for (uint32 minLevel = 0; minLevel <= randomBotMaxLevel; minLevel++)
{
loadWorldBuf(factionId, classId, minLevel, maxLevel);
for (uint32 maxLevel = minLevel; maxLevel <= randomBotMaxLevel; maxLevel++)
{
loadWorldBuff(factionId, classId, specId, minLevel, maxLevel);
}
loadWorldBuff(factionId, classId, specId, minLevel, 0);
}
}
}
}
randomBotAccountPrefix = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotAccountPrefix", "rndbot");
randomBotAccountCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAccountCount", 200);
randomBotAccountCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAccountCount", 0);
deleteRandomBotAccounts = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotAccounts", false);
randomBotGuildCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotGuildCount", 20);
deleteRandomBotGuilds = sConfigMgr->GetOption<bool>("AiPlayerbot.DeleteRandomBotGuilds", false);
@@ -423,8 +445,7 @@ bool PlayerbotAIConfig::Initialize()
minGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600);
maxGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600);
minGuildTaskAdvertisementTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskAdvertisementTime", 300);
maxGuildTaskAdvertisementTime =
sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600);
maxGuildTaskAdvertisementTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600);
minGuildTaskRewardTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskRewardTime", 300);
maxGuildTaskRewardTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskRewardTime", 3600);
guildTaskAdvertCleanupTime = sConfigMgr->GetOption<int32>("AiPlayerbot.GuildTaskAdvertCleanupTime", 300);
@@ -454,22 +475,30 @@ bool PlayerbotAIConfig::Initialize()
autoInitEquipLevelLimitRatio = sConfigMgr->GetOption<float>("AiPlayerbot.AutoInitEquipLevelLimitRatio", 1.0);
maxAddedBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxAddedBots", 40);
maxAddedBotsPerClass = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxAddedBotsPerClass", 10);
addClassCommand = sConfigMgr->GetOption<int32>("AiPlayerbot.AddClassCommand", 1);
addClassAccountPoolSize = sConfigMgr->GetOption<int32>("AiPlayerbot.AddClassAccountPoolSize", 50);
maintenanceCommand = sConfigMgr->GetOption<int32>("AiPlayerbot.MaintenanceCommand", 1);
autoGearCommand = sConfigMgr->GetOption<int32>("AiPlayerbot.AutoGearCommand", 1);
autoGearCommandAltBots = sConfigMgr->GetOption<int32>("AiPlayerbot.AutoGearCommandAltBots", 1);
autoGearQualityLimit = sConfigMgr->GetOption<int32>("AiPlayerbot.AutoGearQualityLimit", 3);
autoGearScoreLimit = sConfigMgr->GetOption<int32>("AiPlayerbot.AutoGearScoreLimit", 0);
playerbotsXPrate = sConfigMgr->GetOption<int32>("AiPlayerbot.KillXPRate", 1);
playerbotsXPrate = sConfigMgr->GetOption<float>("AiPlayerbot.PlayerbotsXPRate", 1.0);
randomBotAllianceRatio = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAllianceRatio", 50);
randomBotHordeRatio = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotHordeRatio", 50);
disableDeathKnightLogin = sConfigMgr->GetOption<bool>("AiPlayerbot.DisableDeathKnightLogin", 0);
limitTalentsExpansion = sConfigMgr->GetOption<bool>("AiPlayerbot.LimitTalentsExpansion", 0);
botActiveAlone = sConfigMgr->GetOption<int32>("AiPlayerbot.BotActiveAlone", 100);
BotActiveAloneForceWhenInRadius = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotActiveAloneForceWhenInRadius", 150);
BotActiveAloneForceWhenInZone = sConfigMgr->GetOption<bool>("AiPlayerbot.BotActiveAloneForceWhenInZone", 1);
BotActiveAloneForceWhenInMap = sConfigMgr->GetOption<bool>("AiPlayerbot.BotActiveAloneForceWhenInMap", 0);
BotActiveAloneForceWhenIsFriend = sConfigMgr->GetOption<bool>("AiPlayerbot.BotActiveAloneForceWhenIsFriend", 1);
BotActiveAloneForceWhenInGuild = sConfigMgr->GetOption<bool>("AiPlayerbot.BotActiveAloneForceWhenInGuild", 1);
botActiveAloneSmartScale = sConfigMgr->GetOption<bool>("AiPlayerbot.botActiveAloneSmartScale", 1);
botActiveAloneSmartScaleWhenMinLevel =
sConfigMgr->GetOption<uint32>("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1);
botActiveAloneSmartScaleWhenMaxLevel =
sConfigMgr->GetOption<uint32>("AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel", 80);
botActiveAloneSmartScaleDiffLimitfloor = sConfigMgr->GetOption<uint32>("AiPlayerbot.botActiveAloneSmartScaleDiffLimitfloor", 50);
botActiveAloneSmartScaleDiffLimitCeiling = sConfigMgr->GetOption<uint32>("AiPlayerbot.botActiveAloneSmartScaleDiffLimitCeiling", 200);
botActiveAloneSmartScaleWhenMinLevel = sConfigMgr->GetOption<uint32>("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1);
botActiveAloneSmartScaleWhenMaxLevel = sConfigMgr->GetOption<uint32>("AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel", 80);
randombotsWalkingRPG = sConfigMgr->GetOption<bool>("AiPlayerbot.RandombotsWalkingRPG", false);
randombotsWalkingRPGInDoors = sConfigMgr->GetOption<bool>("AiPlayerbot.RandombotsWalkingRPG.InDoors", false);
@@ -477,8 +506,9 @@ bool PlayerbotAIConfig::Initialize()
limitEnchantExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitEnchantExpansion", 1);
limitGearExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitGearExpansion", 1);
randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5);
enableRotation = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableRotation", false);
rotationPoolSize = sConfigMgr->GetOption<int32>("AiPlayerbot.RotationPoolSize", 500);
enablePeriodicOnlineOffline = sConfigMgr->GetOption<bool>("AiPlayerbot.EnablePeriodicOnlineOffline", false);
enableRandomBotTrading = sConfigMgr->GetOption<int32>("AiPlayerbot.EnableRandomBotTrading", 1);
periodicOnlineOfflineRatio = sConfigMgr->GetOption<float>("AiPlayerbot.PeriodicOnlineOfflineRatio", 2.0);
gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false);
randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true);
@@ -491,13 +521,16 @@ bool PlayerbotAIConfig::Initialize()
twoRoundsGearInit = sConfigMgr->GetOption<bool>("AiPlayerbot.TwoRoundsGearInit", false);
syncQuestWithPlayer = sConfigMgr->GetOption<bool>("AiPlayerbot.SyncQuestWithPlayer", true);
syncQuestForPlayer = sConfigMgr->GetOption<bool>("AiPlayerbot.SyncQuestForPlayer", false);
dropObsoleteQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.DropObsoleteQuests", true);
autoTrainSpells = sConfigMgr->GetOption<std::string>("AiPlayerbot.AutoTrainSpells", "yes");
autoPickTalents = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoPickTalents", true);
autoUpgradeEquip = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoUpgradeEquip", false);
hunterWolfPet = sConfigMgr->GetOption<int32>("AiPlayerbot.HunterWolfPet", 0);
autoLearnTrainerSpells = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoLearnTrainerSpells", true);
autoLearnQuestSpells = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoLearnQuestSpells", false);
autoTeleportForLevel = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoTeleportForLevel", false);
autoDoQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoDoQuests", false);
autoDoQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoDoQuests", true);
enableNewRpgStrategy = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableNewRpgStrategy", false);
syncLevelWithPlayers = sConfigMgr->GetOption<bool>("AiPlayerbot.SyncLevelWithPlayers", false);
freeFood = sConfigMgr->GetOption<bool>("AiPlayerbot.FreeFood", true);
randomBotGroupNearby = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGroupNearby", true);
@@ -517,8 +550,11 @@ bool PlayerbotAIConfig::Initialize()
{
return true;
}
if (sPlayerbotAIConfig->addClassCommand)
sRandomPlayerbotMgr->PrepareAddclassCache();
if (sPlayerbotAIConfig->enabled)
{
sRandomPlayerbotMgr->Init();
}
sRandomItemMgr->Init();
sRandomItemMgr->InitAfterAhBot();
@@ -532,8 +568,6 @@ bool PlayerbotAIConfig::Initialize()
sTravelMgr->LoadQuestTravelTable();
}
if (sPlayerbotAIConfig->randomBotJoinBG)
sRandomPlayerbotMgr->LoadBattleMastersCache();
if (sPlayerbotAIConfig->randomBotSuggestDungeons)
{
@@ -559,7 +593,7 @@ bool PlayerbotAIConfig::IsInRandomQuestItemList(uint32 id)
bool PlayerbotAIConfig::IsPvpProhibited(uint32 zoneId, uint32 areaId)
{
return IsInPvpProhibitedZone(zoneId) || IsInPvpProhibitedArea(areaId);
return IsInPvpProhibitedZone(zoneId) || IsInPvpProhibitedArea(areaId) || IsInPvpProhibitedZone(areaId);
}
bool PlayerbotAIConfig::IsInPvpProhibitedZone(uint32 id)
@@ -644,36 +678,50 @@ void PlayerbotAIConfig::log(std::string const fileName, char const* str, ...)
fflush(stdout);
}
void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32 minLevel1, uint32 maxLevel1)
void PlayerbotAIConfig::loadWorldBuff(uint32 factionId1, uint32 classId1, uint32 specId1, uint32 minLevel1, uint32 maxLevel1)
{
std::vector<uint32> buffs;
std::ostringstream os;
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << classId1 << "." << minLevel1 << "." << maxLevel1;
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << classId1 << "." << specId1 << "." << minLevel1 << "." << maxLevel1;
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>(os.str().c_str(), "", false), buffs);
for (auto buff : buffs)
{
worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuff wb = {buff, factionId1, classId1, specId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb);
}
if (maxLevel1 == 0)
{
std::ostringstream os;
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << classId1 << "." << minLevel1;
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << classId1 << "." << specId1 << "." << minLevel1;
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>(os.str().c_str(), "", false), buffs);
for (auto buff : buffs)
{
worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuff wb = {buff, factionId1, classId1, specId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb);
}
}
if (maxLevel1 == 0 && minLevel1 == 0)
{
std::ostringstream os;
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << factionId1 << "." << classId1 << "." << specId1;
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>(os.str().c_str(), "", false), buffs);
for (auto buff : buffs)
{
worldBuff wb = {buff, factionId1, classId1, specId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb);
}
}
if (maxLevel1 == 0 && minLevel1 == 0 && specId1 == 0)
{
std::ostringstream os;
os << "AiPlayerbot.WorldBuff." << factionId1 << "." << factionId1 << "." << classId1;
@@ -682,12 +730,12 @@ void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32
for (auto buff : buffs)
{
worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuff wb = {buff, factionId1, classId1, specId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb);
}
}
if (classId1 == 0 && maxLevel1 == 0 && minLevel1 == 0)
if (classId1 == 0 && maxLevel1 == 0 && minLevel1 == 0 && specId1 == 0)
{
std::ostringstream os;
os << "AiPlayerbot.WorldBuff." << factionId1;
@@ -696,12 +744,12 @@ void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32
for (auto buff : buffs)
{
worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuff wb = {buff, factionId1, classId1, specId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb);
}
}
if (factionId1 == 0 && classId1 == 0 && maxLevel1 == 0 && minLevel1 == 0)
if (factionId1 == 0 && classId1 == 0 && maxLevel1 == 0 && minLevel1 == 0 && specId1 == 0)
{
std::ostringstream os;
os << "AiPlayerbot.WorldBuff";
@@ -710,7 +758,7 @@ void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32
for (auto buff : buffs)
{
worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuff wb = {buff, factionId1, classId1, specId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb);
}
}

View File

@@ -35,6 +35,7 @@ enum class HealingManaEfficiency : uint8
};
#define MAX_SPECNO 20
#define MAX_WORLDBUFF_SPECNO 3
class PlayerbotAIConfig
{
@@ -54,7 +55,7 @@ public:
bool IsInPvpProhibitedArea(uint32 id);
bool enabled;
bool allowGuildBots, allowPlayerBots;
bool allowAccountBots, allowGuildBots, allowTrustedAccountBots;
bool randomBotGuildNearby, randomBotInvitePlayer, inviteChat;
uint32 globalCoolDown, reactDelay, maxWaitForMove, disableMoveSplinePath, maxMovementSearchTime, expireActionTime,
dispelAuraDuration, passiveDelay, repeatDelay, errorDelay, rpgDelay, sitDelay, returnDelay, lootDelay;
@@ -85,7 +86,7 @@ public:
float randomGearLoweringChance;
int32 randomGearQualityLimit;
int32 randomGearScoreLimit;
float randomBotMaxLevelChance;
float randomBotMinLevelChance, randomBotMaxLevelChance;
float randomBotRpgChance;
uint32 minRandomBots, maxRandomBots;
uint32 randomBotUpdateInterval, randomBotCountChangeMinInterval, randomBotCountChangeMaxInterval;
@@ -94,7 +95,7 @@ public:
uint32 minRandomBotChangeStrategyTime, maxRandomBotChangeStrategyTime;
uint32 minRandomBotReviveTime, maxRandomBotReviveTime;
uint32 minRandomBotTeleportInterval, maxRandomBotTeleportInterval;
uint32 randomBotInWorldWithRotationDisabled;
uint32 permanantlyInWorldTime;
uint32 minRandomBotPvpTime, maxRandomBotPvpTime;
uint32 randomBotsPerInterval;
uint32 minRandomBotsPriceChangeInterval, maxRandomBotsPriceChangeInterval;
@@ -173,12 +174,25 @@ public:
bool randomBotJoinBG;
bool randomBotAutoJoinBG;
uint32 randomBotAutoJoinWarsongBracket;
std::string randomBotAutoJoinICBrackets;
std::string randomBotAutoJoinEYBrackets;
std::string randomBotAutoJoinAVBrackets;
std::string randomBotAutoJoinABBrackets;
std::string randomBotAutoJoinWSBrackets;
uint32 randomBotAutoJoinBGICCount;
uint32 randomBotAutoJoinBGEYCount;
uint32 randomBotAutoJoinBGAVCount;
uint32 randomBotAutoJoinBGABCount;
uint32 randomBotAutoJoinBGWSCount;
uint32 randomBotAutoJoinArenaBracket;
uint32 randomBotAutoJoinBGWarsongCount;
uint32 randomBotAutoJoinBGRatedArena2v2Count;
uint32 randomBotAutoJoinBGRatedArena3v3Count;
uint32 randomBotAutoJoinBGRatedArena5v5Count;
bool randomBotLoginAtStartup;
uint32 randomBotTeleLowerLevel, randomBotTeleHigherLevel;
bool logInGroupOnly, logValuesPerTick;
@@ -221,8 +235,8 @@ public:
uint32 limitEnchantExpansion;
uint32 limitGearExpansion;
uint32 randombotStartingLevel;
bool enableRotation;
uint32 rotationPoolSize;
bool enablePeriodicOnlineOffline;
float periodicOnlineOfflineRatio;
bool gearscorecheck;
bool randomBotPreQuests;
@@ -247,6 +261,7 @@ public:
uint32 spellId;
uint32 factionId = 0;
uint32 classId = 0;
uint32 specId = 0;
uint32 minLevel = 0;
uint32 maxLevel = 0;
};
@@ -260,10 +275,20 @@ public:
bool randomBotShowCloak;
bool randomBotFixedLevel;
bool disableRandomLevels;
uint32 playerbotsXPrate;
float playerbotsXPrate;
uint32 randomBotAllianceRatio;
uint32 randomBotHordeRatio;
bool disableDeathKnightLogin;
bool limitTalentsExpansion;
uint32 botActiveAlone;
uint32 BotActiveAloneForceWhenInRadius;
bool BotActiveAloneForceWhenInZone;
bool BotActiveAloneForceWhenInMap;
bool BotActiveAloneForceWhenIsFriend;
bool BotActiveAloneForceWhenInGuild;
bool botActiveAloneSmartScale;
uint32 botActiveAloneSmartScaleDiffLimitfloor;
uint32 botActiveAloneSmartScaleDiffLimitCeiling;
uint32 botActiveAloneSmartScaleWhenMinLevel;
uint32 botActiveAloneSmartScaleWhenMaxLevel;
@@ -275,16 +300,20 @@ public:
bool twoRoundsGearInit;
bool syncQuestWithPlayer;
bool syncQuestForPlayer;
bool dropObsoleteQuests;
std::string autoTrainSpells;
bool autoPickTalents;
bool autoUpgradeEquip;
int32 hunterWolfPet;
bool autoLearnTrainerSpells;
bool autoDoQuests;
bool enableNewRpgStrategy;
bool syncLevelWithPlayers;
bool freeFood;
bool autoLearnQuestSpells;
bool autoTeleportForLevel;
bool randomBotGroupNearby;
int32 enableRandomBotTrading;
uint32 tweakValue; // Debugging config
uint32 randomBotArenaTeamCount;
@@ -308,11 +337,16 @@ public:
bool botRepairWhenSummon;
bool autoInitOnly;
float autoInitEquipLevelLimitRatio;
int32 maxAddedBots, maxAddedBotsPerClass;
int32 maxAddedBots;
int32 addClassCommand;
int32 addClassAccountPoolSize;
int32 maintenanceCommand;
int32 autoGearCommand, autoGearQualityLimit, autoGearScoreLimit;
int32 autoGearCommand, autoGearCommandAltBots, autoGearQualityLimit, autoGearScoreLimit;
uint32 useGroundMountAtMinLevel;
uint32 useFastGroundMountAtMinLevel;
uint32 useFlyMountAtMinLevel;
uint32 useFastFlyMountAtMinLevel;
std::string const GetTimestampStr();
bool hasLog(std::string const fileName)
@@ -327,7 +361,7 @@ public:
}
void log(std::string const fileName, const char* str, ...);
void loadWorldBuf(uint32 factionId, uint32 classId, uint32 minLevel, uint32 maxLevel);
void loadWorldBuff(uint32 factionId, uint32 classId, uint32 specId, uint32 minLevel, uint32 maxLevel);
static std::vector<std::vector<uint32>> ParseTempTalentsOrder(uint32 cls, std::string temp_talents_order);
static std::vector<std::vector<uint32>> ParseTempPetTalentsOrder(uint32 spec, std::string temp_talents_order);
};

View File

@@ -17,11 +17,6 @@ void PlayerbotDbStore::Load(PlayerbotAI* botAI)
stmt->SetData(0, guid);
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
{
botAI->ClearStrategies(BOT_STATE_COMBAT);
botAI->ClearStrategies(BOT_STATE_NON_COMBAT);
botAI->ChangeStrategy("+chat", BOT_STATE_COMBAT);
botAI->ChangeStrategy("+chat", BOT_STATE_NON_COMBAT);
std::vector<std::string> values;
do
{
@@ -32,9 +27,17 @@ void PlayerbotDbStore::Load(PlayerbotAI* botAI)
if (key == "value")
values.push_back(value);
else if (key == "co")
{
botAI->ClearStrategies(BOT_STATE_COMBAT);
botAI->ChangeStrategy("+chat", BOT_STATE_COMBAT);
botAI->ChangeStrategy(value, BOT_STATE_COMBAT);
}
else if (key == "nc")
{
botAI->ClearStrategies(BOT_STATE_NON_COMBAT);
botAI->ChangeStrategy("+chat", BOT_STATE_NON_COMBAT);
botAI->ChangeStrategy(value, BOT_STATE_NON_COMBAT);
}
else if (key == "dead")
botAI->ChangeStrategy(value, BOT_STATE_DEAD);
} while (result->NextRow());
@@ -49,6 +52,11 @@ void PlayerbotDbStore::Save(PlayerbotAI* botAI)
Reset(botAI);
PlayerbotsDatabasePreparedStatement* deleteStatement =
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_DB_STORE);
deleteStatement->SetData(0, guid);
PlayerbotsDatabase.Execute(deleteStatement);
std::vector<std::string> data = botAI->GetAiObjectContext()->Save();
for (std::vector<std::string>::iterator i = data.begin(); i != data.end(); ++i)
{

View File

@@ -9,6 +9,9 @@
#include <cstring>
#include <istream>
#include <string>
#include <openssl/sha.h>
#include <unordered_set>
#include <iomanip>
#include "ChannelMgr.h"
#include "CharacterCache.h"
@@ -17,6 +20,7 @@
#include "Define.h"
#include "Group.h"
#include "GroupMgr.h"
#include "GuildMgr.h"
#include "ObjectAccessor.h"
#include "ObjectGuid.h"
#include "ObjectMgr.h"
@@ -30,6 +34,36 @@
#include "WorldSession.h"
#include "ChannelMgr.h"
#include "BroadcastHelper.h"
#include "PlayerbotDbStore.h"
#include "WorldSessionMgr.h"
class BotInitGuard
{
public:
BotInitGuard(ObjectGuid guid) : guid(guid), active(false)
{
if (!botsBeingInitialized.contains(guid))
{
botsBeingInitialized.insert(guid);
active = true;
}
}
~BotInitGuard()
{
if (active)
botsBeingInitialized.erase(guid);
}
bool IsLocked() const { return !active; }
private:
ObjectGuid guid;
bool active;
static std::unordered_set<ObjectGuid> botsBeingInitialized;
};
std::unordered_set<ObjectGuid> BotInitGuard::botsBeingInitialized;
PlayerbotHolder::PlayerbotHolder() : PlayerbotAIBase(false) {}
class PlayerbotLoginQueryHolder : public LoginQueryHolder
@@ -37,7 +71,6 @@ class PlayerbotLoginQueryHolder : public LoginQueryHolder
private:
uint32 masterAccountId;
PlayerbotHolder* playerbotHolder;
public:
PlayerbotLoginQueryHolder(PlayerbotHolder* playerbotHolder, uint32 masterAccount, uint32 accountId, ObjectGuid guid)
: LoginQueryHolder(accountId, guid), masterAccountId(masterAccount), playerbotHolder(playerbotHolder)
@@ -63,6 +96,49 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId
if (!accountId)
return;
WorldSession* masterSession = masterAccountId ? sWorldSessionMgr->FindSession(masterAccountId) : nullptr;
Player* masterPlayer = masterSession ? masterSession->GetPlayer() : nullptr;
bool isRndbot = !masterAccountId;
bool sameAccount = sPlayerbotAIConfig->allowAccountBots && accountId == masterAccountId;
Guild* guild = masterPlayer ? sGuildMgr->GetGuildById(masterPlayer->GetGuildId()) : nullptr;
bool sameGuild = sPlayerbotAIConfig->allowGuildBots && guild && guild->GetMember(playerGuid);
bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(playerGuid.GetCounter());
bool linkedAccount = sPlayerbotAIConfig->allowTrustedAccountBots && IsAccountLinked(accountId, masterAccountId);
bool allowed = true;
std::ostringstream out;
std::string botName;
sCharacterCache->GetCharacterNameByGuid(playerGuid, botName);
if (!isRndbot && !sameAccount && !sameGuild && !addClassBot && !linkedAccount)
{
allowed = false;
out << "Failure: You are not allowed to control bot " << botName.c_str();
}
if (masterAccountId && masterPlayer)
{
PlayerbotMgr* mgr = GET_PLAYERBOT_MGR(masterPlayer);
if (!mgr)
{
LOG_DEBUG("playerbots", "PlayerbotMgr not found for master player with GUID: {}", masterPlayer->GetGUID().GetRawValue());
return;
}
uint32 count = mgr->GetPlayerbotsCount() + botLoading.size();
if (count >= sPlayerbotAIConfig->maxAddedBots)
{
allowed = false;
out << "Failure: You have added too many bots (more than " << sPlayerbotAIConfig->maxAddedBots << ")";
}
}
if (!allowed)
{
if (masterSession)
{
ChatHandler ch(masterSession);
ch.SendSysMessage(out.str());
}
return;
}
std::shared_ptr<PlayerbotLoginQueryHolder> holder =
std::make_shared<PlayerbotLoginQueryHolder>(this, masterAccountId, accountId, playerGuid);
if (!holder->Initialize())
@@ -71,25 +147,23 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId
}
botLoading.insert(playerGuid);
if (WorldSession* masterSession = sWorld->FindSession(masterAccountId))
{
masterSession->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder))
.AfterComplete([this](SQLQueryHolderBase const& holder)
{ HandlePlayerBotLoginCallback(static_cast<PlayerbotLoginQueryHolder const&>(holder)); });
}
else
{
sWorld->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder))
.AfterComplete([this](SQLQueryHolderBase const& holder)
{ HandlePlayerBotLoginCallback(static_cast<PlayerbotLoginQueryHolder const&>(holder)); });
}
// Always login in with world session to avoid race condition
sWorld->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder))
.AfterComplete([this](SQLQueryHolderBase const& holder)
{ HandlePlayerBotLoginCallback(static_cast<PlayerbotLoginQueryHolder const&>(holder)); });
}
bool PlayerbotHolder::IsAccountLinked(uint32 accountId, uint32 linkedAccountId)
{
QueryResult result = PlayerbotsDatabase.Query(
"SELECT 1 FROM playerbot_account_links WHERE account_id = {} AND linked_account_id = {}", accountId, linkedAccountId);
return result != nullptr;
}
void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder)
{
uint32 botAccountId = holder.GetAccountId();
// At login DBC locale should be what the server is set to use by default (as spells etc are hardcoded to ENUS this
// allows channels to work as intended)
WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING,
@@ -109,7 +183,7 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con
}
uint32 masterAccount = holder.GetMasterAccountId();
WorldSession* masterSession = masterAccount ? sWorld->FindSession(masterAccount) : nullptr;
WorldSession* masterSession = masterAccount ? sWorldSessionMgr->FindSession(masterAccount) : nullptr;
// Check if masterSession->GetPlayer() is valid
Player* masterPlayer = masterSession ? masterSession->GetPlayer() : nullptr;
@@ -118,64 +192,9 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con
LOG_DEBUG("mod-playerbots", "Master session found but no player is associated for master account ID: {}", masterAccount);
}
std::ostringstream out;
bool allowed = false;
if (botAccountId == masterAccount)
{
allowed = true;
}
else if (masterSession && sPlayerbotAIConfig->allowGuildBots && bot->GetGuildId() != 0 &&
bot->GetGuildId() == masterPlayer->GetGuildId())
{
allowed = true;
}
else if (sPlayerbotAIConfig->IsInRandomAccountList(botAccountId))
{
allowed = true;
}
else
{
allowed = false;
out << "Failure: You are not allowed to control bot " << bot->GetName().c_str();
}
sRandomPlayerbotMgr->OnPlayerLogin(bot);
OnBotLogin(bot);
if (allowed && masterSession && masterPlayer)
{
PlayerbotMgr* mgr = GET_PLAYERBOT_MGR(masterPlayer);
if (!mgr)
{
LOG_DEBUG("mod-playerbots", "PlayerbotMgr not found for master player with GUID: {}", masterPlayer->GetGUID().GetRawValue());
}
uint32 count = mgr->GetPlayerbotsCount();
uint32 cls_count = mgr->GetPlayerbotsCountByClass(bot->getClass());
if (count >= sPlayerbotAIConfig->maxAddedBots)
{
allowed = false;
out << "Failure: You have added too many bots";
}
else if (cls_count >= sPlayerbotAIConfig->maxAddedBotsPerClass)
{
allowed = false;
out << "Failure: You have added too many bots for this class";
}
}
if (allowed)
{
sRandomPlayerbotMgr->OnPlayerLogin(bot);
OnBotLogin(bot);
}
else
{
if (masterSession)
{
ChatHandler ch(masterSession);
ch.SendSysMessage(out.str());
}
botSession->LogoutPlayer(true);
delete botSession;
}
botLoading.erase(holder.GetGuid());
}
@@ -295,7 +314,7 @@ void PlayerbotHolder::LogoutPlayerBot(ObjectGuid guid)
sPlayerbotDbStore->Save(botAI);
}
LOG_INFO("playerbots", "Bot {} logging out", bot->GetName().c_str());
LOG_DEBUG("playerbots", "Bot {} logging out", bot->GetName().c_str());
bot->SaveToDB(false, false);
WorldSession* botWorldSessionPtr = bot->GetSession();
@@ -352,7 +371,7 @@ void PlayerbotHolder::LogoutPlayerBot(ObjectGuid guid)
botWorldSessionPtr->HandleLogoutRequestOpcode(data);
if (!bot)
{
playerBots.erase(guid);
RemoveFromPlayerbotsMap(guid);
delete botWorldSessionPtr;
if (target)
delete target;
@@ -361,7 +380,7 @@ void PlayerbotHolder::LogoutPlayerBot(ObjectGuid guid)
}
else
{
playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
RemoveFromPlayerbotsMap(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
delete botWorldSessionPtr; // finally delete the bot's WorldSession
if (target)
delete target;
@@ -371,7 +390,7 @@ void PlayerbotHolder::LogoutPlayerBot(ObjectGuid guid)
else if (bot && (logout || !botWorldSessionPtr->isLogingOut()))
{
botAI->TellMaster("Goodbye!");
playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
RemoveFromPlayerbotsMap(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
botWorldSessionPtr->LogoutPlayer(true); // this will delete the bot Player object and PlayerbotAI object
delete botWorldSessionPtr; // finally delete the bot's WorldSession
}
@@ -408,12 +427,17 @@ void PlayerbotHolder::DisablePlayerBot(ObjectGuid guid)
delete target;
}
playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
RemoveFromPlayerbotsMap(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
delete botAI;
}
}
void PlayerbotHolder::RemoveFromPlayerbotsMap(ObjectGuid guid)
{
playerBots.erase(guid);
}
Player* PlayerbotHolder::GetPlayerBot(ObjectGuid playerGuid) const
{
PlayerBotMap::const_iterator it = playerBots.find(playerGuid);
@@ -437,6 +461,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
sPlayerbotsMgr->AddPlayerbotData(bot, true);
playerBots[bot->GetGUID()] = bot;
OnBotLoginInternal(bot);
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
@@ -484,10 +509,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
if (!groupValid)
{
WorldPacket p;
std::string const member = bot->GetName();
p << uint32(PARTY_OP_LEAVE) << member << uint32(0);
bot->GetSession()->HandleGroupDisbandOpcode(p);
bot->RemoveFromGroup();
}
}
@@ -498,9 +520,9 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
}
else
{
// botAI->ResetStrategies(!sRandomPlayerbotMgr->IsRandomBot(bot));
botAI->ResetStrategies();
botAI->ResetStrategies(!sRandomPlayerbotMgr->IsRandomBot(bot));
}
sPlayerbotDbStore->Load(botAI);
if (master && !master->HasUnitState(UNIT_STATE_IN_FLIGHT))
{
@@ -559,12 +581,16 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
}
bot->SaveToDB(false, false);
if (master && isRandomAccount && master->GetLevel() < bot->GetLevel())
bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(bot->GetGUID().GetCounter());
if (addClassBot && master && isRandomAccount && abs((int)master->GetLevel() - (int)bot->GetLevel()) > 3)
{
// PlayerbotFactory factory(bot, master->GetLevel());
// factory.Randomize(false);
uint32 mixedGearScore =
PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
// work around: distinguish from 0 if no gear
if (mixedGearScore == 0)
mixedGearScore = 1;
PlayerbotFactory factory(bot, master->GetLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore);
factory.Randomize(false);
}
@@ -642,25 +668,28 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
return "bot system is disabled";
uint32 botAccount = sCharacterCache->GetCharacterAccountIdByGuid(guid);
bool isRandomBot = sRandomPlayerbotMgr->IsRandomBot(guid.GetCounter());
bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(botAccount);
bool isMasterAccount = (masterAccountId == botAccount);
//bool isRandomBot = sRandomPlayerbotMgr->IsRandomBot(guid.GetCounter()); //not used, line marked for removal.
//bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(botAccount); //not used, shadowed, line marked for removal.
//bool isMasterAccount = (masterAccountId == botAccount); //not used, line marked for removal.
if (!isRandomAccount && !isMasterAccount && !admin && masterguid)
{
Player* master = ObjectAccessor::FindConnectedPlayer(masterguid);
if (master && (!sPlayerbotAIConfig->allowGuildBots || !masterGuildId ||
(masterGuildId && sCharacterCache->GetCharacterGuildIdByGuid(guid) != masterGuildId)))
return "not in your guild or account";
}
if (cmd == "add" || cmd == "login")
if (cmd == "add" || cmd == "addaccount" || cmd == "login")
{
if (ObjectAccessor::FindPlayer(guid))
return "player already logged in";
if (!sPlayerbotAIConfig->allowPlayerBots && !isRandomAccount && !isMasterAccount)
return "You cannot login another player's character as bot.";
// For addaccount command, verify it's an account name
if (cmd == "addaccount")
{
uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(guid);
if (!accountId)
return "character not found";
if (!sPlayerbotAIConfig->allowAccountBots && accountId != masterAccountId &&
!(sPlayerbotAIConfig->allowTrustedAccountBots && IsAccountLinked(accountId, masterAccountId)))
{
return "you can only add bots from your own account or linked accounts";
}
}
AddPlayerBot(guid, masterAccountId);
return "ok";
@@ -686,10 +715,10 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
if (!bot)
return "bot not found";
if (!isRandomAccount || isRandomBot)
{
return "ERROR: You can not use this command on non-summoned random bot.";
}
bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(guid.GetCounter());
if (!addClassBot)
return "ERROR: You can not use this command on non-addclass bot.";
if (!admin)
{
@@ -709,6 +738,14 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
{
return "The command is not allowed, use init=auto instead.";
}
// Use boot guard
BotInitGuard guard(bot->GetGUID());
if (guard.IsLocked())
{
return "Initialization already in progress, please wait.";
}
int gs;
if (cmd == "init=white" || cmd == "init=common")
{
@@ -744,6 +781,9 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
{
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) *
sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
// work around: distinguish from 0 if no gear
if (mixedGearScore == 0)
mixedGearScore = 1;
PlayerbotFactory factory(bot, master->GetLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore);
factory.Randomize(false);
return "ok, gear score limit: " + std::to_string(mixedGearScore / PlayerbotAI::GetItemScoreMultiplier(ItemQualities(ITEM_QUALITY_EPIC))) +
@@ -835,7 +875,7 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
if (!*args)
{
messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME\n");
messages.push_back("usage: list/reload/tweak/self or add/addaccount/init/remove PLAYERNAME\n");
messages.push_back("usage: addclass CLASSNAME");
return messages;
}
@@ -958,9 +998,17 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
if (!strcmp(cmd, "reload"))
{
messages.push_back("Reloading config");
sPlayerbotAIConfig->Initialize();
return messages;
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER)
{
sPlayerbotAIConfig->Initialize();
messages.push_back("Config reloaded.");
return messages;
}
else
{
messages.push_back("ERROR: Only GM can use this command.");
return messages;
}
}
if (!strcmp(cmd, "tweak"))
@@ -1059,15 +1107,22 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
messages.push_back("Error: Invalid Class. Try again.");
return messages;
}
uint8 teamId = master->GetTeamId(true);
std::vector<ObjectGuid> &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)];
for (size_t i = 0; i < guidCache.size(); i++)
if (claz == 6 && master->GetLevel() < sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL))
{
messages.push_back("Your level is too low to summon Deathknight");
return messages;
}
uint8 teamId = master->GetTeamId(true);
const std::unordered_set<ObjectGuid> &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)];
for (const ObjectGuid &guid: guidCache)
{
ObjectGuid guid = guidCache[i];
if (botLoading.find(guid) != botLoading.end())
continue;
if (ObjectAccessor::FindConnectedPlayer(guid))
continue;
uint32 guildId = sCharacterCache->GetCharacterGuildIdByGuid(guid);
if (guildId && PlayerbotAI::IsRealGuild(guildId))
continue;
AddPlayerBot(guid, master->GetSession()->GetAccountId());
messages.push_back("Add class " + std::string(charname));
return messages;
@@ -1139,22 +1194,48 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
{
std::string const s = *i;
uint32 accountId = GetAccountId(s);
if (!accountId)
if (!strcmp(cmd, "addaccount"))
{
bots.insert(s);
continue;
}
QueryResult results = CharacterDatabase.Query("SELECT name FROM characters WHERE account = {}", accountId);
if (results)
{
do
// When using addaccount, first try to get account ID directly
uint32 accountId = GetAccountId(s);
if (!accountId)
{
Field* fields = results->Fetch();
std::string const charName = fields[0].Get<std::string>();
bots.insert(charName);
} while (results->NextRow());
// If not found, try to get account ID from character name
ObjectGuid charGuid = sCharacterCache->GetCharacterGuidByName(s);
if (!charGuid)
{
messages.push_back("Neither account nor character '" + s + "' found");
continue;
}
accountId = sCharacterCache->GetCharacterAccountIdByGuid(charGuid);
if (!accountId)
{
messages.push_back("Could not find account for character '" + s + "'");
continue;
}
}
QueryResult results = CharacterDatabase.Query("SELECT name FROM characters WHERE account = {}", accountId);
if (results)
{
do
{
Field* fields = results->Fetch();
std::string const charName = fields[0].Get<std::string>();
bots.insert(charName);
} while (results->NextRow());
}
}
else
{
// For regular add command, only add the specific character
ObjectGuid charGuid = sCharacterCache->GetCharacterGuidByName(s);
if (!charGuid)
{
messages.push_back("Character '" + s + "' not found");
continue;
}
bots.insert(s);
}
}
@@ -1637,3 +1718,121 @@ PlayerbotMgr* PlayerbotsMgr::GetPlayerbotMgr(Player* player)
return nullptr;
}
void PlayerbotMgr::HandleSetSecurityKeyCommand(Player* player, const std::string& key)
{
uint32 accountId = player->GetSession()->GetAccountId();
// Hash the security key using SHA-256
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256((unsigned char*)key.c_str(), key.size(), hash);
// Convert the hash to a hexadecimal string
std::ostringstream hashedKey;
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
hashedKey << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
// Store the hashed key in the database
PlayerbotsDatabase.Execute(
"REPLACE INTO playerbot_account_keys (account_id, security_key) VALUES ({}, '{}')",
accountId, hashedKey.str());
ChatHandler(player->GetSession()).PSendSysMessage("Security key set successfully.");
}
void PlayerbotMgr::HandleLinkAccountCommand(Player* player, const std::string& accountName, const std::string& key)
{
QueryResult result = LoginDatabase.Query("SELECT id FROM account WHERE username = '{}'", accountName);
if (!result)
{
ChatHandler(player->GetSession()).PSendSysMessage("Account not found.");
return;
}
Field* fields = result->Fetch();
uint32 linkedAccountId = fields[0].Get<uint32>();
result = PlayerbotsDatabase.Query("SELECT security_key FROM playerbot_account_keys WHERE account_id = {}", linkedAccountId);
if (!result)
{
ChatHandler(player->GetSession()).PSendSysMessage("Invalid security key.");
return;
}
// Hash the provided key
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256((unsigned char*)key.c_str(), key.size(), hash);
// Convert the hash to a hexadecimal string
std::ostringstream hashedKey;
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
hashedKey << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
// Compare the hashed key with the stored hashed key
std::string storedKey = result->Fetch()->Get<std::string>();
if (hashedKey.str() != storedKey)
{
ChatHandler(player->GetSession()).PSendSysMessage("Invalid security key.");
return;
}
uint32 accountId = player->GetSession()->GetAccountId();
PlayerbotsDatabase.Execute(
"INSERT IGNORE INTO playerbot_account_links (account_id, linked_account_id) VALUES ({}, {})",
accountId, linkedAccountId);
PlayerbotsDatabase.Execute(
"INSERT IGNORE INTO playerbot_account_links (account_id, linked_account_id) VALUES ({}, {})",
linkedAccountId, accountId);
ChatHandler(player->GetSession()).PSendSysMessage("Account linked successfully.");
}
void PlayerbotMgr::HandleViewLinkedAccountsCommand(Player* player)
{
uint32 accountId = player->GetSession()->GetAccountId();
QueryResult result = PlayerbotsDatabase.Query("SELECT linked_account_id FROM playerbot_account_links WHERE account_id = {}", accountId);
if (!result)
{
ChatHandler(player->GetSession()).PSendSysMessage("No linked accounts.");
return;
}
ChatHandler(player->GetSession()).PSendSysMessage("Linked accounts:");
do
{
Field* fields = result->Fetch();
uint32 linkedAccountId = fields[0].Get<uint32>();
QueryResult accountResult = LoginDatabase.Query("SELECT username FROM account WHERE id = {}", linkedAccountId);
if (accountResult)
{
Field* accountFields = accountResult->Fetch();
std::string username = accountFields[0].Get<std::string>();
ChatHandler(player->GetSession()).PSendSysMessage("- {}", username.c_str());
}
else
{
ChatHandler(player->GetSession()).PSendSysMessage("- Unknown account");
}
} while (result->NextRow());
}
void PlayerbotMgr::HandleUnlinkAccountCommand(Player* player, const std::string& accountName)
{
QueryResult result = LoginDatabase.Query("SELECT id FROM account WHERE username = '{}'", accountName);
if (!result)
{
ChatHandler(player->GetSession()).PSendSysMessage("Account not found.");
return;
}
Field* fields = result->Fetch();
uint32 linkedAccountId = fields[0].Get<uint32>();
uint32 accountId = player->GetSession()->GetAccountId();
PlayerbotsDatabase.Execute("DELETE FROM playerbot_account_links WHERE (account_id = {} AND linked_account_id = {}) OR (account_id = {} AND linked_account_id = {})",
accountId, linkedAccountId, linkedAccountId, accountId);
ChatHandler(player->GetSession()).PSendSysMessage("Account unlinked successfully.");
}

View File

@@ -28,10 +28,12 @@ public:
virtual ~PlayerbotHolder(){};
void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId);
bool IsAccountLinked(uint32 accountId, uint32 masterAccountId);
void HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder);
void LogoutPlayerBot(ObjectGuid guid);
void DisablePlayerBot(ObjectGuid guid);
void RemoveFromPlayerbotsMap(ObjectGuid guid);
Player* GetPlayerBot(ObjectGuid guid) const;
Player* GetPlayerBot(ObjectGuid::LowType lowGuid) const;
PlayerBotMap::const_iterator GetPlayerBotsBegin() const { return playerBots.begin(); }
@@ -81,6 +83,11 @@ public:
void SaveToDB();
void HandleSetSecurityKeyCommand(Player* player, const std::string& key);
void HandleLinkAccountCommand(Player* player, const std::string& accountName, const std::string& key);
void HandleViewLinkedAccountsCommand(Player* player);
void HandleUnlinkAccountCommand(Player* player, const std::string& accountName);
protected:
void OnBotLoginInternal(Player* const bot) override;
void CheckTellErrors(uint32 elapsed);

View File

@@ -86,8 +86,8 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea
}
}
int32 botGS = (int32)botAI->GetEquipGearScore(bot, false, false);
int32 fromGS = (int32)botAI->GetEquipGearScore(from, false, false);
int32 botGS = (int32)botAI->GetEquipGearScore(bot/*, false, false*/);
int32 fromGS = (int32)botAI->GetEquipGearScore(from/*, false, false*/);
if (sPlayerbotAIConfig->gearscorecheck)
{
if (botGS && bot->GetLevel() > 15 && botGS > fromGS &&
@@ -139,7 +139,7 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea
return PLAYERBOT_SECURITY_INVITE;
}
if (group->IsFull())
if (!ignoreGroup && group->IsFull())
{
if (reason)
*reason = PLAYERBOT_DENY_FULL_GROUP;
@@ -147,7 +147,7 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea
return PLAYERBOT_SECURITY_TALK;
}
if (group->GetLeaderGUID() != bot->GetGUID())
if (!ignoreGroup && group->GetLeaderGUID() != bot->GetGUID())
{
if (reason)
*reason = PLAYERBOT_DENY_NOT_LEADER;
@@ -211,8 +211,8 @@ bool PlayerbotSecurity::CheckLevelFor(PlayerbotSecurityLevel level, bool silent,
break;
case PLAYERBOT_DENY_GEARSCORE:
{
int botGS = (int)botAI->GetEquipGearScore(bot, false, false);
int fromGS = (int)botAI->GetEquipGearScore(from, false, false);
int botGS = (int)botAI->GetEquipGearScore(bot/*, false, false*/);
int fromGS = (int)botAI->GetEquipGearScore(from/*, false, false*/);
int diff = (100 * (botGS - fromGS) / botGS);
int req = 12 * sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) / from->GetLevel();
out << "Your gearscore is too low: |cffff0000" << fromGS << "|cffffffff/|cff00ff00" << botGS

View File

@@ -23,6 +23,8 @@
#include "DatabaseLoader.h"
#include "GuildTaskMgr.h"
#include "Metric.h"
#include "PlayerScript.h"
#include "PlayerbotAIConfig.h"
#include "RandomPlayerbotMgr.h"
#include "ScriptMgr.h"
#include "cs_playerbots.h"
@@ -52,7 +54,7 @@ public:
void OnDatabaseSelectIndexLogout(Player* player, uint32& statementIndex, uint32& statementParam) override
{
statementIndex = CHAR_UPD_CHAR_ONLINE;
statementIndex = CHAR_UPD_CHAR_OFFLINE;
statementParam = player->GetGUID().GetCounter();
}
@@ -72,45 +74,53 @@ public:
}
};
class PlayerbotsMetricScript : public MetricScript
{
public:
PlayerbotsMetricScript() : MetricScript("PlayerbotsMetricScript") {}
void OnMetricLogging() override
{
if (sMetric->IsEnabled())
{
sMetric->LogValue("db_queue_playerbots", uint64(PlayerbotsDatabase.QueueSize()), {});
}
}
};
class PlayerbotsPlayerScript : public PlayerScript
{
public:
PlayerbotsPlayerScript() : PlayerScript("PlayerbotsPlayerScript") {}
PlayerbotsPlayerScript() : PlayerScript("PlayerbotsPlayerScript", {
PLAYERHOOK_ON_LOGIN,
PLAYERHOOK_ON_AFTER_UPDATE,
PLAYERHOOK_ON_CHAT,
PLAYERHOOK_ON_CHAT_WITH_CHANNEL,
PLAYERHOOK_ON_CHAT_WITH_GROUP,
PLAYERHOOK_ON_BEFORE_CRITERIA_PROGRESS,
PLAYERHOOK_ON_BEFORE_ACHI_COMPLETE,
PLAYERHOOK_CAN_PLAYER_USE_PRIVATE_CHAT,
PLAYERHOOK_ON_GIVE_EXP
}) {}
void OnLogin(Player* player) override
void OnPlayerLogin(Player* player) override
{
if (!player->GetSession()->IsBot())
{
sPlayerbotsMgr->AddPlayerbotData(player, false);
sRandomPlayerbotMgr->OnPlayerLogin(player);
// Before modifying the following messages, please make sure it does not violate the AGPLv3.0 license
// especially if you are distributing a repack or hosting a public server
// e.g. you can replace the URL with your own repository,
// but it should be publicly accessible and include all modifications you've made
if (sPlayerbotAIConfig->enabled)
{
ChatHandler(player->GetSession()).SendSysMessage(
"|cff00ff00This server runs with |cff00ccffmod-playerbots|r "
"|cffcccccchttps://github.com/liyunfan1223/mod-playerbots|r");
}
if (sPlayerbotAIConfig->enabled || sPlayerbotAIConfig->randomBotAutologin)
{
std::string roundedTime =
std::to_string(std::ceil((sPlayerbotAIConfig->maxRandomBots * 0.13 / 60) * 10) / 10.0);
std::to_string(std::ceil((sPlayerbotAIConfig->maxRandomBots * 0.11 / 60) * 10) / 10.0);
roundedTime = roundedTime.substr(0, roundedTime.find('.') + 2);
ChatHandler(player->GetSession()).SendSysMessage(
"Playerbots: bot initialization at server startup will require '" + roundedTime + "' minutes.");
"|cff00ff00Playerbots:|r bot initialization at server startup takes about '"
+ roundedTime + "' minutes.");
}
}
}
void OnAfterUpdate(Player* player, uint32 diff) override
void OnPlayerAfterUpdate(Player* player, uint32 diff) override
{
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
{
@@ -123,7 +133,7 @@ public:
}
}
bool CanPlayerUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Player* receiver) override
bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Player* receiver) override
{
if (type == CHAT_MSG_WHISPER)
{
@@ -138,7 +148,7 @@ public:
return true;
}
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Group* group) override
void OnPlayerChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Group* group) override
{
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
@@ -152,7 +162,7 @@ public:
}
}
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg) override
void OnPlayerChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg) override
{
if (type == CHAT_MSG_GUILD)
{
@@ -173,7 +183,7 @@ public:
}
}
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override
void OnPlayerChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override
{
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{
@@ -186,7 +196,7 @@ public:
sRandomPlayerbotMgr->HandleCommand(type, msg, player);
}
bool OnBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* /*criteria*/) override
bool OnPlayerBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* /*criteria*/) override
{
if (sRandomPlayerbotMgr->IsRandomBot(player))
{
@@ -195,7 +205,7 @@ public:
return true;
}
bool OnBeforeAchiComplete(Player* player, AchievementEntry const* /*achievement*/) override
bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* /*achievement*/) override
{
if (sRandomPlayerbotMgr->IsRandomBot(player))
{
@@ -203,6 +213,17 @@ public:
}
return true;
}
void OnPlayerGiveXP(Player* player, uint32& amount, Unit* /*victim*/, uint8 /*xpSource*/) override
{
if (!player->GetSession()->IsBot())
return;
if (sPlayerbotAIConfig->playerbotsXPrate != 1.0)
{
amount = static_cast<uint32>(std::round(static_cast<float>(amount) * sPlayerbotAIConfig->playerbotsXPrate));
}
}
};
class PlayerbotsMiscScript : public MiscScript
@@ -227,7 +248,9 @@ public:
class PlayerbotsServerScript : public ServerScript
{
public:
PlayerbotsServerScript() : ServerScript("PlayerbotsServerScript") {}
PlayerbotsServerScript() : ServerScript("PlayerbotsServerScript", {
SERVERHOOK_CAN_PACKET_RECEIVE
}) {}
void OnPacketReceived(WorldSession* session, WorldPacket const& packet) override
{
@@ -240,12 +263,29 @@ public:
class PlayerbotsWorldScript : public WorldScript
{
public:
PlayerbotsWorldScript() : WorldScript("PlayerbotsWorldScript") {}
PlayerbotsWorldScript() : WorldScript("PlayerbotsWorldScript", {
WORLDHOOK_ON_BEFORE_WORLD_INITIALIZED
}) {}
void OnBeforeWorldInitialized() override
{
uint32 oldMSTime = getMSTime();
// Before modifying the following messages, please make sure it does not violate the AGPLv3.0 license
// especially if you are distributing a repack or hosting a public server
// e.g. you can replace the URL with your own repository,
// but it should be publicly accessible and include all modifications you've made
LOG_INFO("server.loading", "╔══════════════════════════════════════════════════════════╗");
LOG_INFO("server.loading", "║ ║");
LOG_INFO("server.loading", "║ AzerothCore Playerbots Module ║");
LOG_INFO("server.loading", "║ ║");
LOG_INFO("server.loading", "╟──────────────────────────────────────────────────────────╢");
LOG_INFO("server.loading", "║ mod-playerbots is a community-driven open-source ║");
LOG_INFO("server.loading", "║ project based on AzerothCore, licensed under AGPLv3.0 ║");
LOG_INFO("server.loading", "╟──────────────────────────────────────────────────────────╢");
LOG_INFO("server.loading", "║ https://github.com/liyunfan1223/mod-playerbots ║");
LOG_INFO("server.loading", "╚══════════════════════════════════════════════════════════╝");
uint32 oldMSTime = getMSTime();
LOG_INFO("server.loading", " ");
LOG_INFO("server.loading", "Load Playerbots Config...");
@@ -339,13 +379,16 @@ public:
sRandomPlayerbotMgr->OnPlayerLogout(player);
}
void OnPlayerbotLogoutBots() override { sRandomPlayerbotMgr->LogoutAllBots(); }
void OnPlayerbotLogoutBots() override
{
LOG_INFO("playerbots", "Logging out all bots...");
sRandomPlayerbotMgr->LogoutAllBots();
}
};
void AddPlayerbotsScripts()
{
new PlayerbotsDatabaseScript();
new PlayerbotsMetricScript();
new PlayerbotsPlayerScript();
new PlayerbotsMiscScript();
new PlayerbotsServerScript();

View File

@@ -1,7 +1,7 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "RandomPlayerbotFactory.h"
@@ -14,11 +14,12 @@
#include "ScriptMgr.h"
#include "SharedDefines.h"
#include "SocialMgr.h"
#include "Timer.h"
std::map<uint8, std::vector<uint8>> RandomPlayerbotFactory::availableRaces;
constexpr RandomPlayerbotFactory::NameRaceAndGender RandomPlayerbotFactory::CombineRaceAndGender(uint8 gender,
uint8 race)
uint8 race)
{
switch (race)
{
@@ -78,6 +79,7 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_ROGUE].push_back(RACE_NIGHTELF);
availableRaces[CLASS_ROGUE].push_back(RACE_GNOME);
availableRaces[CLASS_ROGUE].push_back(RACE_ORC);
availableRaces[CLASS_ROGUE].push_back(RACE_UNDEAD_PLAYER);
availableRaces[CLASS_ROGUE].push_back(RACE_TROLL);
if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{
@@ -223,7 +225,7 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls
}
}
uint8 skinColor = skinColors[urand(0, skinColors.size() - 1)];
//uint8 skinColor = skinColors[urand(0, skinColors.size() - 1)]; //not used, line marked for removal.
std::pair<uint8, uint8> face = faces[urand(0, faces.size() - 1)];
std::pair<uint8, uint8> hair = hairs[urand(0, hairs.size() - 1)];
@@ -242,7 +244,7 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls
delete player;
LOG_ERROR("playerbots", "Unable to create random bot for account {} - name: \"{}\"; race: {}; class: {}",
accountId, name.c_str(), race, cls);
accountId, name.c_str(), race, cls);
return nullptr;
}
@@ -254,7 +256,7 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls
player->learnSpell(50977, false);
}
LOG_DEBUG("playerbots", "Random bot created for account {} - name: \"{}\"; race: {}; class: {}", accountId,
name.c_str(), race, cls);
name.c_str(), race, cls);
return player;
}
@@ -276,13 +278,19 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender
{
break;
}
Field* fields = result->Fetch();
botName = fields[0].Get<std::string>();
if (ObjectMgr::CheckPlayerName(botName) == CHAR_NAME_SUCCESS) // Checks for reservation & profanity, too
{
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->SetData(0, botName);
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
continue;
return botName;
}
}
}
// CONLANG NAME GENERATION
@@ -345,6 +353,14 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender
botName.clear();
continue;
}
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->SetData(0, botName);
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
{
botName.clear();
continue;
}
return std::move(botName);
}
@@ -362,6 +378,14 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender
botName.clear();
continue;
}
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->SetData(0, botName);
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
{
botName.clear();
continue;
}
return std::move(botName);
}
LOG_ERROR("playerbots", "Random name generation failed.");
@@ -369,15 +393,76 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(NameRaceAndGender
return std::move(botName);
}
uint32 RandomPlayerbotFactory::CalculateTotalAccountCount()
{
// Calculates the total number of required accounts, either using the specified randomBotAccountCount
// or determining it dynamically based on the WOTLK condition, max random bots, rotation pool size,
// and additional class account pool size.
// Checks if randomBotAccountCount is set, otherwise calculate it dynamically.
if (sPlayerbotAIConfig->randomBotAccountCount > 0)
return sPlayerbotAIConfig->randomBotAccountCount;
// Avoid creating accounts if both maxRandom & ClassBots are set to zero.
if (sPlayerbotAIConfig->maxRandomBots == 0 &&
sPlayerbotAIConfig->addClassAccountPoolSize == 0)
return 0;
//bool isWOTLK = sWorld->getIntConfig(CONFIG_EXPANSION) == EXPANSION_WRATH_OF_THE_LICH_KING; //not used, line marked for removal.
// Determine divisor based on WOTLK condition
int divisor = CalculateAvailableCharsPerAccount();
// Calculate max bots
int maxBots = sPlayerbotAIConfig->maxRandomBots;
// Take perodic online - offline into account
if (sPlayerbotAIConfig->enablePeriodicOnlineOffline)
{
maxBots *= sPlayerbotAIConfig->periodicOnlineOfflineRatio;
}
// Calculate base accounts, add class account pool size, and add 1 as a fixed offset
uint32 baseAccounts = maxBots / divisor;
return baseAccounts + sPlayerbotAIConfig->addClassAccountPoolSize + 1;
}
uint32 RandomPlayerbotFactory::CalculateAvailableCharsPerAccount()
{
bool noDK = sPlayerbotAIConfig->disableDeathKnightLogin || sWorld->getIntConfig(CONFIG_EXPANSION) != EXPANSION_WRATH_OF_THE_LICH_KING;
uint32 availableChars = noDK ? 9 : 10;
uint32 hordeRatio = sPlayerbotAIConfig->randomBotHordeRatio;
uint32 allianceRatio = sPlayerbotAIConfig->randomBotAllianceRatio;
// horde : alliance = 50 : 50 -> 0%
// horde : alliance = 0 : 50 -> 50%
// horde : alliance = 10 : 50 -> 40%
float unavailableRatio = static_cast<float>((std::max(hordeRatio, allianceRatio) - std::min(hordeRatio, allianceRatio))) /
(std::max(hordeRatio, allianceRatio) * 2);
if (unavailableRatio != 0)
{
// conservative floor to ensure enough chars (may result in more accounts than needed)
availableChars = availableChars - availableChars * unavailableRatio;
}
return availableChars;
}
void RandomPlayerbotFactory::CreateRandomBots()
{
/* multi-thread here is meaningless? since the async db operations */
if (sPlayerbotAIConfig->deleteRandomBotAccounts)
{
std::vector<uint32> botAccounts;
std::vector<uint32> botFriends;
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber)
// Calculates the total number of required accounts.
uint32 totalAccountCount = CalculateTotalAccountCount();
for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber)
{
std::ostringstream out;
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
@@ -387,9 +472,79 @@ void RandomPlayerbotFactory::CreateRandomBots()
botAccounts.push_back(accountId);
}
LOG_INFO("playerbots", "Deleting all random bot characters, {} accounts collected...", botAccounts.size());
LOG_INFO("playerbots", "Deleting all random bot characters and accounts...");
// First execute all the cleanup SQL commands
// Clear playerbots_random_bots table
PlayerbotsDatabase.Execute("DELETE FROM playerbots_random_bots");
// Get the database names dynamically
std::string loginDBName = LoginDatabase.GetConnectionInfo()->database;
std::string characterDBName = CharacterDatabase.GetConnectionInfo()->database;
// Delete all characters from bot accounts
CharacterDatabase.Execute("DELETE FROM characters WHERE account IN (SELECT id FROM " + loginDBName + ".account WHERE username LIKE '{}%%')",
sPlayerbotAIConfig->randomBotAccountPrefix.c_str());
// Clean up orphaned entries in playerbots_guild_tasks
PlayerbotsDatabase.Execute("DELETE FROM playerbots_guild_tasks WHERE owner NOT IN (SELECT guid FROM " + characterDBName + ".characters)");
// Clean up orphaned entries in playerbots_db_store
PlayerbotsDatabase.Execute("DELETE FROM playerbots_db_store WHERE guid NOT IN (SELECT guid FROM " + characterDBName + ".characters WHERE account IN (SELECT id FROM " + loginDBName + ".account WHERE username NOT LIKE '{}%%'))",
sPlayerbotAIConfig->randomBotAccountPrefix.c_str());
// Clean up orphaned records in character-related tables
CharacterDatabase.Execute("DELETE FROM arena_team_member WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM arena_team WHERE arenaTeamId NOT IN (SELECT arenaTeamId FROM arena_team_member)");
CharacterDatabase.Execute("DELETE FROM character_account_data WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_achievement WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_achievement_progress WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_action WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_aura WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_glyphs WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_homebind WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM item_instance WHERE owner_guid NOT IN (SELECT guid FROM characters) AND owner_guid > 0");
CharacterDatabase.Execute("DELETE FROM character_inventory WHERE guid NOT IN (SELECT guid FROM characters)");
// Clean up pet data
CharacterDatabase.Execute("DELETE FROM character_pet WHERE owner NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM pet_aura WHERE guid NOT IN (SELECT id FROM character_pet)");
CharacterDatabase.Execute("DELETE FROM pet_spell WHERE guid NOT IN (SELECT id FROM character_pet)");
CharacterDatabase.Execute("DELETE FROM pet_spell_cooldown WHERE guid NOT IN (SELECT id FROM character_pet)");
// Clean up character data
CharacterDatabase.Execute("DELETE FROM character_queststatus WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_queststatus_rewarded WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_reputation WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_skills WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_social WHERE friend NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_spell WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_spell_cooldown WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM character_talent WHERE guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM corpse WHERE guid NOT IN (SELECT guid FROM characters)");
// Clean up group data
CharacterDatabase.Execute("DELETE FROM `groups` WHERE leaderGuid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM group_member WHERE memberGuid NOT IN (SELECT guid FROM characters)");
// Clean up mail
CharacterDatabase.Execute("DELETE FROM mail WHERE receiver NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM mail_items WHERE receiver NOT IN (SELECT guid FROM characters)");
// Clean up guild data
CharacterDatabase.Execute("DELETE FROM guild WHERE leaderguid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM guild_bank_eventlog WHERE guildid NOT IN (SELECT guildid FROM guild)");
CharacterDatabase.Execute("DELETE FROM guild_member WHERE guildid NOT IN (SELECT guildid FROM guild) OR guid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM guild_rank WHERE guildid NOT IN (SELECT guildid FROM guild)");
// Clean up petition data
CharacterDatabase.Execute("DELETE FROM petition WHERE ownerguid NOT IN (SELECT guid FROM characters)");
CharacterDatabase.Execute("DELETE FROM petition_sign WHERE ownerguid NOT IN (SELECT guid FROM characters) OR playerguid NOT IN (SELECT guid FROM characters)");
// Finally, delete the bot accounts themselves
LOG_INFO("playerbots", "Deleting random bot accounts...");
QueryResult results = LoginDatabase.Query("SELECT id FROM account WHERE username LIKE '{}%%'",
sPlayerbotAIConfig->randomBotAccountPrefix.c_str());
sPlayerbotAIConfig->randomBotAccountPrefix.c_str());
int32 deletion_count = 0;
if (results)
{
@@ -397,16 +552,19 @@ void RandomPlayerbotFactory::CreateRandomBots()
{
Field* fields = results->Fetch();
uint32 accId = fields[0].Get<uint32>();
LOG_INFO("playerbots", "Deleting account accID: {}({})...", accId, ++deletion_count);
LOG_DEBUG("playerbots", "Deleting account accID: {}({})...", accId, ++deletion_count);
AccountMgr::DeleteAccount(accId);
} while (results->NextRow());
}
PlayerbotsDatabase.Execute(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_RANDOM_BOTS));
/* TODO(yunfan): we need to sleep here to wait for async account deleted, or the newly account won't be created
correctly the better way is turning the async db operation to sync db operation */
std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount);
LOG_INFO("playerbots", "Random bot characters deleted.");
uint32 timer = getMSTime();
// Wait for all pending database operations to complete
while (LoginDatabase.QueueSize() || CharacterDatabase.QueueSize() || PlayerbotsDatabase.QueueSize())
{
std::this_thread::sleep_for(1s);
}
LOG_INFO("playerbots", ">> Random bot accounts and data deleted in {} ms", GetMSTimeDiffToNow(timer));
LOG_INFO("playerbots", "Please reset the AiPlayerbot.DeleteRandomBotAccounts to 0 and restart the server...");
World::StopNow(SHUTDOWN_EXIT_CODE);
return;
@@ -414,28 +572,14 @@ void RandomPlayerbotFactory::CreateRandomBots()
LOG_INFO("playerbots", "Creating random bot accounts...");
std::unordered_map<NameRaceAndGender, std::vector<std::string>> nameCache;
uint32 totalAccCount = sPlayerbotAIConfig->randomBotAccountCount;
std::vector<std::future<void>> account_creations;
int account_creation = 0;
LOG_INFO("playerbots", "Creating cache for names per gender and race.");
QueryResult result = CharacterDatabase.Query("SELECT name, gender FROM playerbots_names");
if (!result)
{
LOG_ERROR("playerbots", "No more unused names left");
return;
}
do
{
Field* fields = result->Fetch();
std::string name = fields[0].Get<std::string>();
NameRaceAndGender raceAndGender = static_cast<NameRaceAndGender>(fields[1].Get<uint8>());
if (sObjectMgr->CheckPlayerName(name) == CHAR_NAME_SUCCESS)
nameCache[raceAndGender].push_back(name);
// Calculates the total number of required accounts.
uint32 totalAccountCount = CalculateTotalAccountCount();
uint32 timer = getMSTime();
} while (result->NextRow());
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber)
for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber)
{
std::ostringstream out;
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
@@ -464,22 +608,26 @@ void RandomPlayerbotFactory::CreateRandomBots()
LOG_DEBUG("playerbots", "Account {} created for random bots", accountName.c_str());
}
if (account_creation)
{
/* wait for async accounts create to make character create correctly, same as account delete */
LOG_INFO("playerbots", "Waiting for {} accounts loading into database...", account_creation);
std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount);
LOG_INFO("playerbots", "Waiting for {} accounts loading into database ({} queries)...", account_creation, LoginDatabase.QueueSize());
/* wait for async accounts create to make character create correctly */
while (LoginDatabase.QueueSize())
{
std::this_thread::sleep_for(1s);
}
LOG_INFO("playerbots", ">> {} Accounts loaded into database in {} ms", account_creation, GetMSTimeDiffToNow(timer));
}
LOG_INFO("playerbots", "Creating random bot characters...");
uint32 totalRandomBotChars = 0;
uint32 totalCharCount = sPlayerbotAIConfig->randomBotAccountCount * 10;
std::vector<std::pair<Player*, uint32>> playerBots;
std::vector<WorldSession*> sessionBots;
int bot_creation = 0;
for (uint32 accountNumber = 0; accountNumber < sPlayerbotAIConfig->randomBotAccountCount; ++accountNumber)
timer = getMSTime();
bool nameCached = false;
for (uint32 accountNumber = 0; accountNumber < totalAccountCount; ++accountNumber)
{
std::ostringstream out;
out << sPlayerbotAIConfig->randomBotAccountPrefix << accountNumber;
@@ -501,12 +649,41 @@ void RandomPlayerbotFactory::CreateRandomBots()
{
continue;
}
LOG_INFO("playerbots", "Creating random bot characters for account: [{}/{}]", accountNumber + 1,
sPlayerbotAIConfig->randomBotAccountCount);
if (!nameCached)
{
nameCached = true;
LOG_INFO("playerbots", "Creating cache for names per gender and race...");
QueryResult result = CharacterDatabase.Query("SELECT name, gender FROM playerbots_names");
if (!result)
{
LOG_ERROR("playerbots", "No more unused names left");
return;
}
do
{
Field* fields = result->Fetch();
std::string name = fields[0].Get<std::string>();
NameRaceAndGender raceAndGender = static_cast<NameRaceAndGender>(fields[1].Get<uint8>());
if (sObjectMgr->CheckPlayerName(name) == CHAR_NAME_SUCCESS)
{
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->SetData(0, name);
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
continue;
nameCache[raceAndGender].push_back(name);
}
} while (result->NextRow());
}
LOG_DEBUG("playerbots", "Creating random bot characters for account: [{}/{}]", accountNumber + 1, totalAccountCount);
RandomPlayerbotFactory factory(accountId);
WorldSession* session = new WorldSession(accountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING,
time_t(0), LOCALE_enUS, 0, false, false, 0, true);
time_t(0), LOCALE_enUS, 0, false, false, 0, true);
sessionBots.push_back(session);
for (uint8 cls = CLASS_WARRIOR; cls < MAX_CLASSES - count; ++cls)
@@ -543,9 +720,13 @@ void RandomPlayerbotFactory::CreateRandomBots()
if (bot_creation)
{
LOG_INFO("playerbots", "Waiting for {} characters loading into database...", bot_creation);
LOG_INFO("playerbots", "Waiting for {} characters loading into database ({} queries)...", bot_creation, CharacterDatabase.QueueSize());
/* wait for characters load into database, or characters will fail to loggin */
std::this_thread::sleep_for(5s + bot_creation * 5ms);
while (CharacterDatabase.QueueSize())
{
std::this_thread::sleep_for(1s);
}
LOG_INFO("playerbots", ">> {} Characters loaded into database in {} ms", bot_creation, GetMSTimeDiffToNow(timer));
}
for (WorldSession* session : sessionBots)
@@ -556,8 +737,8 @@ void RandomPlayerbotFactory::CreateRandomBots()
totalRandomBotChars += AccountMgr::GetCharactersCount(accountId);
}
LOG_INFO("server.loading", "{} random bot accounts with {} characters available",
sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars);
LOG_INFO("server.loading", ">> {} random bot accounts with {} characters available",
sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars);
}
void RandomPlayerbotFactory::CreateRandomGuilds()
@@ -627,7 +808,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds()
if (!player)
{
LOG_ERROR("playerbots", "ObjectAccessor Cannot find player to set leader for guild {} . Skipped...",
guildName.c_str());
guildName.c_str());
continue;
}
@@ -638,7 +819,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds()
if (!guild->Create(player, guildName))
{
LOG_ERROR("playerbots", "Error creating guild [ {} ] with leader [ {} ]", guildName.c_str(),
player->GetName().c_str());
player->GetName().c_str());
delete guild;
continue;
}
@@ -800,7 +981,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count
sPlayerbotAIConfig->randomBotArenaTeams.push_back(arenateam->GetId());
}
LOG_INFO("playerbots", "{} random bot arena teams available", arenaTeamNumber);
LOG_DEBUG("playerbots", "{} random bot {}vs{} arena teams available", arenaTeamNumber, type, type);
}
std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName()

View File

@@ -54,6 +54,8 @@ public:
static void CreateRandomGuilds();
static void CreateRandomArenaTeams(ArenaType slot, uint32 count);
static std::string const CreateRandomGuildName();
static uint32 CalculateTotalAccountCount();
static uint32 CalculateAvailableCharsPerAccount();
private:
std::string const CreateRandomBotName(NameRaceAndGender raceAndGender);

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@
#ifndef _PLAYERBOT_RANDOMPLAYERBOTMGR_H
#define _PLAYERBOT_RANDOMPLAYERBOTMGR_H
#include "NewRpgInfo.h"
#include "ObjectGuid.h"
#include "PlayerbotMgr.h"
@@ -111,6 +112,8 @@ public:
static bool HandlePlayerbotConsoleCommand(ChatHandler* handler, char const* args);
bool IsRandomBot(Player* bot);
bool IsRandomBot(ObjectGuid::LowType bot);
bool IsAddclassBot(Player* bot);
bool IsAddclassBot(ObjectGuid::LowType bot);
void Randomize(Player* bot);
void Clear(Player* bot);
void RandomizeFirst(Player* bot);
@@ -170,7 +173,20 @@ public:
static uint8 GetTeamClassIdx(bool isAlliance, uint8 claz) { return isAlliance * 20 + claz; }
void PrepareAddclassCache();
std::map<uint8, std::vector<ObjectGuid>> addclassCache;
void PrepareZone2LevelBracket();
void PrepareTeleportCache();
void Init();
std::map<uint8, std::unordered_set<ObjectGuid>> addclassCache;
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
std::map<uint8, std::vector<WorldLocation>> allianceStarterPerLevelCache;
std::map<uint8, std::vector<WorldLocation>> hordeStarterPerLevelCache;
struct LevelBracket {
uint32 low;
uint32 high;
bool InsideBracket(uint32 val) { return val >= low && val <= high; }
};
std::map<uint32, LevelBracket> zone2LevelBracket;
std::map<uint8, std::vector<WorldLocation>> bankerLocsPerLevelCache;
protected:
void OnBotLoginInternal(Player* const bot) override;
@@ -179,6 +195,8 @@ private:
botPID pid = botPID(1, 50, -50, 0, 0, 0);
float activityMod = 0.25;
bool _isBotInitializing = true;
bool _isBotLogging = true;
NewRpgStatistic rpgStasticTotal;
uint32 GetEventValue(uint32 bot, std::string const event);
std::string const GetEventData(uint32 bot, std::string const event);
uint32 SetEventValue(uint32 bot, std::string const event, uint32 value, uint32 validIn,
@@ -188,19 +206,18 @@ private:
time_t BgCheckTimer;
time_t LfgCheckTimer;
time_t PlayersCheckTimer;
time_t printStatsTimer;
uint32 AddRandomBots();
bool ProcessBot(uint32 bot);
void ScheduleRandomize(uint32 bot, uint32 time);
void RandomTeleport(Player* bot);
void RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth = false);
uint32 GetZoneLevel(uint16 mapId, float teleX, float teleY, float teleZ);
void PrepareTeleportCache();
typedef void (RandomPlayerbotMgr::*ConsoleCommandHandler)(Player*);
std::vector<Player*> players;
uint32 processTicks;
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
std::map<uint8, std::vector<WorldLocation>> bankerLocsPerLevelCache;
// std::map<uint32, std::vector<WorldLocation>> rpgLocsCache;
std::map<uint32, std::map<uint32, std::vector<WorldLocation>>> rpgLocsCacheLevel;

View File

@@ -33,12 +33,21 @@ public:
static ChatCommandTable playerbotsDebugCommandTable = {
{"bg", HandleDebugBGCommand, SEC_GAMEMASTER, Console::Yes},
};
static ChatCommandTable playerbotsAccountCommandTable = {
{"setKey", HandleSetSecurityKeyCommand, SEC_PLAYER, Console::No},
{"link", HandleLinkAccountCommand, SEC_PLAYER, Console::No},
{"linkedAccounts", HandleViewLinkedAccountsCommand, SEC_PLAYER, Console::No},
{"unlink", HandleUnlinkAccountCommand, SEC_PLAYER, Console::No},
};
static ChatCommandTable playerbotsCommandTable = {
{"bot", HandlePlayerbotCommand, SEC_PLAYER, Console::No},
{"gtask", HandleGuildTaskCommand, SEC_GAMEMASTER, Console::Yes},
{"pmon", HandlePerfMonCommand, SEC_GAMEMASTER, Console::Yes},
{"rndbot", HandleRandomPlayerbotCommand, SEC_GAMEMASTER, Console::Yes},
{"debug", playerbotsDebugCommandTable},
{"account", playerbotsAccountCommandTable},
};
static ChatCommandTable commandTable = {
@@ -101,6 +110,103 @@ public:
{
return BGTactics::HandleConsoleCommand(handler, args);
}
static bool HandleSetSecurityKeyCommand(ChatHandler* handler, char const* args)
{
if (!args || !*args)
{
handler->PSendSysMessage("Usage: .playerbots account setKey <securityKey>");
return false;
}
Player* player = handler->GetSession()->GetPlayer();
std::string key = args;
PlayerbotMgr* mgr = sPlayerbotsMgr->GetPlayerbotMgr(player);
if (mgr)
{
mgr->HandleSetSecurityKeyCommand(player, key);
return true;
}
else
{
handler->PSendSysMessage("PlayerbotMgr instance not found.");
return false;
}
}
static bool HandleLinkAccountCommand(ChatHandler* handler, char const* args)
{
if (!args || !*args)
return false;
char* accountName = strtok((char*)args, " ");
char* key = strtok(nullptr, " ");
if (!accountName || !key)
{
handler->PSendSysMessage("Usage: .playerbots account link <accountName> <securityKey>");
return false;
}
Player* player = handler->GetSession()->GetPlayer();
PlayerbotMgr* mgr = sPlayerbotsMgr->GetPlayerbotMgr(player);
if (mgr)
{
mgr->HandleLinkAccountCommand(player, accountName, key);
return true;
}
else
{
handler->PSendSysMessage("PlayerbotMgr instance not found.");
return false;
}
}
static bool HandleViewLinkedAccountsCommand(ChatHandler* handler, char const* /*args*/)
{
Player* player = handler->GetSession()->GetPlayer();
PlayerbotMgr* mgr = sPlayerbotsMgr->GetPlayerbotMgr(player);
if (mgr)
{
mgr->HandleViewLinkedAccountsCommand(player);
return true;
}
else
{
handler->PSendSysMessage("PlayerbotMgr instance not found.");
return false;
}
}
static bool HandleUnlinkAccountCommand(ChatHandler* handler, char const* args)
{
if (!args || !*args)
return false;
char* accountName = strtok((char*)args, " ");
if (!accountName)
{
handler->PSendSysMessage("Usage: .playerbots account unlink <accountName>");
return false;
}
Player* player = handler->GetSession()->GetPlayer();
PlayerbotMgr* mgr = sPlayerbotsMgr->GetPlayerbotMgr(player);
if (mgr)
{
mgr->HandleUnlinkAccountCommand(player, accountName);
return true;
}
else
{
handler->PSendSysMessage("PlayerbotMgr instance not found.");
return false;
}
}
};
void AddSC_playerbots_commandscript() { new playerbots_commandscript(); }

View File

@@ -87,27 +87,23 @@ Engine::~Engine(void)
void Engine::Reset()
{
strategyTypeMask = 0;
ActionNode* action = nullptr;
do
{
action = queue.Pop();
if (!action)
break;
while ((action = queue.Pop()) != nullptr)
{
delete action;
} while (true);
}
for (std::vector<TriggerNode*>::iterator i = triggers.begin(); i != triggers.end(); i++)
for (TriggerNode* trigger : triggers)
{
TriggerNode* trigger = *i;
delete trigger;
}
triggers.clear();
for (std::vector<Multiplier*>::iterator i = multipliers.begin(); i != multipliers.end(); i++)
for (Multiplier* multiplier : multipliers)
{
Multiplier* multiplier = *i;
delete multiplier;
}
@@ -146,160 +142,100 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
bool actionExecuted = false;
ActionBasket* basket = nullptr;
time_t currentTime = time(nullptr);
// aiObjectContext->Update();
// Update triggers and push default actions
ProcessTriggers(minimal);
PushDefaultActions();
uint32 iterations = 0;
uint32 iterationsPerTick = queue.Size() * (minimal ? 2 : sPlayerbotAIConfig->iterationsPerTick);
do
while (++iterations <= iterationsPerTick)
{
basket = queue.Peek();
if (!basket)
break;
if (basket)
float relevance = basket->getRelevance(); // for reference
bool skipPrerequisites = basket->isSkipPrerequisites();
if (minimal && (relevance < 100))
continue;
Event event = basket->getEvent();
ActionNode* actionNode = queue.Pop(); // NOTE: Pop() deletes basket
Action* action = InitializeAction(actionNode);
if (!action)
{
float relevance = basket->getRelevance(); // just for reference
bool skipPrerequisites = basket->isSkipPrerequisites();
if (minimal && (relevance < 100))
continue;
Event event = basket->getEvent();
// NOTE: queue.Pop() deletes basket
ActionNode* actionNode = queue.Pop();
Action* action = InitializeAction(actionNode);
if (action)
LogAction("A:%s - UNKNOWN", actionNode->getName().c_str());
}
else if (action->isUseful())
{
// Apply multipliers early to avoid unnecessary iterations
for (Multiplier* multiplier : multipliers)
{
relevance *= multiplier->GetValue(action);
action->setRelevance(relevance);
if (!action)
{
// LOG_ERROR("playerbots", "Action: {} - is UNKNOWN - c:{} l:{}", actionNode->getName().c_str(),
// botAI->GetBot()->getClass(), botAI->GetBot()->GetLevel());
LogAction("A:%s - UNKNOWN", actionNode->getName().c_str());
}
else if (action->isUseful())
{
for (std::vector<Multiplier*>::iterator i = multipliers.begin(); i != multipliers.end(); i++)
if (relevance <= 0)
{
Multiplier* multiplier = *i;
relevance *= multiplier->GetValue(action);
action->setRelevance(relevance);
LogAction("Multiplier %s made action %s useless", multiplier->getName().c_str(), action->getName().c_str());
break;
}
}
if (!relevance)
if (action->isPossible() && relevance > 0)
{
if (!skipPrerequisites)
{
LogAction("A:%s - PREREQ", action->getName().c_str());
if (MultiplyAndPush(actionNode->getPrerequisites(), relevance + 0.002f, false, event, "prereq"))
{
LogAction("Multiplier %s made action %s useless", multiplier->getName().c_str(),
action->getName().c_str());
break;
PushAgain(actionNode, relevance + 0.001f, event);
continue;
}
}
if (action->isPossible() && relevance)
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_ACTION, action->getName(), &aiObjectContext->performanceStack);
actionExecuted = ListenAndExecute(action, event);
if (pmo)
pmo->finish();
if (actionExecuted)
{
if (!skipPrerequisites)
{
LogAction("A:%s - PREREQ", action->getName().c_str());
if (MultiplyAndPush(actionNode->getPrerequisites(), relevance + 0.002f, false, event, "prereq"))
{
PushAgain(actionNode, relevance + 0.001f, event);
continue;
}
}
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_ACTION, action->getName(),
&aiObjectContext->performanceStack);
actionExecuted = ListenAndExecute(action, event);
if (pmo)
pmo->finish();
if (actionExecuted)
{
LogAction("A:%s - OK", action->getName().c_str());
MultiplyAndPush(actionNode->getContinuers(), relevance, false, event, "cont");
lastRelevance = relevance;
delete actionNode;
break;
}
else
{
LogAction("A:%s - FAILED", action->getName().c_str());
MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event, "alt");
}
LogAction("A:%s - OK", action->getName().c_str());
MultiplyAndPush(actionNode->getContinuers(), relevance, false, event, "cont");
lastRelevance = relevance;
delete actionNode; // Safe memory management
break;
}
else
{
if (botAI->HasStrategy("debug", BOT_STATE_NON_COMBAT))
{
std::ostringstream out;
out << "do: ";
out << action->getName();
out << " impossible (";
out << action->getRelevance() << ")";
if (!event.GetSource().empty())
out << " [" << event.GetSource() << "]";
botAI->TellMasterNoFacing(out);
}
LogAction("A:%s - IMPOSSIBLE", action->getName().c_str());
LogAction("A:%s - FAILED", action->getName().c_str());
MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event, "alt");
}
}
else
{
if (botAI->HasStrategy("debug", BOT_STATE_NON_COMBAT))
{
std::ostringstream out;
out << "do: ";
out << action->getName();
out << " useless (";
out << action->getRelevance() << ")";
if (!event.GetSource().empty())
out << " [" << event.GetSource() << "]";
botAI->TellMasterNoFacing(out);
}
lastRelevance = relevance;
LogAction("A:%s - USELESS", action->getName().c_str());
LogAction("A:%s - IMPOSSIBLE", action->getName().c_str());
MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event, "alt");
}
delete actionNode;
}
} while (basket && ++iterations <= iterationsPerTick);
// if (!basket)
// {
// lastRelevance = 0.0f;
// PushDefaultActions();
// // prevent the delay after pushing default actions
// if (queue.Peek() && depth < 1 && !minimal)
// return DoNextAction(unit, depth + 1, minimal);
// }
// MEMORY FIX TEST
/*
do
{
basket = queue.Peek();
if (basket)
else
{
// NOTE: queue.Pop() deletes basket
delete queue.Pop();
LogAction("A:%s - USELESS", action->getName().c_str());
lastRelevance = relevance;
}
delete actionNode; // Always delete after processing the action node
}
while (basket);
*/
if (time(nullptr) - currentTime > 1)
{
LogAction("too long execution");
LogAction("Execution time exceeded 1 second");
}
if (!actionExecuted)
@@ -567,7 +503,7 @@ std::string const Engine::ListStrategies()
std::string s = "Strategies: ";
if (strategies.empty())
return std::move(s);
return s;
for (std::map<std::string, Strategy*>::iterator i = strategies.begin(); i != strategies.end(); i++)
{

134
src/engine/Queue.cpp Normal file
View File

@@ -0,0 +1,134 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "Queue.h"
#include "AiObjectContext.h"
#include "Log.h"
#include "PlayerbotAIConfig.h"
void Queue::Push(ActionBasket* action)
{
if (!action)
{
return;
}
for (ActionBasket* basket : actions)
{
if (action->getAction()->getName() == basket->getAction()->getName())
{
updateExistingBasket(basket, action);
return;
}
}
actions.push_back(action);
}
ActionNode* Queue::Pop()
{
ActionBasket* highestRelevanceBasket = findHighestRelevanceBasket();
if (!highestRelevanceBasket)
{
return nullptr;
}
return extractAndDeleteBasket(highestRelevanceBasket);
}
ActionBasket* Queue::Peek()
{
return findHighestRelevanceBasket();
}
uint32 Queue::Size()
{
return actions.size();
}
void Queue::RemoveExpired()
{
if (!sPlayerbotAIConfig->expireActionTime)
{
return;
}
std::list<ActionBasket*> expiredBaskets;
collectExpiredBaskets(expiredBaskets);
removeAndDeleteBaskets(expiredBaskets);
}
// Private helper methods
void Queue::updateExistingBasket(ActionBasket* existing, ActionBasket* newBasket)
{
if (existing->getRelevance() < newBasket->getRelevance())
{
existing->setRelevance(newBasket->getRelevance());
}
if (ActionNode* actionNode = newBasket->getAction())
{
delete actionNode;
}
delete newBasket;
}
ActionBasket* Queue::findHighestRelevanceBasket() const
{
if (actions.empty())
{
return nullptr;
}
float maxRelevance = -1.0f;
ActionBasket* selection = nullptr;
for (ActionBasket* basket : actions)
{
if (basket->getRelevance() > maxRelevance)
{
maxRelevance = basket->getRelevance();
selection = basket;
}
}
return selection;
}
ActionNode* Queue::extractAndDeleteBasket(ActionBasket* basket)
{
ActionNode* action = basket->getAction();
actions.remove(basket);
delete basket;
return action;
}
void Queue::collectExpiredBaskets(std::list<ActionBasket*>& expiredBaskets)
{
uint32 expiryTime = sPlayerbotAIConfig->expireActionTime;
for (ActionBasket* basket : actions)
{
if (basket->isExpired(expiryTime))
{
expiredBaskets.push_back(basket);
}
}
}
void Queue::removeAndDeleteBaskets(std::list<ActionBasket*>& basketsToRemove)
{
for (ActionBasket* basket : basketsToRemove)
{
actions.remove(basket);
if (ActionNode* action = basket->getAction())
{
delete action;
}
delete basket;
}
}

94
src/engine/Queue.h Normal file
View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef PLAYERBOT_QUEUE_H
#define PLAYERBOT_QUEUE_H
#include "Action.h"
#include "Common.h"
/**
* @class Queue
* @brief Manages a priority queue of actions for the playerbot system
*
* This queue maintains a list of ActionBasket objects, each containing an action
* and its relevance score. Actions with higher relevance scores are prioritized.
*/
class Queue
{
public:
Queue() = default;
~Queue() = default;
/**
* @brief Adds an action to the queue or updates existing action's relevance
* @param action Pointer to the ActionBasket to be added
*
* If an action with the same name exists, updates its relevance if the new
* relevance is higher, then deletes the new action. Otherwise, adds the new
* action to the queue.
*/
void Push(ActionBasket* action);
/**
* @brief Removes and returns the action with highest relevance
* @return Pointer to the highest relevance ActionNode, or nullptr if queue is empty
*
* Ownership of the returned ActionNode is transferred to the caller.
* The associated ActionBasket is deleted.
*/
ActionNode* Pop();
/**
* @brief Returns the action with highest relevance without removing it
* @return Pointer to the ActionBasket with highest relevance, or nullptr if queue is empty
*/
ActionBasket* Peek();
/**
* @brief Returns the current size of the queue
* @return Number of actions in the queue
*/
uint32 Size();
/**
* @brief Removes and deletes expired actions from the queue
*
* Uses sPlayerbotAIConfig->expireActionTime to determine if actions have expired.
* Both the ActionNode and ActionBasket are deleted for expired actions.
*/
void RemoveExpired();
private:
/**
* @brief Updates existing basket with new relevance and cleans up new basket
*/
void updateExistingBasket(ActionBasket* existing, ActionBasket* newBasket);
/**
* @brief Finds the basket with the highest relevance score
* @return Pointer to the highest relevance basket, or nullptr if queue is empty
*/
ActionBasket* findHighestRelevanceBasket() const;
/**
* @brief Extracts action from basket and handles basket cleanup
*/
ActionNode* extractAndDeleteBasket(ActionBasket* basket);
/**
* @brief Collects all expired baskets into the provided list
*/
void collectExpiredBaskets(std::list<ActionBasket*>& expiredBaskets);
/**
* @brief Removes and deletes all baskets in the provided list
*/
void removeAndDeleteBaskets(std::list<ActionBasket*>& basketsToRemove);
std::list<ActionBasket*> actions; /**< Container for action baskets */
};
#endif

View File

@@ -275,7 +275,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
if (!player->InBattleground())
{
engine->addStrategiesNoInit("racials", "chat", "default", "cast time", "duel", "boost", nullptr);
engine->addStrategiesNoInit("racials", "chat", "default", "cast time", "potions", "duel", "boost", nullptr);
}
if (sPlayerbotAIConfig->autoAvoidAoe && facade->HasRealPlayerMaster())
{
@@ -304,7 +304,16 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
if (tab == 0)
engine->addStrategiesNoInit("arcane", "arcane aoe", nullptr);
else if (tab == 1)
engine->addStrategiesNoInit("fire", "fire aoe", nullptr);
{
if (player->HasSpell(44614) /*Frostfire Bolt*/ && player->HasAura(15047) /*Ice Shards*/)
{
engine->addStrategiesNoInit("frostfire", "frostfire aoe", nullptr);
}
else
{
engine->addStrategiesNoInit("fire", "fire aoe", nullptr);
}
}
else
engine->addStrategiesNoInit("frost", "frost aoe", nullptr);
@@ -312,8 +321,8 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
break;
case CLASS_WARRIOR:
if (tab == 2)
engine->addStrategiesNoInit("tank", "tank assist", "aoe", "mark rti", nullptr);
else if (player->GetLevel() < 36 || tab == 0)
engine->addStrategiesNoInit("tank", "tank assist", "aoe", nullptr);
else if (tab == 0 || !player->HasSpell(1680)) // Whirlwind
engine->addStrategiesNoInit("arms", "aoe", "dps assist", /*"behind",*/ nullptr);
else
engine->addStrategiesNoInit("fury", "aoe", "dps assist", /*"behind",*/ nullptr);
@@ -347,7 +356,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
engine->addStrategiesNoInit("heal", "cure", "dps assist", nullptr);
else
{
if (player->GetLevel() >= 20 && !player->HasAura(16931) /*thick hide*/)
if (player->HasSpell(768) /*cat form*/&& !player->HasAura(16931) /*thick hide*/)
{
engine->addStrategiesNoInit("cat", "dps assist", nullptr);
}
@@ -360,15 +369,19 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
case CLASS_HUNTER:
engine->addStrategiesNoInit("dps", "aoe", "bdps", "dps assist", nullptr);
engine->addStrategy("dps debuff", false);
// if (tab == HUNTER_TAB_SURVIVAL)
// {
// engine->addStrategy("trap weave", false);
// }
break;
case CLASS_ROGUE:
if (tab == ROGUE_TAB_ASSASSINATION)
if (tab == ROGUE_TAB_ASSASSINATION || tab == ROGUE_TAB_SUBTLETY)
{
engine->addStrategiesNoInit("melee", "dps assist", "aoe", /*"behind",*/ nullptr);
engine->addStrategiesNoInit("melee", "dps assist", "aoe", nullptr);
}
else
{
engine->addStrategiesNoInit("dps", "dps assist", "aoe", /*"behind",*/ nullptr);
engine->addStrategiesNoInit("dps", "dps assist", "aoe", nullptr);
}
break;
case CLASS_WARLOCK:
@@ -600,14 +613,15 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
if (!player->InBattleground())
{
nonCombatEngine->addStrategiesNoInit("nc", "food", "chat", "follow", "default", "quest", "loot", "gather", "duel",
"buff", "mount", "emote", nullptr);
nonCombatEngine->addStrategiesNoInit("nc", "food", "chat", "follow", "default", "quest", "loot",
"gather", "duel", "pvp", "buff", "mount", "emote", nullptr);
}
if (sPlayerbotAIConfig->autoSaveMana)
if (sPlayerbotAIConfig->autoSaveMana && PlayerbotAI::IsHeal(player, true))
{
nonCombatEngine->addStrategy("save mana", false);
}
if ((sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground())
{
Player* master = facade->GetMaster();
@@ -625,13 +639,17 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
// if (!urand(0, 3))
// nonCombatEngine->addStrategy("attack tagged");
nonCombatEngine->addStrategy("pvp", false);
// nonCombatEngine->addStrategy("pvp", false);
// nonCombatEngine->addStrategy("collision");
nonCombatEngine->addStrategy("grind", false);
// nonCombatEngine->addStrategy("group");
// nonCombatEngine->addStrategy("guild");
nonCombatEngine->addStrategy("grind", false);
if (sPlayerbotAIConfig->autoDoQuests)
if (sPlayerbotAIConfig->enableNewRpgStrategy)
{
nonCombatEngine->addStrategy("new rpg", false);
}
else if (sPlayerbotAIConfig->autoDoQuests)
{
// nonCombatEngine->addStrategy("travel");
nonCombatEngine->addStrategy("rpg", false);
@@ -658,7 +676,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master);
if (masterBotAI || sRandomPlayerbotMgr->IsRandomBot(player))
{
nonCombatEngine->addStrategy("pvp", false);
// nonCombatEngine->addStrategy("pvp", false);
// nonCombatEngine->addStrategy("collision");
// nonCombatEngine->addStrategy("group");
// nonCombatEngine->addStrategy("guild");
@@ -678,7 +696,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
}
else
{
nonCombatEngine->addStrategy("pvp", false);
// nonCombatEngine->addStrategy("pvp", false);
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -122,6 +122,7 @@ public:
static void InitTalentsByParsedSpecLink(Player* bot, std::vector<std::vector<uint32>> parsedSpecLink, bool reset);
void InitAvailableSpells();
void InitClassSpells();
void InitSpecialSpells();
void InitEquipment(bool incremental, bool second_chance = false);
void InitPet();
void InitAmmo();
@@ -136,7 +137,11 @@ public:
void ApplyEnchantAndGemsNew(bool destoryOld = true);
void InitInstanceQuests();
void UnbindInstance();
void InitKeyring();
void InitReputation();
void InitAttunementQuests();
void InitPotions();
private:
void Prepare();
// void InitSecondEquipmentSet();
@@ -149,14 +154,12 @@ private:
void InitSpells();
void ClearSpells();
void ClearSkills();
void InitSpecialSpells();
void InitTalents(uint32 specNo);
void InitTalentsByTemplate(uint32 specNo);
void InitQuests(std::list<uint32>& questMap);
void InitQuests(std::list<uint32>& questMap, bool withRewardItem = true);
void ClearInventory();
void ClearAllItems();
void ResetQuests();
void InitPotions();
std::vector<uint32> GetCurrentGemsCount();
bool CanEquipArmor(ItemTemplate const* proto);
@@ -190,7 +193,7 @@ private:
uint32 itemQuality;
uint32 gearScoreLimit;
static std::list<uint32> specialQuestIds;
std::vector<uint32> trainerIdCache;
static std::unordered_map<uint32, std::vector<uint32>> trainerIdCache;
static std::vector<uint32> enchantSpellIdCache;
static std::vector<uint32> enchantGemIdCache;

View File

@@ -833,7 +833,7 @@ bool RandomItemMgr::CanEquipWeapon(uint8 clazz, ItemTemplate const* proto)
void RandomItemMgr::BuildItemInfoCache()
{
uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
//uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); //not used, line marked for removal.
// load weightscales
LOG_INFO("playerbots", "Loading weightscales info");
@@ -1347,7 +1347,7 @@ uint32 RandomItemMgr::CalculateStatWeight(uint8 playerclass, uint8 spec, ItemTem
// check weapon dps
if (proto->IsWeaponVellum())
{
WeaponAttackType attType = BASE_ATTACK;
//WeaponAttackType attType = BASE_ATTACK; //not used, line marked for removal.
uint32 dps = 0;
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; i++)
@@ -2206,7 +2206,7 @@ void RandomItemMgr::BuildEquipCacheNew()
ObjectMgr::QuestMap const& questTemplates = sObjectMgr->GetQuestTemplates();
for (ObjectMgr::QuestMap::const_iterator i = questTemplates.begin(); i != questTemplates.end(); ++i)
{
uint32 questId = i->first;
//uint32 questId = i->first; //not used in this scope, line marked for removal.
Quest const* quest = i->second;
if (quest->IsRepeatable())
@@ -2313,8 +2313,9 @@ void RandomItemMgr::BuildAmmoCache()
for (uint32 subClass = ITEM_SUBCLASS_ARROW; subClass <= ITEM_SUBCLASS_BULLET; subClass++)
{
QueryResult results = WorldDatabase.Query(
"SELECT entry, Flags FROM item_template WHERE class = {} AND subclass = {} AND RequiredLevel <= {} and duration = 0 "
"ORDER BY stackable DESC, RequiredLevel DESC",
"SELECT entry FROM item_template WHERE class = {} AND subclass = {} AND RequiredLevel <= {} AND duration = 0 "
"AND (Flags & 16) = 0 AND dmg_min1 != 0 AND RequiredLevel != 0 "
"ORDER BY stackable DESC, ItemLevel DESC",
ITEM_CLASS_PROJECTILE, subClass, level);
if (!results)
continue;
@@ -2322,35 +2323,27 @@ void RandomItemMgr::BuildAmmoCache()
{
Field* fields = results->Fetch();
uint32 entry = fields[0].Get<uint32>();
uint32 flags = fields[1].Get<uint32>();
if (flags & ITEM_FLAG_DEPRECATED)
{
continue;
}
ammoCache[level][subClass] = entry;
ammoCache[level][subClass].push_back(entry);
++counter;
break;
} while (results->NextRow());
}
}
LOG_INFO("server.loading", "Cached {} types of ammo", counter); // TEST
LOG_INFO("server.loading", "Cached {} ammo", counter); // TEST
}
uint32 RandomItemMgr::GetAmmo(uint32 level, uint32 subClass) { return ammoCache[level][subClass]; }
std::vector<uint32> RandomItemMgr::GetAmmo(uint32 level, uint32 subClass) { return ammoCache[level][subClass]; }
void RandomItemMgr::BuildPotionCache()
{
uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
// if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
// maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
LOG_INFO("server.loading", "Building potion cache for {} levels", maxLevel);
LOG_INFO("playerbots", "Building potion cache for {} levels", maxLevel);
ItemTemplateContainer const* itemTemplates = sObjectMgr->GetItemTemplateStore();
uint32 counter = 0;
for (uint32 level = 1; level <= maxLevel + 1; level += 10)
for (uint32 level = 1; level <= maxLevel; level++)
{
uint32 effects[] = {SPELL_EFFECT_HEAL, SPELL_EFFECT_ENERGIZE};
for (uint8 i = 0; i < 2; ++i)
@@ -2367,8 +2360,9 @@ void RandomItemMgr::BuildPotionCache()
(proto->SubClass != ITEM_SUBCLASS_POTION && proto->SubClass != ITEM_SUBCLASS_FLASK) ||
proto->Bonding != NO_BIND)
continue;
if (proto->RequiredLevel && (proto->RequiredLevel > level || proto->RequiredLevel < level - 10))
uint32 requiredLevel = proto->RequiredLevel;
if (requiredLevel > level || (level > 13 && requiredLevel < level - 13))
continue;
if (proto->RequiredSkill)
@@ -2380,39 +2374,44 @@ void RandomItemMgr::BuildPotionCache()
if (proto->Duration & 0x80000000)
continue;
for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; j++)
if (proto->AllowableClass != -1)
continue;
bool hybrid = false;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[0].SpellId);
if (!spellInfo)
continue;
// do not accept hybrid potion
for (uint8 i = 1; i < 3; i++)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[j].SpellId);
if (!spellInfo)
continue;
for (uint8 i = 0; i < 3; i++)
if (spellInfo->Effects[i].Effect != 0)
{
if (spellInfo->Effects[i].Effect == effect)
{
potionCache[level / 10][effect].push_back(itr.first);
break;
}
hybrid = true;
break;
}
}
if (hybrid)
continue;
if (spellInfo->Effects[0].Effect == effect)
potionCache[level][effect].push_back(itr.first);
}
}
}
for (uint32 level = 1; level <= maxLevel + 1; level += 10)
for (uint32 level = 1; level <= maxLevel; level++)
{
uint32 effects[] = {SPELL_EFFECT_HEAL, SPELL_EFFECT_ENERGIZE};
for (uint8 i = 0; i < 2; ++i)
{
uint32 effect = effects[i];
uint32 size = potionCache[level / 10][effect].size();
++counter;
LOG_DEBUG("server.loading", "Potion cache for level={}, effect={}: {} items", level, effect, size);
uint32 size = potionCache[level][effect].size();
counter += size;
}
}
LOG_INFO("server.loading", "Cached {} types of potions", counter); // TEST
LOG_INFO("playerbots", "Cached {} potions", counter);
}
void RandomItemMgr::BuildFoodCache()
@@ -2478,7 +2477,7 @@ void RandomItemMgr::BuildFoodCache()
uint32 RandomItemMgr::GetRandomPotion(uint32 level, uint32 effect)
{
std::vector<uint32> potions = potionCache[(level - 1) / 10][effect];
const std::vector<uint32> &potions = potionCache[level][effect];
if (potions.empty())
return 0;

View File

@@ -157,7 +157,7 @@ public:
uint32 GetStatWeight(Player* player, uint32 itemId);
uint32 GetLiveStatWeight(Player* player, uint32 itemId);
uint32 GetRandomItem(uint32 level, RandomItemType type, RandomItemPredicate* predicate = nullptr);
uint32 GetAmmo(uint32 level, uint32 subClass);
std::vector<uint32> GetAmmo(uint32 level, uint32 subClass);
uint32 GetRandomPotion(uint32 level, uint32 effect);
uint32 GetRandomFood(uint32 level, uint32 category);
uint32 GetFood(uint32 level, uint32 category);
@@ -195,7 +195,7 @@ private:
std::map<RandomItemType, RandomItemPredicate*> predicates;
BotEquipCache equipCache;
std::map<EquipmentSlots, std::set<InventoryType>> viableSlots;
std::map<uint32, std::map<uint32, uint32>> ammoCache;
std::map<uint32, std::map<uint32, std::vector<uint32>>> ammoCache;
std::map<uint32, std::map<uint32, std::vector<uint32>>> potionCache;
std::map<uint32, std::map<uint32, std::vector<uint32>>> foodCache;
std::map<uint32, std::vector<uint32>> tradeCache;

View File

@@ -5,11 +5,14 @@
#include "DBCStores.h"
#include "ItemTemplate.h"
#include "ObjectMgr.h"
#include "PlayerbotAI.h"
#include "PlayerbotAIAware.h"
#include "SharedDefines.h"
#include "SpellAuraDefines.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "UpdateFields.h"
#include "Util.h"
StatsCollector::StatsCollector(CollectorType type, int32 cls) : type_(type), cls_(cls) { Reset(); }
@@ -52,12 +55,12 @@ void StatsCollector::CollectItemStats(ItemTemplate const* proto)
CollectSpellStats(proto->Spells[j].SpellId, 1.0f, 0);
break;
case ITEM_SPELLTRIGGER_CHANCE_ON_HIT:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
{
if (proto->Spells[j].SpellPPMRate > 0.01f)
CollectSpellStats(proto->Spells[j].SpellId, 1.0f, 60000 / proto->Spells[j].SpellPPMRate);
else
CollectSpellStats(proto->Spells[j].SpellId, 1.0f, 60000 / 1.8f); // Default PPM = 1.8
CollectSpellStats(proto->Spells[j].SpellId, 1.0f, 60000 / 1.8f); // Default PPM = 1.8
}
break;
default:
@@ -67,7 +70,7 @@ void StatsCollector::CollectItemStats(ItemTemplate const* proto)
if (proto->socketBonus)
{
if (const SpellItemEnchantmentEntry *enchant = sSpellItemEnchantmentStore.LookupEntry(proto->socketBonus))
if (const SpellItemEnchantmentEntry* enchant = sSpellItemEnchantmentStore.LookupEntry(proto->socketBonus))
CollectEnchantStats(enchant);
}
}
@@ -94,34 +97,50 @@ void StatsCollector::CollectSpellStats(uint32 spellId, float multiplier, int32 s
procFlags = eventEntry->procFlags;
else
procFlags = spellInfo->ProcFlags;
if (eventEntry && eventEntry->customChance)
procChance = eventEntry->customChance;
else
procChance = spellInfo->ProcChance;
bool lowChance = procChance <= 5;
bool lowChance = procChance <= 5;
if (lowChance || (procFlags && !CanBeTriggeredByType(spellInfo, procFlags)))
canNextTrigger = false;
if (spellInfo->StackAmount)
{
// Heuristic multiplier for spell with stackAmount since high stackAmount may not be available
if (spellInfo->StackAmount <= 10)
multiplier *= spellInfo->StackAmount * 0.6;
if (spellInfo->StackAmount <= 1)
multiplier *= spellInfo->StackAmount * 1;
else if (spellInfo->StackAmount <= 5)
multiplier *= 1 + (spellInfo->StackAmount - 1) * 0.75;
else if (spellInfo->StackAmount <= 10)
multiplier *= 4 + (spellInfo->StackAmount - 5) * 0.6;
else if (spellInfo->StackAmount <= 20)
multiplier *= 6 + (spellInfo->StackAmount - 10) * 0.4;
multiplier *= 7 + (spellInfo->StackAmount - 10) * 0.4;
else
multiplier *= 10;
multiplier *= 11;
}
for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
{
const SpellEffectInfo& effectInfo = spellInfo->Effects[i];
if (!effectInfo.Effect)
continue;
switch (effectInfo.Effect)
{
case SPELL_EFFECT_APPLY_AURA:
{
if (spellInfo->SpellFamilyName && /*effectInfo.ApplyAuraName != SPELL_AURA_DUMMY &&*/
effectInfo.ApplyAuraName != SPELL_AURA_PROC_TRIGGER_SPELL)
{
if (!CheckSpellValidation(spellInfo->SpellFamilyName, effectInfo.SpellClassMask))
return;
// Some dummy effects cannot be recognized, make some bonus to identify
stats[STATS_TYPE_BONUS] += 1;
}
/// @todo Handle negative spell
if (!spellInfo->IsPositive())
break;
@@ -130,7 +149,8 @@ void StatsCollector::CollectSpellStats(uint32 spellId, float multiplier, int32 s
if (spellCooldown <= 2000 || spellInfo->GetDuration() == -1)
coverage = 1.0f;
else
coverage = std::min(1.0f, (float)spellInfo->GetDuration() / (spellInfo->GetDuration() + spellCooldown));
coverage =
std::min(1.0f, (float)spellInfo->GetDuration() / (spellInfo->GetDuration() + spellCooldown));
multiplier *= coverage;
HandleApplyAura(effectInfo, multiplier, canNextTrigger, triggerCooldown);
@@ -167,12 +187,12 @@ void StatsCollector::CollectSpellStats(uint32 spellId, float multiplier, int32 s
break;
float normalizedCd = std::max((float)spellCooldown / 1000, 5.0f);
int32 val = AverageValue(effectInfo);
if (type_ == CollectorType::MELEE || type_ == CollectorType::RANGED)
if (type_ & (CollectorType::MELEE | CollectorType::RANGED))
{
float transfer_multiplier = 1;
stats[STATS_TYPE_ATTACK_POWER] += (float)val / normalizedCd * multiplier * transfer_multiplier;
}
else if (type_ == CollectorType::SPELL_DMG)
else if (type_ & CollectorType::SPELL_DMG)
{
float transfer_multiplier = 0.5;
stats[STATS_TYPE_SPELL_POWER] += (float)val / normalizedCd * multiplier * transfer_multiplier;
@@ -200,7 +220,7 @@ void StatsCollector::CollectEnchantStats(SpellItemEnchantmentEntry const* enchan
{
case ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL:
{
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
CollectSpellStats(enchant_spell_id, 0.25f);
break;
}
@@ -225,55 +245,60 @@ void StatsCollector::CollectEnchantStats(SpellItemEnchantmentEntry const* enchan
}
/// @todo Special case for some spell that hard to calculate, like trinket, relic, etc.
bool StatsCollector::SpecialSpellFilter(uint32 spellId) {
bool StatsCollector::SpecialSpellFilter(uint32 spellId)
{
// trinket
switch (spellId)
{
case 27521: // Insightful Earthstorm Diamond
case 60764: // Totem of Splintering
if (type_ & (CollectorType::SPELL))
return true;
break;
case 27521: // Insightful Earthstorm Diamond
stats[STATS_TYPE_MANA_REGENERATION] += 20;
return true;
case 55381: // Insightful Earthsiege Diamond
case 55381: // Insightful Earthsiege Diamond
stats[STATS_TYPE_MANA_REGENERATION] += 40;
return true;
case 39442: // Darkmoon Card: Wrath
if (type_ != CollectorType::SPELL_HEAL)
case 39442: // Darkmoon Card: Wrath
if (!(type_ & CollectorType::SPELL_HEAL))
stats[STATS_TYPE_CRIT] += 50;
return true;
case 59620: // Berserk
if (type_ == CollectorType::MELEE)
case 59620: // Berserk
if (type_ & CollectorType::MELEE)
stats[STATS_TYPE_ATTACK_POWER] += 120;
return true;
case 67702: // Death's Verdict
case 67702: // Death's Verdict
stats[STATS_TYPE_ATTACK_POWER] += 225;
return true;
case 67771: // Death's Verdict (heroic)
case 67771: // Death's Verdict (heroic)
stats[STATS_TYPE_ATTACK_POWER] += 260;
return true;
case 71406: // Tiny Abomination in a Jar
case 71406: // Tiny Abomination in a Jar
if (cls_ == CLASS_PALADIN)
stats[STATS_TYPE_ATTACK_POWER] += 600;
else
stats[STATS_TYPE_ATTACK_POWER] += 150;
return true;
case 71545: // Tiny Abomination in a Jar (heroic)
case 71545: // Tiny Abomination in a Jar (heroic)
if (cls_ == CLASS_PALADIN)
stats[STATS_TYPE_ATTACK_POWER] += 800;
else
stats[STATS_TYPE_ATTACK_POWER] += 200;
return true;
case 71519: // Deathbringer's Will
return true;
case 71519: // Deathbringer's Will
stats[STATS_TYPE_ATTACK_POWER] += 350;
return true;
case 71562: // Deathbringer's Will (heroic)
case 71562: // Deathbringer's Will (heroic)
stats[STATS_TYPE_ATTACK_POWER] += 400;
return true;
case 71602: // Dislodged Foreign Object
case 71602: // Dislodged Foreign Object
/// @todo The item can be triggered by heal spell, which mismatch with it's description
/// Noticing that heroic item can not be triggered, probably a bug to report to AC
if (type_ == CollectorType::SPELL_HEAL)
if (type_ & CollectorType::SPELL_HEAL)
return true;
break;
case 71903: // Shadowmourne
case 71903: // Shadowmourne
stats[STATS_TYPE_STRENGTH] += 200;
return true;
default:
@@ -295,26 +320,26 @@ bool StatsCollector::SpecialEnchantFilter(uint32 enchantSpellId)
switch (enchantSpellId)
{
case 64440:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
{
stats[STATS_TYPE_PARRY] += 50;
}
return true;
case 53365: // Rune of the Fallen Crusader
if (type_ == CollectorType::MELEE)
case 53365: // Rune of the Fallen Crusader
if (type_ & CollectorType::MELEE)
{
stats[STATS_TYPE_STRENGTH] += 75;
}
return true;
case 62157: // Rune of the Stoneskin Gargoyle
if (type_ == CollectorType::MELEE)
case 62157: // Rune of the Stoneskin Gargoyle
if (type_ & CollectorType::MELEE)
{
stats[STATS_TYPE_DEFENSE] += 25;
stats[STATS_TYPE_STAMINA] += 50;
}
return true;
case 64571: // Blood draining
if (type_ == CollectorType::MELEE)
case 64571: // Blood draining
if (type_ & CollectorType::MELEE)
{
stats[STATS_TYPE_STAMINA] += 50;
}
@@ -325,18 +350,34 @@ bool StatsCollector::SpecialEnchantFilter(uint32 enchantSpellId)
return false;
}
bool StatsCollector::CanBeTriggeredByType(SpellInfo const* spellInfo, uint32 procFlags)
bool StatsCollector::CanBeTriggeredByType(SpellInfo const* spellInfo, uint32 procFlags, bool strict)
{
const SpellProcEventEntry* eventEntry = sSpellMgr->GetSpellProcEvent(spellInfo->Id);
uint32 spellFamilyName = eventEntry ? eventEntry->spellFamilyName : 0;
uint32 spellFamilyName = 0;
if (eventEntry)
{
spellFamilyName = eventEntry->spellFamilyName;
flag96 spellFamilyMask = eventEntry->spellFamilyMask;
if (spellFamilyName != 0)
{
if (!CheckSpellValidation(spellFamilyName, spellFamilyMask, strict))
return false;
}
}
if (spellFamilyName != 0)
/// @todo Check specific trigger spell by spellFamilyMask
return true;
uint32 triggerMask = TAKEN_HIT_PROC_FLAG_MASK; // Generic trigger mask
switch (type_) {
case CollectorType::MELEE:
uint32 triggerMask = TAKEN_HIT_PROC_FLAG_MASK; // Generic trigger mask
switch (type_)
{
case CollectorType::MELEE_DMG:
{
triggerMask |= MELEE_PROC_FLAG_MASK;
triggerMask |= SPELL_PROC_FLAG_MASK;
triggerMask |= PROC_FLAG_DONE_PERIODIC;
if (procFlags & triggerMask)
return true;
break;
}
case CollectorType::MELEE_TANK:
{
triggerMask |= MELEE_PROC_FLAG_MASK;
triggerMask |= SPELL_PROC_FLAG_MASK;
@@ -349,7 +390,7 @@ bool StatsCollector::CanBeTriggeredByType(SpellInfo const* spellInfo, uint32 pro
{
triggerMask |= RANGED_PROC_FLAG_MASK;
triggerMask |= SPELL_PROC_FLAG_MASK;
triggerMask |= PERIODIC_PROC_FLAG_MASK;
triggerMask |= PROC_FLAG_DONE_PERIODIC;
if (procFlags & triggerMask)
return true;
break;
@@ -357,6 +398,7 @@ bool StatsCollector::CanBeTriggeredByType(SpellInfo const* spellInfo, uint32 pro
case CollectorType::SPELL_DMG:
{
triggerMask |= SPELL_PROC_FLAG_MASK;
triggerMask |= PROC_FLAG_DONE_PERIODIC;
// Healing spell cannot trigger
triggerMask &= ~PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS;
triggerMask &= ~PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS;
@@ -367,10 +409,13 @@ bool StatsCollector::CanBeTriggeredByType(SpellInfo const* spellInfo, uint32 pro
case CollectorType::SPELL_HEAL:
{
triggerMask |= SPELL_PROC_FLAG_MASK;
triggerMask |= PROC_FLAG_DONE_PERIODIC;
// Dmg spell should not trigger
triggerMask &= ~PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG;
triggerMask &= ~PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG;
triggerMask &= ~PROC_FLAG_DONE_PERIODIC; // spellFamilyName = 0 and PROC_FLAG_DONE_PERIODIC -> it is a dmg spell
if (!spellFamilyName)
triggerMask &=
~PROC_FLAG_DONE_PERIODIC; // spellFamilyName = 0 and PROC_FLAG_DONE_PERIODIC -> it is a dmg spell
if (procFlags & triggerMask)
return true;
break;
@@ -419,39 +464,39 @@ void StatsCollector::CollectByItemStatType(uint32 itemStatType, int32 val)
stats[STATS_TYPE_BLOCK_RATING] += val;
break;
case ITEM_MOD_HIT_MELEE_RATING:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
stats[STATS_TYPE_HIT] += val;
break;
case ITEM_MOD_HIT_RANGED_RATING:
if (type_ == CollectorType::RANGED)
if (type_ & CollectorType::RANGED)
stats[STATS_TYPE_HIT] += val;
break;
case ITEM_MOD_HIT_SPELL_RATING:
if (type_ == CollectorType::SPELL)
if (type_ & CollectorType::SPELL)
stats[STATS_TYPE_HIT] += val;
break;
case ITEM_MOD_CRIT_MELEE_RATING:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
stats[STATS_TYPE_CRIT] += val;
break;
case ITEM_MOD_CRIT_RANGED_RATING:
if (type_ == CollectorType::RANGED)
if (type_ & CollectorType::RANGED)
stats[STATS_TYPE_CRIT] += val;
break;
case ITEM_MOD_CRIT_SPELL_RATING:
if (type_ == CollectorType::SPELL)
if (type_ & CollectorType::SPELL)
stats[STATS_TYPE_CRIT] += val;
break;
case ITEM_MOD_HASTE_MELEE_RATING:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
stats[STATS_TYPE_HASTE] += val;
break;
case ITEM_MOD_HASTE_RANGED_RATING:
if (type_ == CollectorType::RANGED)
if (type_ & CollectorType::RANGED)
stats[STATS_TYPE_HASTE] += val;
break;
case ITEM_MOD_HASTE_SPELL_RATING:
if (type_ == CollectorType::SPELL)
if (type_ & CollectorType::SPELL)
stats[STATS_TYPE_HASTE] += val;
break;
case ITEM_MOD_HIT_RATING:
@@ -502,13 +547,14 @@ void StatsCollector::CollectByItemStatType(uint32 itemStatType, int32 val)
}
}
void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float multiplier, bool canNextTrigger, uint32 triggerCooldown)
void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float multiplier, bool canNextTrigger,
uint32 triggerCooldown)
{
if (effectInfo.Effect != SPELL_EFFECT_APPLY_AURA)
return;
int32 val = AverageValue(effectInfo);
switch (effectInfo.ApplyAuraName)
{
case SPELL_AURA_MOD_DAMAGE_DONE:
@@ -534,11 +580,11 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu
break;
}
case SPELL_AURA_MOD_ATTACK_POWER:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
stats[STATS_TYPE_ATTACK_POWER] += val * multiplier;
break;
case SPELL_AURA_MOD_RANGED_ATTACK_POWER:
if (type_ == CollectorType::RANGED)
if (type_ & CollectorType::RANGED)
stats[STATS_TYPE_ATTACK_POWER] += val * multiplier;
break;
case SPELL_AURA_MOD_SHIELD_BLOCKVALUE:
@@ -564,7 +610,7 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu
case STAT_SPIRIT:
stats[STATS_TYPE_SPIRIT] += val * multiplier;
break;
case -1: // Stat all
case -1: // Stat all
stats[STATS_TYPE_STRENGTH] += val * multiplier;
stats[STATS_TYPE_AGILITY] += val * multiplier;
stats[STATS_TYPE_STAMINA] += val * multiplier;
@@ -579,7 +625,7 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu
case SPELL_AURA_MOD_RESISTANCE:
{
int32 statType = effectInfo.MiscValue;
if (statType & SPELL_SCHOOL_MASK_NORMAL) // physical
if (statType & SPELL_SCHOOL_MASK_NORMAL) // physical
stats[STATS_TYPE_ARMOR] += val * multiplier;
break;
}
@@ -604,39 +650,39 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu
stats[STATS_TYPE_BLOCK_RATING] += val * multiplier;
break;
case CR_HIT_MELEE:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
stats[STATS_TYPE_HIT] += val * multiplier;
break;
case CR_HIT_RANGED:
if (type_ == CollectorType::RANGED)
if (type_ & CollectorType::RANGED)
stats[STATS_TYPE_HIT] += val * multiplier;
break;
case CR_HIT_SPELL:
if (type_ == CollectorType::SPELL)
if (type_ & CollectorType::SPELL)
stats[STATS_TYPE_HIT] += val * multiplier;
break;
case CR_CRIT_MELEE:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
stats[STATS_TYPE_CRIT] += val * multiplier;
break;
case CR_CRIT_RANGED:
if (type_ == CollectorType::RANGED)
if (type_ & CollectorType::RANGED)
stats[STATS_TYPE_CRIT] += val * multiplier;
break;
case CR_CRIT_SPELL:
if (type_ == CollectorType::SPELL)
if (type_ & CollectorType::SPELL)
stats[STATS_TYPE_CRIT] += val * multiplier;
break;
case CR_HASTE_MELEE:
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
stats[STATS_TYPE_HASTE] += val * multiplier;
break;
case CR_HASTE_RANGED:
if (type_ == CollectorType::RANGED)
if (type_ & CollectorType::RANGED)
stats[STATS_TYPE_HASTE] += val * multiplier;
break;
case CR_HASTE_SPELL:
if (type_ == CollectorType::SPELL)
if (type_ & CollectorType::SPELL)
stats[STATS_TYPE_HASTE] += val * multiplier;
break;
case CR_EXPERTISE:
@@ -675,12 +721,18 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu
CollectSpellStats(effectInfo.TriggerSpell, multiplier, triggerCooldown);
break;
}
case SPELL_AURA_ADD_TARGET_TRIGGER:
{
if (canNextTrigger)
CollectSpellStats(effectInfo.TriggerSpell, multiplier, triggerCooldown);
break;
}
case SPELL_AURA_MOD_CRIT_DAMAGE_BONUS:
{
if (type_ != CollectorType::SPELL_HEAL)
{
int32 statType = effectInfo.MiscValue;
if (statType & SPELL_SCHOOL_MASK_NORMAL) // physical
if (statType & SPELL_SCHOOL_MASK_NORMAL) // physical
stats[STATS_TYPE_CRIT] += 30 * val * multiplier;
}
break;
@@ -692,7 +744,7 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu
int32 StatsCollector::AverageValue(const SpellEffectInfo& effectInfo)
{
float basePointsPerLevel = effectInfo.RealPointsPerLevel;
//float basePointsPerLevel = effectInfo.RealPointsPerLevel; //not used, line marked for removal.
int32 basePoints = effectInfo.BasePoints;
int32 randomPoints = int32(effectInfo.DieSides);
@@ -709,4 +761,73 @@ int32 StatsCollector::AverageValue(const SpellEffectInfo& effectInfo)
break;
}
return basePoints;
}
}
bool StatsCollector::CheckSpellValidation(uint32 spellFamilyName, flag96 spelFalimyFlags, bool strict)
{
if (PlayerbotAI::Class2SpellFamilyName(cls_) != spellFamilyName)
return false;
bool isHealingSpell = PlayerbotAI::IsHealingSpell(spellFamilyName, spelFalimyFlags);
// strict to healer
if (strict && (type_ & CollectorType::SPELL_HEAL))
{
return isHealingSpell;
}
if (!(type_ & CollectorType::SPELL_HEAL) && isHealingSpell)
return false;
// spells for caster/melee/tank are ambiguous
if (cls_ == CLASS_DRUID && spellFamilyName == SPELLFAMILY_DRUID && (type_ & CollectorType::MELEE))
{
uint32 castingFlagsA = 0x4 | 0x2 | 0x1 | 0x200000; // starfire | moonfire | wrath | insect swarm
uint32 castingFlagsB = 0x0;
uint32 castingFlagsC = 0x0;
flag96 invalidFlags = {castingFlagsA, castingFlagsB, castingFlagsC};
if (spelFalimyFlags & invalidFlags)
return false;
}
if (cls_ == CLASS_PALADIN && spellFamilyName == SPELLFAMILY_PALADIN && (type_ & CollectorType::MELEE_TANK))
{
uint32 retributionFlagsA = 0x0;
uint32 retributionFlagsB = 0x8000; // crusader strike
uint32 retributionFlagsC = 0x0;
flag96 invalidFlags = {retributionFlagsA, retributionFlagsB, retributionFlagsC};
if (spelFalimyFlags & invalidFlags)
return false;
}
if (cls_ == CLASS_PALADIN && spellFamilyName == SPELLFAMILY_PALADIN && (type_ & CollectorType::MELEE_DMG))
{
uint32 retributionFlagsA = 0x0;
uint32 retributionFlagsB = 0x100000 | 0x40; // shield of righteouness | holy shield
uint32 retributionFlagsC = 0x0;
flag96 invalidFlags = {retributionFlagsA, retributionFlagsB, retributionFlagsC};
if (spelFalimyFlags & invalidFlags)
return false;
}
if (cls_ == CLASS_SHAMAN && spellFamilyName == SPELLFAMILY_SHAMAN && (type_ & CollectorType::SPELL_DMG))
{
uint32 meleeFlagsA = 0x0;
uint32 meleeFlagsB = 0x1000010; // stromstrike
uint32 meleeFlagsC = 0x4; // lava lash
flag96 invalidFlags = {meleeFlagsA, meleeFlagsB, meleeFlagsC};
if (spelFalimyFlags & invalidFlags)
return false;
}
if (cls_ == CLASS_SHAMAN && spellFamilyName == SPELLFAMILY_SHAMAN && (type_ & CollectorType::MELEE_DMG))
{
uint32 casterFlagsA = 0x0;
uint32 casterFlagsB = 0x1000; // lava burst
uint32 casterFlagsC = 0x0;
flag96 invalidFlags = {casterFlagsA, casterFlagsB, casterFlagsC};
if (spelFalimyFlags & invalidFlags)
return false;
}
return true;
}

View File

@@ -42,15 +42,19 @@ enum StatsType : uint8
// Stats for weapon dps
STATS_TYPE_MELEE_DPS,
STATS_TYPE_RANGED_DPS,
STATS_TYPE_MAX = 25
// Bonus for unrecognized stats
STATS_TYPE_BONUS,
STATS_TYPE_MAX = 26
};
enum CollectorType : uint8
{
MELEE = 1,
RANGED = 2,
SPELL_DMG = 4,
SPELL_HEAL = 8,
MELEE_DMG = 1,
MELEE_TANK = 2,
RANGED = 4,
SPELL_DMG = 8,
SPELL_HEAL = 16,
MELEE = MELEE_DMG | MELEE_TANK,
SPELL = SPELL_DMG | SPELL_HEAL
};
@@ -63,19 +67,21 @@ public:
void CollectItemStats(ItemTemplate const* proto);
void CollectSpellStats(uint32 spellId, float multiplier = 1.0f, int32 spellCooldown = -1);
void CollectEnchantStats(SpellItemEnchantmentEntry const* enchant);
bool CanBeTriggeredByType(SpellInfo const* spellInfo, uint32 procFlags, bool strict = true);
bool CheckSpellValidation(uint32 spellFamilyName, flag96 spelFalimyFlags, bool strict = true);
public:
int32 stats[STATS_TYPE_MAX];
private:
bool CanBeTriggeredByType(SpellInfo const* spellInfo, uint32 procFlags);
void CollectByItemStatType(uint32 itemStatType, int32 val);
bool SpecialSpellFilter(uint32 spellId);
bool SpecialEnchantFilter(uint32 enchantSpellId);
void HandleApplyAura(const SpellEffectInfo& effectInfo, float multiplier, bool canNextTrigger, uint32 triggerCooldown);
void HandleApplyAura(const SpellEffectInfo& effectInfo, float multiplier, bool canNextTrigger,
uint32 triggerCooldown);
int32 AverageValue(const SpellEffectInfo& effectInfo);
private:
CollectorType type_;
uint32 cls_;

View File

@@ -14,6 +14,8 @@
#include "PlayerbotAI.h"
#include "PlayerbotFactory.h"
#include "SharedDefines.h"
#include "SpellAuraDefines.h"
#include "SpellMgr.h"
#include "StatsCollector.h"
#include "Unit.h"
@@ -23,15 +25,16 @@ StatsWeightCalculator::StatsWeightCalculator(Player* player) : player_(player)
type_ = CollectorType::SPELL_HEAL;
else if (PlayerbotAI::IsCaster(player))
type_ = CollectorType::SPELL_DMG;
else if (PlayerbotAI::IsTank(player))
type_ = CollectorType::MELEE_TANK;
else if (PlayerbotAI::IsMelee(player))
type_ = CollectorType::MELEE;
type_ = CollectorType::MELEE_DMG;
else
type_ = CollectorType::RANGED;
cls = player->getClass();
tab = AiFactory::GetPlayerSpecTab(player);
collector_ = std::make_unique<StatsCollector>(type_, cls);
if (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_UNHOLY)
hitOverflowType_ = CollectorType::SPELL;
else if (cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ENHANCEMENT)
@@ -79,7 +82,7 @@ float StatsWeightCalculator::CalculateItem(uint32 itemId)
CalculateItemTypePenalty(proto);
if (enable_item_set_bonus_)
CalculateItemSetBonus(player_, proto);
CalculateItemSetMod(player_, proto);
CalculateSocketBonus(player_, proto);
@@ -123,8 +126,10 @@ void StatsWeightCalculator::GenerateWeights(Player* player)
void StatsWeightCalculator::GenerateBasicWeights(Player* player)
{
// Basic weights
stats_weights_[STATS_TYPE_STAMINA] += 0.01f;
stats_weights_[STATS_TYPE_STAMINA] += 0.1f;
stats_weights_[STATS_TYPE_ARMOR] += 0.001f;
stats_weights_[STATS_TYPE_BONUS] += 1.0f;
stats_weights_[STATS_TYPE_MELEE_DPS] += 0.01f;
if (cls == CLASS_HUNTER && (tab == HUNTER_TAB_BEASTMASTER || tab == HUNTER_TAB_SURVIVAL))
{
@@ -259,8 +264,8 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
stats_weights_[STATS_TYPE_MELEE_DPS] += 8.5f;
}
else if (cls == CLASS_WARLOCK || (cls == CLASS_MAGE && tab != MAGE_TAB_FIRE) ||
(cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW) || // shadow
(cls == CLASS_DRUID && tab == DRUID_TAB_BALANCE)) // balance
(cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW) || // shadow
(cls == CLASS_DRUID && tab == DRUID_TAB_BALANCE)) // balance
{
stats_weights_[STATS_TYPE_INTELLECT] += 0.3f;
stats_weights_[STATS_TYPE_SPIRIT] += 0.6f;
@@ -289,16 +294,24 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
stats_weights_[STATS_TYPE_HASTE] += 1.0f;
}
else if ((cls == CLASS_PALADIN && tab == PALADIN_TAB_HOLY) || // holy
(cls == CLASS_PRIEST && tab != PRIEST_TAB_SHADOW) || // discipline / holy
(cls == CLASS_SHAMAN && tab == SHAMAN_TAB_RESTORATION) || // heal
(cls == CLASS_SHAMAN && tab == SHAMAN_TAB_RESTORATION)) // heal
{
stats_weights_[STATS_TYPE_INTELLECT] += 0.9f;
stats_weights_[STATS_TYPE_SPIRIT] += 0.15f;
stats_weights_[STATS_TYPE_HEAL_POWER] += 1.0f;
stats_weights_[STATS_TYPE_MANA_REGENERATION] += 0.9f;
stats_weights_[STATS_TYPE_CRIT] += 0.6f;
stats_weights_[STATS_TYPE_HASTE] += 0.8f;
}
else if ((cls == CLASS_PRIEST && tab != PRIEST_TAB_SHADOW) || // discipline / holy
(cls == CLASS_DRUID && tab == DRUID_TAB_RESTORATION))
{
stats_weights_[STATS_TYPE_INTELLECT] += 0.8f;
stats_weights_[STATS_TYPE_SPIRIT] += 0.8f;
stats_weights_[STATS_TYPE_SPIRIT] += 0.6f;
stats_weights_[STATS_TYPE_HEAL_POWER] += 1.0f;
stats_weights_[STATS_TYPE_MANA_REGENERATION] += 1.2f;
stats_weights_[STATS_TYPE_CRIT] += 0.7f;
stats_weights_[STATS_TYPE_HASTE] += 1.0f;
stats_weights_[STATS_TYPE_MANA_REGENERATION] += 0.9f;
stats_weights_[STATS_TYPE_CRIT] += 0.6f;
stats_weights_[STATS_TYPE_HASTE] += 0.8f;
stats_weights_[STATS_TYPE_RANGED_DPS] += 1.0f;
}
else if ((cls == CLASS_WARRIOR && tab == WARRIOR_TAB_PROTECTION) ||
@@ -311,7 +324,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
stats_weights_[STATS_TYPE_DEFENSE] += 2.5f;
stats_weights_[STATS_TYPE_PARRY] += 2.0f;
stats_weights_[STATS_TYPE_DODGE] += 2.0f;
stats_weights_[STATS_TYPE_RESILIENCE] += 2.0f;
// stats_weights_[STATS_TYPE_RESILIENCE] += 2.0f;
stats_weights_[STATS_TYPE_BLOCK_RATING] += 1.0f;
stats_weights_[STATS_TYPE_BLOCK_VALUE] += 0.5f;
stats_weights_[STATS_TYPE_ARMOR] += 0.15f;
@@ -330,7 +343,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
stats_weights_[STATS_TYPE_DEFENSE] += 3.5f;
stats_weights_[STATS_TYPE_PARRY] += 2.0f;
stats_weights_[STATS_TYPE_DODGE] += 2.0f;
stats_weights_[STATS_TYPE_RESILIENCE] += 2.0f;
// stats_weights_[STATS_TYPE_RESILIENCE] += 2.0f;
stats_weights_[STATS_TYPE_ARMOR] += 0.15f;
stats_weights_[STATS_TYPE_HIT] += 2.0f;
stats_weights_[STATS_TYPE_CRIT] += 0.5f;
@@ -347,7 +360,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
stats_weights_[STATS_TYPE_ATTACK_POWER] += 1.0f;
stats_weights_[STATS_TYPE_DEFENSE] += 0.3f;
stats_weights_[STATS_TYPE_DODGE] += 0.7f;
stats_weights_[STATS_TYPE_RESILIENCE] += 1.0f;
// stats_weights_[STATS_TYPE_RESILIENCE] += 1.0f;
stats_weights_[STATS_TYPE_ARMOR] += 0.15f;
stats_weights_[STATS_TYPE_HIT] += 3.0f;
stats_weights_[STATS_TYPE_CRIT] += 1.3f;
@@ -380,7 +393,7 @@ void StatsWeightCalculator::GenerateAdditionalWeights(Player* player)
}
}
void StatsWeightCalculator::CalculateItemSetBonus(Player* player, ItemTemplate const* proto)
void StatsWeightCalculator::CalculateItemSetMod(Player* player, ItemTemplate const* proto)
{
uint32 itemSet = proto->ItemSet;
if (!itemSet)
@@ -466,7 +479,7 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
// enhancement, rogue, ice dk, unholy dk, shield tank, fury warrior without titan's grip but with duel wield
if (isDoubleHand &&
((cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ENHANCEMENT && player_->CanDualWield()) ||
(cls == CLASS_ROGUE) || (cls == CLASS_DEATH_KNIGHT && tab != DEATHKNIGHT_TAB_BLOOD) ||
(cls == CLASS_ROGUE) || (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_FROST) ||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && !player_->CanTitanGrip() && player_->CanDualWield()) ||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_PROTECTION) ||
(cls == CLASS_PALADIN && tab == PALADIN_TAB_PROTECTION)))
@@ -486,21 +499,20 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
weight_ *= 0.1;
}
// fury with titan's grip
if ((!isDoubleHand || proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF) &&
if ((!isDoubleHand || proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM ||
proto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF) &&
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && player_->CanTitanGrip()))
{
weight_ *= 0.1;
}
}
if (proto->Class == ITEM_CLASS_WEAPON)
{
if (cls == CLASS_HUNTER && proto->SubClass == ITEM_SUBCLASS_WEAPON_THROWN)
{
weight_ *= 0.1;
}
if (cls == CLASS_ROGUE && tab == ROGUE_TAB_ASSASSINATION && proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER)
if (cls == CLASS_ROGUE && (tab == ROGUE_TAB_ASSASSINATION || tab == ROGUE_TAB_SUBTLETY) &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER)
{
weight_ *= 0.1;
weight_ *= 0.5;
}
if (cls == CLASS_ROGUE && player_->HasAura(13964) &&
(proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE))
@@ -512,6 +524,10 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
{
weight_ *= 1.1;
}
if (cls == CLASS_DEATH_KNIGHT && player_->HasAura(50138) && !isDoubleHand)
{
weight_ *= 1.3;
}
bool slowDelay = proto->Delay > 2500;
if (cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ENHANCEMENT && slowDelay)
weight_ *= 1.1;
@@ -540,19 +556,24 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player)
{
float hit_current, hit_overflow;
float validPoints;
// m_modMeleeHitChance = (float)GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
// m_modMeleeHitChance += GetRatingBonusValue(CR_HIT_MELEE);
if (hitOverflowType_ == CollectorType::SPELL)
if (hitOverflowType_ & CollectorType::SPELL)
{
hit_current = player->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE);
hit_current += player->GetTotalAuraModifier(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT); // suppression (18176)
hit_current += player->GetRatingBonusValue(CR_HIT_SPELL);
if (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW && player->HasAura(15835)) // Shadow Focus
hit_current += 3;
if (cls == CLASS_MAGE && tab == MAGE_TAB_ARCANE && player->HasAura(12840)) // Arcane Focus
hit_current += 3;
hit_overflow = SPELL_HIT_OVERFLOW;
if (hit_overflow > hit_current)
validPoints = (hit_overflow - hit_current) / player->GetRatingMultiplier(CR_HIT_SPELL);
else
validPoints = 0;
}
else if (hitOverflowType_ == CollectorType::MELEE)
else if (hitOverflowType_ & CollectorType::MELEE)
{
hit_current = player->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
hit_current += player->GetRatingBonusValue(CR_HIT_MELEE);
@@ -576,7 +597,7 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player)
}
{
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
{
float expertise_current, expertise_overflow;
expertise_current = player->GetUInt32Value(PLAYER_EXPERTISE);
@@ -589,12 +610,13 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player)
else
validPoints = 0;
collector_->stats[STATS_TYPE_EXPERTISE] = std::min(collector_->stats[STATS_TYPE_EXPERTISE], (int)validPoints);
collector_->stats[STATS_TYPE_EXPERTISE] =
std::min(collector_->stats[STATS_TYPE_EXPERTISE], (int)validPoints);
}
}
{
if (type_ == CollectorType::MELEE)
if (type_ & CollectorType::MELEE)
{
float defense_current, defense_overflow;
defense_current = player->GetRatingBonusValue(CR_DEFENSE_SKILL);
@@ -611,7 +633,7 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player)
}
{
if (type_ == CollectorType::MELEE || type_ == CollectorType::RANGED)
if (type_ & (CollectorType::MELEE | CollectorType::RANGED))
{
float armor_penetration_current, armor_penetration_overflow;
armor_penetration_current = player->GetRatingBonusValue(CR_ARMOR_PENETRATION);
@@ -619,11 +641,13 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player)
float validPoints;
if (armor_penetration_overflow > armor_penetration_current)
validPoints = (armor_penetration_overflow - armor_penetration_current) / player->GetRatingMultiplier(CR_ARMOR_PENETRATION);
validPoints = (armor_penetration_overflow - armor_penetration_current) /
player->GetRatingMultiplier(CR_ARMOR_PENETRATION);
else
validPoints = 0;
collector_->stats[STATS_TYPE_ARMOR_PENETRATION] = std::min(collector_->stats[STATS_TYPE_ARMOR_PENETRATION], (int)validPoints);
collector_->stats[STATS_TYPE_ARMOR_PENETRATION] =
std::min(collector_->stats[STATS_TYPE_ARMOR_PENETRATION], (int)validPoints);
}
}
}
@@ -631,9 +655,9 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player)
void StatsWeightCalculator::ApplyWeightFinetune(Player* player)
{
{
if (type_ == CollectorType::MELEE || type_ == CollectorType::RANGED)
if (type_ & (CollectorType::MELEE | CollectorType::RANGED))
{
float armor_penetration_current, armor_penetration_overflow;
float armor_penetration_current/*, armor_penetration_overflow*/; //not used, line marked for removal.
armor_penetration_current = player->GetRatingBonusValue(CR_ARMOR_PENETRATION);
if (armor_penetration_current > 50)
stats_weights_[STATS_TYPE_ARMOR_PENETRATION] *= 1.2f;

View File

@@ -40,7 +40,7 @@ private:
void GenerateBasicWeights(Player* player);
void GenerateAdditionalWeights(Player* player);
void CalculateItemSetBonus(Player* player, ItemTemplate const* proto);
void CalculateItemSetMod(Player* player, ItemTemplate const* proto);
void CalculateSocketBonus(Player* player, ItemTemplate const* proto);
void CalculateItemTypePenalty(ItemTemplate const* proto);

View File

@@ -16,7 +16,7 @@ uint8 BroadcastHelper::GetLocale()
return locale;
}
bool BroadcastHelper::BroadcastTest(PlayerbotAI* ai, Player* bot)
bool BroadcastHelper::BroadcastTest(PlayerbotAI* ai, Player* /* bot */)
{
//return something to ignore the logic
return false;
@@ -609,7 +609,7 @@ bool BroadcastHelper::BroadcastLevelup(PlayerbotAI* ai, Player* bot)
return false;
}
bool BroadcastHelper::BroadcastGuildMemberPromotion(PlayerbotAI* ai, Player* bot, Player* player)
bool BroadcastHelper::BroadcastGuildMemberPromotion(PlayerbotAI* ai, Player* /* bot */, Player* player)
{
if (!sPlayerbotAIConfig->enableBroadcasts)
return false;
@@ -627,7 +627,7 @@ bool BroadcastHelper::BroadcastGuildMemberPromotion(PlayerbotAI* ai, Player* bot
return false;
}
bool BroadcastHelper::BroadcastGuildMemberDemotion(PlayerbotAI* ai, Player* bot, Player* player)
bool BroadcastHelper::BroadcastGuildMemberDemotion(PlayerbotAI* ai, Player* /* bot */, Player* player)
{
if (urand(1, sPlayerbotAIConfig->broadcastChanceMaxValue) <= sPlayerbotAIConfig->broadcastChanceGuildManagement)
{
@@ -643,7 +643,7 @@ bool BroadcastHelper::BroadcastGuildMemberDemotion(PlayerbotAI* ai, Player* bot,
return false;
}
bool BroadcastHelper::BroadcastGuildGroupOrRaidInvite(PlayerbotAI* ai, Player* bot, Player* player, Group* group)
bool BroadcastHelper::BroadcastGuildGroupOrRaidInvite(PlayerbotAI* ai, Player* /* bot */, Player* player, Group* group)
{
if (!sPlayerbotAIConfig->enableBroadcasts)
return false;

View File

@@ -156,7 +156,7 @@ public:
return message;
bool found = false;
bool isRti = false;
//bool isRti = false; //not used, shadowed by the next declaration, line marked for removal.
for (std::vector<std::string>::iterator i = rtis.begin(); i != rtis.end(); i++)
{
std::string const rti = *i;
@@ -213,7 +213,7 @@ public:
Player* bot = botAI->GetBot();
bool found = false;
bool isClass = false;
//bool isClass = false; //not used, shadowed by the next declaration, line marked for removal.
for (std::map<std::string, uint8>::iterator i = classNames.begin(); i != classNames.end(); i++)
{
bool isClass = message.find(i->first) == 0;

View File

@@ -6,6 +6,9 @@
#include "ChatHelper.h"
#include "AiFactory.h"
#include "Common.h"
#include "ItemTemplate.h"
#include "ObjectMgr.h"
#include "Playerbots.h"
#include "SpellInfo.h"
@@ -310,7 +313,16 @@ std::string const ChatHelper::FormatQuest(Quest const* quest)
}
std::ostringstream out;
out << "|cFFFFFF00|Hquest:" << quest->GetQuestId() << ':' << quest->GetQuestLevel() << "|h[" << quest->GetTitle() << "]|h|r";
QuestLocale const* locale = sObjectMgr->GetQuestLocale(quest->GetQuestId());
std::string questTitle;
if (locale && locale->Title.size() > sWorld->GetDefaultDbcLocale())
questTitle = locale->Title[sWorld->GetDefaultDbcLocale()];
if (questTitle.empty())
questTitle = quest->GetTitle();
out << "|cFFFFFF00|Hquest:" << quest->GetQuestId() << ':' << quest->GetQuestLevel() << "|h[" << questTitle << "]|h|r";
return out.str();
}
@@ -318,7 +330,7 @@ std::string const ChatHelper::FormatGameobject(GameObject* go)
{
std::ostringstream out;
out << "|cFFFFFF00|Hfound:" << go->GetGUID().GetRawValue() << ":" << go->GetEntry() << ":"
<< "|h[" << go->GetNameForLocaleIdx(LOCALE_enUS) << "]|h|r";
<< "|h[" << go->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()) << "]|h|r";
return out.str();
}
@@ -327,8 +339,8 @@ std::string const ChatHelper::FormatWorldobject(WorldObject* wo)
std::ostringstream out;
out << "|cFFFFFF00|Hfound:" << wo->GetGUID().GetRawValue() << ":" << wo->GetEntry() << ":"
<< "|h[";
out << (wo->ToGameObject() ? ((GameObject*)wo)->GetNameForLocaleIdx(LOCALE_enUS)
: wo->GetNameForLocaleIdx(LOCALE_enUS))
out << (wo->ToGameObject() ? ((GameObject*)wo)->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale())
: wo->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()))
<< "]|h|r";
return out.str();
}
@@ -361,7 +373,9 @@ std::string const ChatHelper::FormatWorldEntry(int32 entry)
std::string const ChatHelper::FormatSpell(SpellInfo const* spellInfo)
{
std::ostringstream out;
out << "|cffffffff|Hspell:" << spellInfo->Id << "|h[" << spellInfo->SpellName[LOCALE_enUS] << "]|h|r";
std::string spellName = spellInfo->SpellName[sWorld->GetDefaultDbcLocale()] ?
spellInfo->SpellName[sWorld->GetDefaultDbcLocale()] : spellInfo->SpellName[LOCALE_enUS];
out << "|cffffffff|Hspell:" << spellInfo->Id << "|h[" << spellName << "]|h|r";
return out.str();
}
@@ -370,11 +384,18 @@ std::string const ChatHelper::FormatItem(ItemTemplate const* proto, uint32 count
char color[32];
sprintf(color, "%x", ItemQualityColors[proto->Quality]);
// const std::string &name = sObjectMgr->GetItemLocale(proto->ItemId)->Name[LOCALE_enUS];
std::string itemName;
const ItemLocale* locale = sObjectMgr->GetItemLocale(proto->ItemId);
if (locale && locale->Name.size() > sWorld->GetDefaultDbcLocale())
itemName = locale->Name[sWorld->GetDefaultDbcLocale()];
if (itemName.empty())
itemName = proto->Name1;
std::ostringstream out;
out << "|c" << color << "|Hitem:" << proto->ItemId << ":0:0:0:0:0:0:0"
<< "|h[" << proto->Name1 << "]|h|r";
<< "|h[" << itemName << "]|h|r";
if (count > 1)
out << "x" << count;
@@ -462,7 +483,7 @@ GuidVector ChatHelper::parseGameobjects(std::string const text)
break;
std::string const entryC = text.substr(pos, endPos - pos); // get std::string const within window i.e entry
uint32 entry = atol(entryC.c_str()); // convert ascii to float
//uint32 entry = atol(entryC.c_str()); // convert ascii to float
ObjectGuid lootCurrent = ObjectGuid(guid);

View File

@@ -18,7 +18,7 @@ class FleePoint
{
public:
FleePoint(PlayerbotAI* botAI, float x, float y, float z)
: botAI(botAI), sumDistance(0.0f), minDistance(0.0f), x(x), y(y), z(z)
: x(x), y(y), z(z), sumDistance(0.0f), minDistance(0.0f), botAI(botAI)
{
}

View File

@@ -168,7 +168,7 @@ public:
bool Apply(ItemTemplate const* proto) override
{
uint32* tradeSkills = PlayerbotFactory::tradeSkills;
//uint32* tradeSkills = PlayerbotFactory::tradeSkills;
for (uint32 i = 0; i < 13; ++i)
{
@@ -546,7 +546,7 @@ bool GuildTaskMgr::IsGuildTaskItem(uint32 itemId, uint32 guildId)
}
std::map<uint32, uint32> GuildTaskMgr::GetTaskValues(uint32 owner, std::string const type,
uint32* validIn /* = nullptr */)
[[maybe_unused]] uint32* validIn /* = nullptr */)
{
std::map<uint32, uint32> results;
@@ -571,10 +571,10 @@ std::map<uint32, uint32> GuildTaskMgr::GetTaskValues(uint32 owner, std::string c
} while (result->NextRow());
}
return std::move(results);
return results;
}
uint32 GuildTaskMgr::GetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32* validIn /* = nullptr */)
uint32 GuildTaskMgr::GetTaskValue(uint32 owner, uint32 guildId, std::string const type, [[maybe_unused]] uint32* validIn /* = nullptr */)
{
uint32 value = 0;
@@ -622,7 +622,7 @@ uint32 GuildTaskMgr::SetTaskValue(uint32 owner, uint32 guildId, std::string cons
return value;
}
bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* handler, char const* args)
bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* /* handler */, char const* args)
{
if (!sPlayerbotAIConfig->guildTaskEnabled)
{

View File

@@ -9,7 +9,7 @@
#include "Playerbots.h"
#include "Unit.h"
#define MAX_LOOT_OBJECT_COUNT 10
#define MAX_LOOT_OBJECT_COUNT 200
LootTarget::LootTarget(ObjectGuid guid) : guid(guid), asOfTime(time(nullptr)) {}
@@ -81,7 +81,8 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
GameObject* go = botAI->GetGameObject(lootGUID);
if (go && go->isSpawned() && go->GetGoState() == GO_STATE_READY)
{
bool isQuestItemOnly = false;
bool onlyHasQuestItems = true;
bool hasAnyQuestItems = false;
GameObjectQuestItemList const* items = sObjectMgr->GetGameObjectQuestItemList(go->GetEntry());
for (int i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; i++)
@@ -89,19 +90,88 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
if (!items || i >= items->size())
break;
auto itemId = uint32((*items)[i]);
uint32 itemId = uint32((*items)[i]);
if (!itemId)
continue;
hasAnyQuestItems = true;
if (IsNeededForQuest(bot, itemId))
{
this->guid = lootGUID;
return;
}
isQuestItemOnly |= itemId > 0;
const ItemTemplate* proto = sObjectMgr->GetItemTemplate(itemId);
if (!proto)
continue;
if (proto->Class != ITEM_CLASS_QUEST)
{
onlyHasQuestItems = false;
}
}
if (isQuestItemOnly)
// Retrieve the correct loot table entry
uint32 lootEntry = go->GetGOInfo()->GetLootId();
if (lootEntry == 0)
return;
// Check the main loot template
if (const LootTemplate* lootTemplate = LootTemplates_Gameobject.GetLootFor(lootEntry))
{
Loot loot;
lootTemplate->Process(loot, LootTemplates_Gameobject, 1, bot);
for (const LootItem& item : loot.items)
{
uint32 itemId = item.itemid;
if (!itemId)
continue;
const ItemTemplate* proto = sObjectMgr->GetItemTemplate(itemId);
if (!proto)
continue;
if (proto->Class != ITEM_CLASS_QUEST)
{
onlyHasQuestItems = false;
break;
}
// If this item references another loot table, process it
if (const LootTemplate* refLootTemplate = LootTemplates_Reference.GetLootFor(itemId))
{
Loot refLoot;
refLootTemplate->Process(refLoot, LootTemplates_Reference, 1, bot);
for (const LootItem& refItem : refLoot.items)
{
uint32 refItemId = refItem.itemid;
if (!refItemId)
continue;
const ItemTemplate* refProto = sObjectMgr->GetItemTemplate(refItemId);
if (!refProto)
continue;
if (refProto->Class != ITEM_CLASS_QUEST)
{
onlyHasQuestItems = false;
break;
}
}
}
}
}
// If gameobject has only quest items that bot doesnt need, skip it.
if (hasAnyQuestItems && onlyHasQuestItems)
return;
// Otherwise, loot it.
guid = lootGUID;
uint32 goId = go->GetEntry();
uint32 lockId = go->GetGOInfo()->GetLockId();
LockEntry const* lockInfo = sLockStore.LookupEntry(lockId);
@@ -119,6 +189,7 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
guid = lootGUID;
}
break;
case LOCK_KEY_SKILL:
if (goId == 13891 || goId == 19535) // Serpentbloom
{
@@ -131,6 +202,7 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
guid = lootGUID;
}
break;
case LOCK_KEY_NONE:
guid = lootGUID;
break;
@@ -200,7 +272,11 @@ LootObject::LootObject(LootObject const& other)
bool LootObject::IsLootPossible(Player* bot)
{
if (IsEmpty() || !GetWorldObject(bot))
if (IsEmpty() || !bot)
return false;
WorldObject* worldObj = GetWorldObject(bot); // Store result to avoid multiple calls
if (!worldObj)
return false;
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
@@ -211,7 +287,7 @@ bool LootObject::IsLootPossible(Player* bot)
if (reqItem && !bot->HasItemCount(reqItem, 1))
return false;
if (abs(GetWorldObject(bot)->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE)
if (abs(worldObj->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE -2.0f)
return false;
Creature* creature = botAI->GetCreature(guid);
@@ -236,25 +312,32 @@ bool LootObject::IsLootPossible(Player* bot)
uint32 skillValue = uint32(bot->GetSkillValue(skillId));
if (reqSkillValue > skillValue)
return false;
if (skillId == SKILL_MINING && !bot->HasItemCount(756, 1) &&
!bot->HasItemCount(778, 1) &&
!bot->HasItemCount(1819, 1) &&
!bot->HasItemCount(1893, 1) &&
!bot->HasItemCount(1959, 1) &&
!bot->HasItemCount(2901, 1) &&
!bot->HasItemCount(9465, 1) &&
!bot->HasItemCount(20723, 1) &&
!bot->HasItemCount(40772, 1) &&
!bot->HasItemCount(40892, 1) &&
!bot->HasItemCount(40893, 1) )
if (skillId == SKILL_SKINNING && !bot->HasItemCount(7005, 1) &&
!bot->HasItemCount(40772, 1) &&
!bot->HasItemCount(40893, 1) &&
!bot->HasItemCount(12709, 1) &&
!bot->HasItemCount(19901, 1) )
return false;
if (skillId == SKILL_MINING &&
!bot->HasItemCount(756, 1) &&
!bot->HasItemCount(778, 1) &&
!bot->HasItemCount(1819, 1) &&
!bot->HasItemCount(1893, 1) &&
!bot->HasItemCount(1959, 1) &&
!bot->HasItemCount(2901, 1) &&
!bot->HasItemCount(9465, 1) &&
!bot->HasItemCount(20723, 1) &&
!bot->HasItemCount(40772, 1) &&
!bot->HasItemCount(40892, 1) &&
!bot->HasItemCount(40893, 1))
{
return false; // Bot is missing a mining pick
}
if (skillId == SKILL_SKINNING &&
!bot->HasItemCount(7005, 1) &&
!bot->HasItemCount(40772, 1) &&
!bot->HasItemCount(40893, 1) &&
!bot->HasItemCount(12709, 1) &&
!bot->HasItemCount(19901, 1))
{
return false; // Bot is missing a skinning knife
}
return true;
}
@@ -297,7 +380,6 @@ LootObject LootObjectStack::GetLoot(float maxDistance)
std::vector<LootObject> ordered = OrderByDistance(maxDistance);
return ordered.empty() ? LootObject() : *ordered.begin();
}
std::vector<LootObject> LootObjectStack::OrderByDistance(float maxDistance)
{
availableLoot.shrink(time(nullptr) - 30);
@@ -308,17 +390,23 @@ std::vector<LootObject> LootObjectStack::OrderByDistance(float maxDistance)
{
ObjectGuid guid = i->guid;
LootObject lootObject(bot, guid);
if (!lootObject.IsLootPossible(bot))
if (!lootObject.IsLootPossible(bot)) // Ensure loot object is valid
continue;
float distance = bot->GetDistance(lootObject.GetWorldObject(bot));
WorldObject* worldObj = lootObject.GetWorldObject(bot);
if (!worldObj) // Prevent null pointer dereference
{
continue;
}
float distance = bot->GetDistance(worldObj);
if (!maxDistance || distance <= maxDistance)
sortedMap[distance] = lootObject;
}
std::vector<LootObject> result;
for (std::map<float, LootObject>::iterator i = sortedMap.begin(); i != sortedMap.end(); i++)
result.push_back(i->second);
for (auto& [_, lootObject] : sortedMap)
result.push_back(lootObject);
return result;
}

View File

@@ -6,6 +6,7 @@
#include "PlayerbotTextMgr.h"
#include "Playerbots.h"
#include "WorldSessionMgr.h"
void PlayerbotTextMgr::replaceAll(std::string& str, const std::string& from, const std::string& to)
{
@@ -184,7 +185,7 @@ uint32 PlayerbotTextMgr::GetLocalePriority()
uint32 topLocale = 0;
// if no real players online, reset top locale
if (!sWorld->GetActiveSessionCount())
if (!sWorldSessionMgr->GetActiveSessionCount())
{
ResetLocalePriority();
return 0;

View File

@@ -260,7 +260,7 @@ void TalentSpec::ReadTalents(Player* bot)
// Set the talent ranks to the ranks of the link.
void TalentSpec::ReadTalents(std::string const link)
{
uint32 rank = 0;
//uint32 rank = 0; //not used, line marked for removal.
uint32 pos = 0;
uint32 tab = 0;
std::string chr;
@@ -397,7 +397,7 @@ uint32 TalentSpec::highestTree()
std::string const TalentSpec::FormatSpec(Player* bot)
{
uint8 cls = bot->getClass();
// uint8 cls = bot->getClass(); //not used, (used in lined 403), line marked for removal.
std::ostringstream out;
// out << chathelper:: specs[cls][highestTree()] << " (";
@@ -468,7 +468,7 @@ bool TalentSpec::isEarlierVersionOf(TalentSpec& newSpec)
// Modifies current talents towards new talents up to a maxium of points.
void TalentSpec::ShiftTalents(TalentSpec* currentSpec, uint32 level)
{
uint32 currentPoints = currentSpec->GetTalentPoints();
//uint32 currentPoints = currentSpec->GetTalentPoints(); //not used, line marked for removal.
if (points >= LeveltoPoints(level)) // We have no more points to spend. Better reset and crop
{
CropTalents(level);

View File

@@ -22,12 +22,26 @@
WorldPosition::WorldPosition(std::string const str)
{
std::stringstream out(str);
out >> this->m_mapId;
out >> this->m_positionX;
out >> this->m_positionY;
out >> this->m_positionZ;
out >> this->m_orientation;
std::vector<std::string> tokens = split(str, '|');
if (tokens.size() == 5)
{
try
{
m_mapId = std::stoi(tokens[0]);
m_positionX = std::stof(tokens[1]);
m_positionY = std::stof(tokens[2]);
m_positionZ = std::stof(tokens[3]);
m_orientation = std::stof(tokens[4]);
}
catch (const std::exception&)
{
m_mapId = 0;
m_positionX = 0.0f;
m_positionY = 0.0f;
m_positionZ = 0.0f;
m_orientation = 0.0f;
}
}
}
WorldPosition::WorldPosition(uint32 mapId, const Position& pos)
@@ -361,13 +375,25 @@ std::string const WorldPosition::print()
std::string const WorldPosition::to_string()
{
std::stringstream out;
out << GetMapId();
out << GetPositionX();
out << GetPositionY();
out << GetPositionZ();
out << GetOrientation();
out << m_mapId << '|';
out << m_positionX << '|';
out << m_positionY << '|';
out << m_positionZ << '|';
out << m_orientation;
return out.str();
};
}
std::vector<std::string> WorldPosition::split(const std::string& s, char delimiter)
{
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(s);
while (std::getline(tokenStream, token, delimiter))
{
tokens.push_back(token);
}
return tokens;
}
void WorldPosition::printWKT(std::vector<WorldPosition> points, std::ostringstream& out, uint32 dim, bool loop)
{
@@ -618,7 +644,7 @@ void WorldPosition::loadMapAndVMap(uint32 mapId, uint8 x, uint8 y)
{
// load VMAPs for current map/grid...
const MapEntry* i_mapEntry = sMapStore.LookupEntry(mapId);
const char* mapName = i_mapEntry ? i_mapEntry->name[sWorld->GetDefaultDbcLocale()] : "UNNAMEDMAP\x0";
//const char* mapName = i_mapEntry ? i_mapEntry->name[sWorld->GetDefaultDbcLocale()] : "UNNAMEDMAP\x0"; //not used, (usage are commented out below), line marked for removal.
int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapMgr()->loadMap(
(sWorld->GetDataPath() + "vmaps").c_str(), mapId, x, y);
@@ -1077,7 +1103,7 @@ bool QuestRelationTravelDestination::isActive(Player* bot)
if (!bot->GetMap()->GetEntry()->IsWorldMap() || !bot->CanTakeQuest(questTemplate, false))
return false;
uint32 dialogStatus = sTravelMgr->getDialogStatus(bot, entry, questTemplate);
//uint32 dialogStatus = sTravelMgr->getDialogStatus(bot, entry, questTemplate); //not used, shadowed by the next declaration, line marked for removal.
if (AI_VALUE(bool, "can fight equal"))
{

View File

@@ -131,6 +131,7 @@ public:
std::string const print();
std::string const to_string();
std::vector<std::string> split(const std::string& s, char delimiter);
void printWKT(std::vector<WorldPosition> points, std::ostringstream& out, uint32 dim = 0, bool loop = false);
void printWKT(std::ostringstream& out) { printWKT({*this}, out); }

View File

@@ -594,7 +594,7 @@ bool TravelNode::isEqual(TravelNode* compareNode)
void TravelNode::print([[maybe_unused]] bool printFailed)
{
WorldPosition* startPosition = getPosition();
// WorldPosition* startPosition = getPosition(); //not used, line marked for removal.
uint32 mapSize = getNodeMap(true).size();
@@ -1167,9 +1167,9 @@ std::vector<TravelNode*> TravelNodeMap::getNodes(WorldPosition pos, float range)
TravelNode* TravelNodeMap::getNode(WorldPosition pos, [[maybe_unused]] std::vector<WorldPosition>& ppath, Unit* bot,
float range)
{
float x = pos.getX();
float y = pos.getY();
float z = pos.getZ();
//float x = pos.getX(); //not used, line marked for removal.
//float y = pos.getY(); //not used, line marked for removal.
//float z = pos.getZ(); //not used, line marked for removal.
if (bot && !bot->GetMap())
return nullptr;
@@ -1348,6 +1348,9 @@ TravelNodeRoute TravelNodeMap::getRoute(WorldPosition startPos, WorldPosition en
std::vector<WorldPosition> newStartPath;
std::vector<TravelNode*> startNodes = m_nodes, endNodes = m_nodes;
if(!startNodes.size() || !endNodes.size())
return TravelNodeRoute();
// Partial sort to get the closest 5 nodes at the begin of the array.
std::partial_sort(startNodes.begin(), startNodes.begin() + 5, startNodes.end(),
[startPos](TravelNode* i, TravelNode* j) { return i->fDist(startPos) < j->fDist(startPos); });
@@ -1495,7 +1498,7 @@ TravelNode* TravelNodeMap::addZoneLinkNode(TravelNode* startNode)
{
for (auto& path : *startNode->getPaths())
{
TravelNode* endNode = path.first;
//TravelNode* endNode = path.first; //not used, line marked for removal.
std::string zoneName = startNode->getPosition()->getAreaName(true, true);
for (auto& pos : path.second.getPath())
@@ -1638,7 +1641,7 @@ void TravelNodeMap::generateNpcNodes()
else if (cInfo->npcflag & UNIT_NPC_FLAG_SPIRITGUIDE)
nodeName += " spiritguide";
TravelNode* node = sTravelNodeMap->addNode(guidP, nodeName, true, true);
/*TravelNode* node = */ sTravelNodeMap->addNode(guidP, nodeName, true, true); //node not used, fragment marked for removal.
}
else if (cInfo->rank == 3)
{
@@ -1754,7 +1757,7 @@ void TravelNodeMap::generateAreaTriggerNodes()
else
nodeName = inPos.getAreaName(false) + " portal";
TravelNode* entryNode = sTravelNodeMap->getNode(outPos, nullptr, 20.0f); // Entry side, portal exit.
//TravelNode* entryNode = sTravelNodeMap->getNode(outPos, nullptr, 20.0f); // Entry side, portal exit. //not used, line marked for removal.
TravelNode* outNode = sTravelNodeMap->addNode(outPos, nodeName, true, true); // Exit size, portal exit.
@@ -1976,7 +1979,7 @@ void TravelNodeMap::generateZoneMeanNodes()
WorldPosition pos = WorldPosition(points, WP_MEAN_CENTROID);
TravelNode* node = sTravelNodeMap->addNode(pos, pos.getAreaName(), true, true, false);
/*TravelNode* node = */sTravelNodeMap->addNode(pos, pos.getAreaName(), true, true, false); //node not used, but addNode as side effect, fragment marked for removal.
}
}
@@ -2117,7 +2120,7 @@ void TravelNodeMap::removeUselessPaths()
if (path.second.getComplete() && startNode->hasLinkTo(path.first))
ASSERT(true);
}
uint32 it = 0, rem = 0;
uint32 it = 0/*, rem = 0*/; //rem not used in this scope, (shadowing) fragment marked for removal.
while (true)
{
uint32 rem = 0;
@@ -2207,7 +2210,7 @@ void TravelNodeMap::printMap()
std::vector<TravelNode*> anodes = getNodes();
uint32 nr = 0;
//uint32 nr = 0; //not used, line marked for removal.
for (auto& node : anodes)
{

View File

@@ -488,7 +488,7 @@ protected:
// node_name , action, prerequisite
#define ACTION_NODE_P(name, spell, pre) \
static ActionNode* name(PlayerbotAI* botAI) \
static ActionNode* name([[maybe_unused]] PlayerbotAI* botAI) \
{ \
return new ActionNode(spell, /*P*/ NextAction::array(0, new NextAction(pre), nullptr), /*A*/ nullptr, \
/*C*/ nullptr); \
@@ -496,7 +496,7 @@ protected:
// node_name , action, alternative
#define ACTION_NODE_A(name, spell, alt) \
static ActionNode* name(PlayerbotAI* botAI) \
static ActionNode* name([[maybe_unused]] PlayerbotAI* botAI) \
{ \
return new ActionNode(spell, /*P*/ nullptr, /*A*/ NextAction::array(0, new NextAction(alt), nullptr), \
/*C*/ nullptr); \
@@ -504,7 +504,7 @@ protected:
// node_name , action, continuer
#define ACTION_NODE_C(name, spell, con) \
static ActionNode* name(PlayerbotAI* botAI) \
static ActionNode* name([[maybe_unused]] PlayerbotAI* botAI) \
{ \
return new ActionNode(spell, /*P*/ nullptr, /*A*/ nullptr, \
/*C*/ NextAction::array(0, new NextAction(con), nullptr)); \

View File

@@ -9,8 +9,6 @@
#include "ChatActionContext.h"
#include "ChatTriggerContext.h"
#include "Playerbots.h"
#include "RaidIccActionContext.h"
#include "RaidIccTriggerContext.h"
#include "RaidUlduarTriggerContext.h"
#include "RaidUlduarActionContext.h"
#include "SharedValueContext.h"
@@ -19,18 +17,28 @@
#include "ValueContext.h"
#include "WorldPacketActionContext.h"
#include "WorldPacketTriggerContext.h"
#include "raids/RaidStrategyContext.h"
#include "raids/blackwinglair/RaidBwlActionContext.h"
#include "raids/blackwinglair/RaidBwlTriggerContext.h"
#include "raids/naxxramas/RaidNaxxActionContext.h"
#include "raids/naxxramas/RaidNaxxTriggerContext.h"
#include "raids/moltencore/RaidMcActionContext.h"
#include "raids/moltencore/RaidMcTriggerContext.h"
#include "raids/aq20/RaidAq20ActionContext.h"
#include "raids/aq20/RaidAq20TriggerContext.h"
#include "dungeons/DungeonStrategyContext.h"
#include "dungeons/wotlk/WotlkDungeonActionContext.h"
#include "dungeons/wotlk/WotlkDungeonTriggerContext.h"
#include "RaidStrategyContext.h"
#include "RaidBwlActionContext.h"
#include "RaidBwlTriggerContext.h"
#include "RaidNaxxActionContext.h"
#include "RaidNaxxTriggerContext.h"
#include "RaidIccActionContext.h"
#include "RaidIccTriggerContext.h"
#include "RaidOsActionContext.h"
#include "RaidOsTriggerContext.h"
#include "RaidEoEActionContext.h"
#include "RaidVoATriggerContext.h"
#include "RaidOnyxiaActionContext.h"
#include "RaidOnyxiaTriggerContext.h"
#include "RaidVoAActionContext.h"
#include "RaidEoETriggerContext.h"
#include "RaidMcActionContext.h"
#include "RaidMcTriggerContext.h"
#include "RaidAq20ActionContext.h"
#include "RaidAq20TriggerContext.h"
#include "DungeonStrategyContext.h"
#include "WotlkDungeonActionContext.h"
#include "WotlkDungeonTriggerContext.h"
AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
{
@@ -46,8 +54,12 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
actionContexts.Add(new WorldPacketActionContext());
actionContexts.Add(new RaidMcActionContext());
actionContexts.Add(new RaidBwlActionContext());
actionContexts.Add(new RaidOnyxiaActionContext());
actionContexts.Add(new RaidAq20ActionContext());
actionContexts.Add(new RaidNaxxActionContext());
actionContexts.Add(new RaidOsActionContext());
actionContexts.Add(new RaidEoEActionContext());
actionContexts.Add(new RaidVoAActionContext());
actionContexts.Add(new RaidUlduarActionContext());
actionContexts.Add(new RaidIccActionContext());
actionContexts.Add(new WotlkDungeonUKActionContext());
@@ -63,14 +75,19 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
actionContexts.Add(new WotlkDungeonUPActionContext());
actionContexts.Add(new WotlkDungeonCoSActionContext());
actionContexts.Add(new WotlkDungeonFoSActionContext());
actionContexts.Add(new WotlkDungeonToCActionContext());
triggerContexts.Add(new TriggerContext());
triggerContexts.Add(new ChatTriggerContext());
triggerContexts.Add(new WorldPacketTriggerContext());
triggerContexts.Add(new RaidMcTriggerContext());
triggerContexts.Add(new RaidBwlTriggerContext());
triggerContexts.Add(new RaidOnyxiaTriggerContext());
triggerContexts.Add(new RaidAq20TriggerContext());
triggerContexts.Add(new RaidNaxxTriggerContext());
triggerContexts.Add(new RaidOsTriggerContext());
triggerContexts.Add(new RaidEoETriggerContext());
triggerContexts.Add(new RaidVoATriggerContext());
triggerContexts.Add(new RaidUlduarTriggerContext());
triggerContexts.Add(new RaidIccTriggerContext());
triggerContexts.Add(new WotlkDungeonUKTriggerContext());
@@ -86,6 +103,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
triggerContexts.Add(new WotlkDungeonUPTriggerContext());
triggerContexts.Add(new WotlkDungeonCoSTriggerContext());
triggerContexts.Add(new WotlkDungeonFosTriggerContext());
triggerContexts.Add(new WotlkDungeonToCTriggerContext());
valueContexts.Add(new ValueContext());

View File

@@ -1,104 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "Queue.h"
#include "AiObjectContext.h"
#include "Log.h"
#include "PlayerbotAIConfig.h"
void Queue::Push(ActionBasket* action)
{
if (action)
{
for (std::list<ActionBasket*>::iterator iter = actions.begin(); iter != actions.end(); iter++)
{
ActionBasket* basket = *iter;
if (action->getAction()->getName() == basket->getAction()->getName())
{
if (basket->getRelevance() < action->getRelevance())
basket->setRelevance(action->getRelevance());
if (ActionNode* actionNode = action->getAction())
delete actionNode;
delete action;
return;
}
}
actions.push_back(action);
}
}
ActionNode* Queue::Pop()
{
float max = -1;
ActionBasket* selection = nullptr;
for (std::list<ActionBasket*>::iterator iter = actions.begin(); iter != actions.end(); iter++)
{
ActionBasket* basket = *iter;
if (basket->getRelevance() > max)
{
max = basket->getRelevance();
selection = basket;
}
}
if (selection != nullptr)
{
ActionNode* action = selection->getAction();
actions.remove(selection);
delete selection;
return action;
}
return nullptr;
}
ActionBasket* Queue::Peek()
{
float max = -1;
ActionBasket* selection = nullptr;
for (std::list<ActionBasket*>::iterator iter = actions.begin(); iter != actions.end(); iter++)
{
ActionBasket* basket = *iter;
if (basket->getRelevance() > max)
{
max = basket->getRelevance();
selection = basket;
}
}
return selection;
}
uint32 Queue::Size() { return actions.size(); }
void Queue::RemoveExpired()
{
std::list<ActionBasket*> expired;
for (std::list<ActionBasket*>::iterator iter = actions.begin(); iter != actions.end(); iter++)
{
ActionBasket* basket = *iter;
if (sPlayerbotAIConfig->expireActionTime && basket->isExpired(sPlayerbotAIConfig->expireActionTime))
expired.push_back(basket);
}
for (std::list<ActionBasket*>::iterator iter = expired.begin(); iter != expired.end(); iter++)
{
ActionBasket* basket = *iter;
actions.remove(basket);
if (ActionNode* action = basket->getAction())
{
delete action;
}
delete basket;
}
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_QUEUE_H
#define _PLAYERBOT_QUEUE_H
#include "Action.h"
#include "Common.h"
class Queue
{
public:
Queue(void) {}
~Queue(void) {}
void Push(ActionBasket* action);
ActionNode* Pop();
ActionBasket* Peek();
uint32 Size();
void RemoveExpired();
private:
std::list<ActionBasket*> actions;
};
#endif

View File

@@ -31,6 +31,7 @@
#include "MeleeCombatStrategy.h"
#include "MoveFromGroupStrategy.h"
#include "NamedObjectContext.h"
#include "NewRpgStrategy.h"
#include "NonCombatStrategy.h"
#include "PassiveStrategy.h"
#include "PullStrategy.h"
@@ -82,6 +83,7 @@ public:
creators["reveal"] = &StrategyContext::reveal;
creators["collision"] = &StrategyContext::collision;
creators["rpg"] = &StrategyContext::rpg;
creators["new rpg"] = &StrategyContext::new_rpg;
creators["travel"] = &StrategyContext::travel;
creators["explore"] = &StrategyContext::explore;
creators["map"] = &StrategyContext::map;
@@ -117,6 +119,7 @@ public:
creators["move random"] = &StrategyContext::move_random;
creators["formation"] = &StrategyContext::combat_formation;
creators["move from group"] = &StrategyContext::move_from_group;
creators["worldbuff"] = &StrategyContext::world_buff;
}
private:
@@ -152,6 +155,7 @@ private:
static Strategy* reveal(PlayerbotAI* botAI) { return new RevealStrategy(botAI); }
static Strategy* collision(PlayerbotAI* botAI) { return new CollisionStrategy(botAI); }
static Strategy* rpg(PlayerbotAI* botAI) { return new RpgStrategy(botAI); }
static Strategy* new_rpg(PlayerbotAI* botAI) { return new NewRpgStrategy(botAI); }
static Strategy* travel(PlayerbotAI* botAI) { return new TravelStrategy(botAI); }
static Strategy* explore(PlayerbotAI* botAI) { return new ExploreStrategy(botAI); }
static Strategy* map(PlayerbotAI* botAI) { return new MapStrategy(botAI); }
@@ -183,6 +187,7 @@ private:
static Strategy* move_random(PlayerbotAI* ai) { return new MoveRandomStrategy(ai); }
static Strategy* combat_formation(PlayerbotAI* ai) { return new CombatFormationStrategy(ai); }
static Strategy* move_from_group(PlayerbotAI* botAI) { return new MoveFromGroupStrategy(botAI); }
static Strategy* world_buff(PlayerbotAI* botAI) { return new WorldBuffStrategy(botAI); }
};
class MovementStrategyContext : public NamedObjectContext<Strategy>

View File

@@ -1,348 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "CheckMountStateAction.h"
#include "BattlegroundWS.h"
#include "Event.h"
#include "PlayerbotAI.h"
#include "PlayerbotAIConfig.h"
#include "Playerbots.h"
#include "ServerFacade.h"
#include "SpellAuraEffects.h"
bool CheckMountStateAction::Execute(Event event)
{
bool noattackers = !AI_VALUE2(bool, "combat", "self target") || !AI_VALUE(uint8, "attacker count");
bool enemy = AI_VALUE(Unit*, "enemy player target");
bool dps = AI_VALUE(Unit*, "dps target");
bool shouldDismount = false;
bool shouldMount = false;
if (Unit* currentTarget = AI_VALUE(Unit*, "current target"))
{
float dismount_distance;
float mount_distance;
if (PlayerbotAI::IsMelee(bot))
{
dismount_distance = sPlayerbotAIConfig->meleeDistance + 2.0f;
mount_distance = sPlayerbotAIConfig->meleeDistance + 10.0f;
}
else
{
dismount_distance = sPlayerbotAIConfig->spellDistance + 2.0f;
mount_distance = sPlayerbotAIConfig->spellDistance + 10.0f;
}
// warrior bots should dismount far enough to charge (because its important for generating some initial rage),
// a real player would be riding toward enemy mashing the charge key but the bots wont cast charge while mounted
if (CLASS_WARRIOR == bot->getClass())
dismount_distance = std::max(18.0f, dismount_distance);
// mount_distance should be >= 21 regardless of class, because when travelling a distance < 21 it takes longer
// to cast mount-spell than the time saved from the speed increase. At a distance of 21 both approaches take 3
// seconds:
// 21 / 7 = 21 / 14 + 1.5 = 3 (7 = dismounted speed 14 = epic-mount speed 1.5 = mount-spell cast time)
mount_distance = std::max(21.0f, mount_distance);
float combatReach = bot->GetCombatReach() + currentTarget->GetCombatReach();
float disToTarget = bot->GetExactDist(currentTarget);
shouldDismount = disToTarget <= dismount_distance + combatReach;
shouldMount = disToTarget > mount_distance + combatReach;
}
else
{
shouldDismount = false;
shouldMount = true;
}
if (bot->IsMounted() && shouldDismount)
{
WorldPacket emptyPacket;
bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket);
return true;
}
Player* master = GetMaster();
if (master != nullptr && !bot->InBattleground())
{
if (!bot->GetGroup() || bot->GetGroup()->GetLeaderGUID() != master->GetGUID())
return false;
// bool farFromMaster = sServerFacade->GetDistance2d(bot, master) > sPlayerbotAIConfig->sightDistance;
if (master->IsMounted() && !bot->IsMounted() && noattackers && shouldMount && !bot->IsInCombat() &&
botAI->GetState() != BOT_STATE_COMBAT)
{
return Mount();
}
if (!master->IsMounted() && bot->IsMounted())
{
WorldPacket emptyPacket;
bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket);
return true;
}
return false;
}
// For random bots
if (!bot->InBattleground() && !master)
{
if (!bot->IsMounted() && noattackers && shouldMount && !bot->IsInCombat())
{
return Mount();
}
}
if (bot->InBattleground() && shouldMount && noattackers && !bot->IsInCombat() && !bot->IsMounted())
{
if (bot->GetBattlegroundTypeId() == BATTLEGROUND_WS)
{
BattlegroundWS* bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground();
if (bot->HasAura(23333) || bot->HasAura(23335))
{
return false;
}
}
return Mount();
}
if (!bot->IsFlying() && shouldDismount && bot->IsMounted() && (enemy || dps || (!noattackers && bot->IsInCombat())))
{
WorldPacket emptyPacket;
bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket);
return true;
}
return false;
}
bool CheckMountStateAction::isUseful()
{
// do not use on vehicle
if (botAI->IsInVehicle())
return false;
if (bot->isDead())
return false;
if (bot->HasUnitState(UNIT_STATE_IN_FLIGHT))
return false;
if (!bot->IsOutdoors())
return false;
// in addition to checking IsOutdoors, also check whether bot is clipping below floor slightly because that will
// cause bot to falsly indicate they are outdoors. This fixes bug where bot tries to mount indoors (which seems
// to mostly be an issue in tunnels of WSG and AV)
if (!bot->IsMounted() && bot->GetPositionZ() < bot->GetMapWaterOrGroundLevel(
bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()))
return false;
if (bot->InArena())
return false;
if (!GET_PLAYERBOT_AI(bot)->HasStrategy("mount", BOT_STATE_NON_COMBAT) && !bot->IsMounted())
return false;
bool firstmount = bot->GetLevel() >= 20;
if (!firstmount)
return false;
// Do not use with BG Flags
if (bot->HasAura(23333) || bot->HasAura(23335) || bot->HasAura(34976))
{
return false;
}
// Only mount if BG starts in less than 30 sec
if (bot->InBattleground())
{
if (Battleground* bg = bot->GetBattleground())
if (bg->GetStatus() == STATUS_WAIT_JOIN)
{
if (bg->GetStartDelayTime() > BG_START_DELAY_30S)
return false;
}
}
return true;
}
bool CheckMountStateAction::Mount()
{
uint32 secondmount = 40;
if (bot->isMoving())
{
bot->StopMoving();
// bot->GetMotionMaster()->Clear();
// bot->GetMotionMaster()->MoveIdle();
}
Player* master = GetMaster();
botAI->RemoveShapeshift();
botAI->RemoveAura("tree of life");
int32 masterSpeed = 59;
SpellInfo const* masterSpell = nullptr;
if (master && !master->GetAuraEffectsByType(SPELL_AURA_MOUNTED).empty() && !bot->InBattleground())
{
masterSpell = master->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetSpellInfo();
masterSpeed = std::max(masterSpell->Effects[1].BasePoints, masterSpell->Effects[2].BasePoints);
}
else
{
masterSpeed = 59;
for (PlayerSpellMap::iterator itr = bot->GetSpellMap().begin(); itr != bot->GetSpellMap().end(); ++itr)
{
uint32 spellId = itr->first;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo || spellInfo->Effects[0].ApplyAuraName != SPELL_AURA_MOUNTED)
continue;
if (itr->second->State == PLAYERSPELL_REMOVED || !itr->second->Active || spellInfo->IsPassive())
continue;
int32 effect = std::max(spellInfo->Effects[1].BasePoints, spellInfo->Effects[2].BasePoints);
if (effect > masterSpeed)
masterSpeed = effect;
}
}
if (bot->GetPureSkillValue(SKILL_RIDING) <= 75 && bot->GetLevel() < secondmount)
masterSpeed = 59;
if (bot->InBattleground() && masterSpeed > 99)
masterSpeed = 99;
bool hasSwiftMount = false;
// std::map<int32, std::vector<uint32> > spells;
std::map<uint32, std::map<int32, std::vector<uint32>>> allSpells;
for (PlayerSpellMap::iterator itr = bot->GetSpellMap().begin(); itr != bot->GetSpellMap().end(); ++itr)
{
uint32 spellId = itr->first;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo || spellInfo->Effects[0].ApplyAuraName != SPELL_AURA_MOUNTED)
continue;
if (itr->second->State == PLAYERSPELL_REMOVED || !itr->second->Active || spellInfo->IsPassive())
continue;
int32 effect = std::max(spellInfo->Effects[1].BasePoints, spellInfo->Effects[2].BasePoints);
// if (effect < masterSpeed)
// continue;
uint32 index = (spellInfo->Effects[1].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED ||
spellInfo->Effects[2].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED ||
// Winged Steed of the Ebon Blade
// This mount is meant to autoscale from a 150% flyer
// up to a 280% as you train your flying skill up.
// This incorrectly gets categorised as a ground mount, force this to flyer only.
// TODO: Add other scaling mounts here if they have the same issue, or adjust above
// checks so that they are all correctly detected.
spellInfo->Id == 54729)
? 1 // Flying Mount
: 0; // Ground Mount
if (index == 0 &&
std::max(spellInfo->Effects[EFFECT_1].BasePoints, spellInfo->Effects[EFFECT_2].BasePoints) > 59)
hasSwiftMount = true;
if (index == 1 &&
std::max(spellInfo->Effects[EFFECT_1].BasePoints, spellInfo->Effects[EFFECT_2].BasePoints) > 149)
hasSwiftMount = true;
allSpells[index][effect].push_back(spellId);
}
int32 masterMountType = 0;
if (masterSpell)
{
masterMountType = (masterSpell->Effects[1].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED ||
masterSpell->Effects[2].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED)
? 1
: 0;
}
// Check for preferred mounts table in db
QueryResult checkTable = PlayerbotsDatabase.Query(
"SELECT EXISTS(SELECT * FROM information_schema.tables WHERE table_schema = 'acore_playerbots' AND table_name = 'playerbots_preferred_mounts')");
if (checkTable)
{
uint32 tableExists = checkTable->Fetch()[0].Get<uint32>();
if (tableExists == 1)
{
// Check for preferred mount entry
QueryResult result = PlayerbotsDatabase.Query(
"SELECT spellid FROM playerbots_preferred_mounts WHERE guid = {} AND type = {}",
bot->GetGUID().GetCounter(), masterMountType);
if (result)
{
std::vector<uint32> mounts;
do
{
Field* fields = result->Fetch();
uint32 spellId = fields[0].Get<uint32>();
mounts.push_back(spellId);
} while (result->NextRow());
uint32 index = urand(0, mounts.size() - 1);
// Validate spell ID
if (index < mounts.size() && sSpellMgr->GetSpellInfo(mounts[index]))
{
// TODO: May want to do checks for 'bot riding skill > skill required to ride the mount'
return botAI->CastSpell(mounts[index], bot);
}
}
}
}
// No preferred mount found (or invalid), continue with random mount selection
std::map<int32, std::vector<uint32>>& spells = allSpells[masterMountType];
if (hasSwiftMount)
{
for (auto i : spells)
{
std::vector<uint32> ids = i.second;
for (auto itr : ids)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr);
if (!spellInfo)
continue;
if (masterMountType == 0 && masterSpeed > 59 &&
std::max(spellInfo->Effects[EFFECT_1].BasePoints, spellInfo->Effects[EFFECT_2].BasePoints) < 99)
spells[59].clear();
if (masterMountType == 1 && masterSpeed > 149 &&
std::max(spellInfo->Effects[EFFECT_1].BasePoints, spellInfo->Effects[EFFECT_2].BasePoints) < 279)
spells[149].clear();
}
}
}
for (std::map<int32, std::vector<uint32>>::iterator i = spells.begin(); i != spells.end(); ++i)
{
std::vector<uint32>& ids = i->second;
uint32 index = urand(0, ids.size() - 1);
if (index >= ids.size())
continue;
return botAI->CastSpell(ids[index], bot);
;
}
std::vector<Item*> items = AI_VALUE2(std::vector<Item*>, "inventory items", "mount");
if (!items.empty())
return UseItemAuto(*items.begin());
return false;
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_CHECKMOUNTSTATEACTION_H
#define _PLAYERBOT_CHECKMOUNTSTATEACTION_H
#include "UseItemAction.h"
class PlayerbotAI;
class CheckMountStateAction : public UseItemAction
{
public:
CheckMountStateAction(PlayerbotAI* botAI) : UseItemAction(botAI, "check mount state", true) {}
bool Execute(Event event) override;
bool isUseful() override;
bool isPossible() override { return true; }
bool Mount();
};
#endif

View File

@@ -1,210 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "EquipAction.h"
#include "Event.h"
#include "ItemCountValue.h"
#include "ItemUsageValue.h"
#include "Playerbots.h"
#include "StatsWeightCalculator.h"
bool EquipAction::Execute(Event event)
{
std::string const text = event.getParam();
ItemIds ids = chat->parseItems(text);
EquipItems(ids);
return true;
}
void EquipAction::EquipItems(ItemIds ids)
{
for (ItemIds::iterator i = ids.begin(); i != ids.end(); i++)
{
FindItemByIdVisitor visitor(*i);
EquipItem(&visitor);
}
}
// Return bagslot with smalest bag.
uint8 EquipAction::GetSmallestBagSlot()
{
int8 curBag = 0;
uint32 curSlots = 0;
for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag)
{
const Bag* const pBag = (Bag*)bot->GetItemByPos(INVENTORY_SLOT_BAG_0, bag);
if (pBag)
{
if (curBag > 0 && curSlots < pBag->GetBagSize())
continue;
curBag = bag;
curSlots = pBag->GetBagSize();
}
else
return bag;
}
return curBag;
}
void EquipAction::EquipItem(FindItemVisitor* visitor)
{
IterateItems(visitor);
std::vector<Item*> items = visitor->GetResult();
if (!items.empty())
EquipItem(*items.begin());
}
void EquipAction::EquipItem(Item* item)
{
uint8 bagIndex = item->GetBagSlot();
uint8 slot = item->GetSlot();
const ItemTemplate* itemProto = item->GetTemplate();
uint32 itemId = itemProto->ItemId;
if (itemProto->InventoryType == INVTYPE_AMMO)
{
bot->SetAmmo(itemId);
}
else
{
bool equippedBag = false;
if (itemProto->Class == ITEM_CLASS_CONTAINER)
{
Bag* pBag = (Bag*)&item;
uint8 newBagSlot = GetSmallestBagSlot();
if (newBagSlot > 0)
{
uint16 src = ((bagIndex << 8) | slot);
uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | newBagSlot);
bot->SwapItem(src, dst);
equippedBag = true;
}
}
if (!equippedBag)
{
uint8 dstSlot = botAI->FindEquipSlot(itemProto, NULL_SLOT, true);
bool have2HWeapon = false;
bool isValidTGWeapon = false;
if (dstSlot == EQUIPMENT_SLOT_MAINHAND)
{
Item* currentWeapon = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
have2HWeapon = currentWeapon && currentWeapon->GetTemplate()->InventoryType == INVTYPE_2HWEAPON;
isValidTGWeapon = itemProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2 ||
itemProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE2 ||
itemProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD2;
}
if (dstSlot == EQUIPMENT_SLOT_FINGER1 ||
dstSlot == EQUIPMENT_SLOT_TRINKET1 ||
(dstSlot == EQUIPMENT_SLOT_MAINHAND && bot->CanDualWield() &&
((itemProto->InventoryType != INVTYPE_2HWEAPON && !have2HWeapon) || (bot->CanTitanGrip() && isValidTGWeapon))))
{
Item* const equippedItems[2] = {
bot->GetItemByPos(INVENTORY_SLOT_BAG_0, dstSlot),
bot->GetItemByPos(INVENTORY_SLOT_BAG_0, dstSlot + 1)
};
if (equippedItems[0])
{
if (equippedItems[1])
{
// Both slots are full - determine worst item to replace
StatsWeightCalculator calculator(bot);
calculator.SetItemSetBonus(false);
calculator.SetOverflowPenalty(false);
// float newItemScore = calculator.CalculateItem(itemId);
float equippedItemScore[2] = {
equippedItemScore[0] = calculator.CalculateItem(equippedItems[0]->GetTemplate()->ItemId),
equippedItemScore[1] = calculator.CalculateItem(equippedItems[1]->GetTemplate()->ItemId)
};
// Second item is worse than first, equip candidate item in second slot
if (equippedItemScore[0] > equippedItemScore[1])
{
dstSlot++;
}
}
else // No item equipped in slot 2, equip in that slot instead of replacing first item
{
dstSlot++;
}
}
}
WorldPacket packet(CMSG_AUTOEQUIP_ITEM_SLOT, 2);
ObjectGuid itemguid = item->GetGUID();
packet << itemguid << dstSlot;
bot->GetSession()->HandleAutoEquipItemSlotOpcode(packet);
// WorldPacket packet(CMSG_AUTOEQUIP_ITEM, 2);
// packet << bagIndex << slot;
// bot->GetSession()->HandleAutoEquipItemOpcode(packet);
}
}
std::ostringstream out;
out << "equipping " << chat->FormatItem(itemProto);
botAI->TellMaster(out);
}
bool EquipUpgradesAction::Execute(Event event)
{
if (!sPlayerbotAIConfig->autoEquipUpgradeLoot && !sRandomPlayerbotMgr->IsRandomBot(bot))
return false;
if (event.GetSource() == "trade status")
{
WorldPacket p(event.getPacket());
p.rpos(0);
uint32 status;
p >> status;
if (status != TRADE_STATUS_TRADE_ACCEPT)
return false;
}
ListItemsVisitor visitor;
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
ItemIds items;
for (std::map<uint32, uint32>::iterator i = visitor.items.begin(); i != visitor.items.end(); ++i)
{
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", i->first);
if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP)
{
// LOG_INFO("playerbots", "Bot {} <{}> auto equips item {} ({})", bot->GetGUID().ToString().c_str(),
// bot->GetName().c_str(), i->first, usage == 1 ? "no item in slot" : usage == 2 ? "replace" : usage == 3 ?
// "wrong item but empty slot" : "");
items.insert(i->first);
}
}
EquipItems(items);
return true;
}
bool EquipUpgradeAction::Execute(Event event)
{
ListItemsVisitor visitor;
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
ItemIds items;
for (std::map<uint32, uint32>::iterator i = visitor.items.begin(); i != visitor.items.end(); ++i)
{
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", i->first);
if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP)
{
items.insert(i->first);
}
}
EquipItems(items);
return true;
}

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