I'm not 100% sure but think that the current implementation of timers
for Attumen, Netherspite, and Nightbane with the instance's map id as
the key would result in the timers being shared across separate raids
running the instance at the same time. I've refactored to use the
instance id as the key for all shared timers so to the extent this was
an issue, it shouldn't be anymore.
I also made some minor tweaks to the tank positioning for BBW and
Curator as I noticed there was some weirdness in the logic that I
neglected to address with the refactor.
The feature `Disable bot XP gain when master has XP turned off` (#1910)
was unintentionally disabled in #1929.
This PR re-enables it with better checks in order to prevent crashes
when playing together with the individual progression module.
Hotfix for the issue where bots can't enter/move on transports
(elevators, zeppelins, ships, etc.). Change the logic to determine if
bot is on a vehicle. According to the current implementation in
AzerothCore, `GetVehicle()` is the most common approach for this.
Additionally, other checks related to the vehicle: `GetBase`, `IsAlive`,
`GetVehicleInfo`, and `GetSeatForPassenger` -- are processed inside
`IsInVehicle`.
This should be more than enough to determine if the bot is on a vehicle
and can/cant control it.
Issue: https://github.com/mod-playerbots/mod-playerbots/issues/1927
This is based off of Wishmasters rewrite of spell PR. #1912 and #1843,
and partial #1918
I created a new cache singleton with the required code to reference as
needed.
I clarified some variable names for additional clarity in how they
functioned.
This requires a wiki update to better describe the functionality that
was already defined in code.
Commands
Spells - Returns all spells
Spells <Profession> Returns only the spells in that profession
+<profession> Returns only the recipies that the bot has materials to
craft
<profession> `x - y` Craftable items within those levels
<profession> <slot> e.g. Chest, returns craftable items within that
slot.
Its messy whether what combinations work for commands, but fixing that
will come when bot professions are enabled.
Edit:
To test you can teach a bot various professions by going to a trainer
with them.
Using gm command .setskill you increase their skill level and with
maintenance teach the commands.
From wishmasters PR he detailed various commands to test
spells
spells first aid
spells tailoring
spells 20-40
spells +tailoring
spells head
---------
Co-authored-by: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com>
Addresses #1846
This PR disables XP gain for bots whose non-bot master has disabled XP
gain via an "Experience Eliminator" NPC.
If the current master has disabled XP gain, randombots in the group and
addclass-bots belonging to the player won't gain XP.
Randombots not grouped with a player will continue to gain XP as normal.
Discussed points:
- `Should this feature only be enabled via a new configuration value?`:
Comments currently tend towards no config value.
Open points:
- Should bots be allowed to gain XP until they reach the player's level,
even if the player has disabled XP gain?
Noticed that if you ask a bot to duel in a PVP prohibited area, it will
accept, and do nothing. I thought about making the bot reject the
request, but if you (the real player) want to duel with it, the duel
should happen. This is just a minor fix to allow bots to duel if you ask
them to in such areas.
Tested with bots in party, random bots of the same faction, and random
bots of the opposite faction. All behaved the same before and after fix.
An example place to test is Zim'Torga in Zul'Drak which is by default is
a PVP prohibited area.
- Before fix, you challenge a bot, they accept and turn red, then they
either just stay where they are or wander off.
- After fix, bot attacks you within the PVP prohibited area when the
duel starts.
Okay, what have been done:
1. Fix heartbeat spam for root flag: check against `MOVEMENTFLAG_ROOT`
flag (`IsRooted`) instead of `HasRootAura`.
2. Rewrite `IsMovingAllowed` - place checks from most common to the
rarest.
3. Remove unnecessary checks: `HasRootAura`, `HasConfuseAura`,
`HasStunAura` - handled by AuraEffects and set unit state flags
`UNIT_STATE_ROOT`, `UNIT_STATE_CONFUSED`, `UNIT_STATE_STUNNED` -
`UNIT_STATE_LOST_CONTROL` already handles confused and stunned (rooted
checked with `IsRooted` method).
4. Combine traveling state checks for taxi flights:
`UNIT_STATE_IN_FLIGHT` + MM flag `FLIGHT_MOTION_TYPE`.
5. Simplify check against being in vehicle: use
`MOVEMENTFLAG_ONTRANSPORT` as an indicator that the unit is in the
vehicle.
Also, update `UpdateMovementState` method with simplified checks and the
updated logic (common > rare).
This should fix issues:
https://github.com/mod-playerbots/mod-playerbots/issues/1903 and
https://github.com/mod-playerbots/mod-playerbots/issues/1902
NOTE: The `PlayerbotAI` class has a method `CanMove` with the same
checks, but this method is only used once in the code. We should decide
how to properly check if the bot can move or not:
1. Place all logic into `IsMovingAllowed` and drop `CanMove`.
2. Place all logic into `CanMove` and use it inside `IsMovingAllowed`.
3. Use them for different approaches:
- `CanMove`: simple checks (unit flags, CC state, death state, travel
state, vehicle state);
- `IsMovingAllowed`: everything from `CanMove` + MM flags checks (not
sure about rooted since it still checks for movement flags...).
This PR adds a couple of neutral quest hubs in Outland to PvP restricted
areas (and makes a couple of very minor formatting fixes to the Karazhan
files).
3786: Ogri'la
3973: Blackwind Landing (Sha'tari Skyguard quest hub in Skettis)
This PR completely refactors the Karazhan raid strategies to clean up
the code and polish up/introduce new strategies, including for
Nightbane.
General changes with respect to the code:
- Moved gating checks for action methods to triggers instead of relying
on isUseful functions
- Got rid of the nonsensical helper class I made and switched to a
helper namespace
- Broke up some longer action classes into separate methods and/or
private members
- Deleted/consolidated some excess code
- Made greater use of early returns
- Renamed methods, multipliers, and triggers to make them easier to
understand
- Generally made edits to conform with AC code standards
Below are the implemented strategies. I’m including all of them, not
just new/modified ones, because I don’t think the first set of
strategies was ever tested. So each boss could probably use complete
testing.
### **Trash**
I added strategies for a trash mob that I find particularly annoying:
- Mana Warp: These are, IMO, the most annoying trash mobs in Karazhan.
They blow up when low on health, and having two blow up in quick
succession is enough to take out a decent chunk of your raid. The
strategy directs bots to use pretty much every stun in the book on Mana
Warps when they’re low on HP, which is the only way to prevent the
explosion.
### **Attumen**
- During the first phase, bots will focus on Midnight (taking either
Midnight or Attumen to 25% starts the next phase). When Attumen spawns,
the assist tank will pick him up and move him away so that bots don’t
get cleaved.
- When Attumen mounts Midnight, starting phase 2, threat is wiped, and
bots will pause DPS for a few seconds to allow the main tank to get
aggro. All bots, other than the main tank and any bot that pulls aggro,
will stack behind Attumen (~6 yards for ranged so Hunters can still
attack).
### **Moroes**
- As before, bots will mark and prioritize adds and the boss in the
recommended kill order: Dorothea, Catriona, Keira, Rafe, Robin, Crispin,
and Moroes. In practice, the enemies will probably be stacked up, and
the bots will AoE them down in accordance with their typical AoE
strategies, but classes without AoE capabilities should still prioritize
the skull.
- Based on testing feedback, added a method for the main tank to
prioritize Moroes
### **Maiden of Virtue**
I’ve made only minor changes to Revision’s original strategy here.
- The tank with aggro will position Maiden in the middle of the room and
move her to a healer when Repentance is cast so that the Holy Ground
will break the healer’s stun.
- Ranged bots have assigned positions between the columns around the
middle of the room (to prevent chain damage from Holy Wrath).
### **The Big Bad Wolf**
- The tank with aggro brings the boss to the front left of the stage.
- If a bot gets turned into Little Red Riding Hood, it will run around
the stage in a counter-clockwise rectangle until the transformation
fades. I tweaked this strategy a bit; it's still not perfect, but it
works better than before.
### **Romulo and Julianne**
There are no substantive changes to this strategy. As before, in phase
3, when both bosses are active, the bots switch back-and-forth between
the bosses by alternating the skull icon based on which boss has lower
HP (10% differential).
### **The Wizard of Oz**
There are no substantive changes to this strategy. As before, bots mark
the bosses with a skull icon in their recommended kill order: Dorothee,
Tito (assuming he spawns before you kill Dorothee), Roar, Strawman,
Tinhead, and the Crone. Additionally, Mages will spam Scorch on Strawman
to daze him.
### **The Curator**
- The tank will drag the boss to a fixed spot down the hallway. Ranged
bots will spread out to avoid chain damage from Arcing Sear, and bots
will mark Astral Flares with the skull icon to prioritize them down.
- Those strategies already existed, but now I made the assist tank also
focus on the boss to try to stay second in aggro and therefore absorb
Hateful Bolts.
- Added a multiplier to save Bloodlust/Heroism until Evocation.
### **Terestian Illhoof**
There are no substantive changes to this strategy. The bots will mark
targets with the skull icon in the following order: Demonic Chains,
Kil'rek, and Illhoof.
### **Shade of Aran**
I redid the strategies a bit, and I think (hope) they work better.
- Flame Wreath: Bots will stop moving until the aura fades. There is a
bug in which Flame Wreath will sometimes persist long beyond its
supposed 20-second duration. If Aran casts Arcane Explosion during this
time, you will almost certainly wipe, so that’s frustrating. I made it
so that bots will stay in place still and eat the Arcane Explosion
because it’s the lesser of two evils, and if you are overgeared, you may
be able to survive. In the previous strategy, bots would stop actions
entirely, but now they should keep attacking/casting without moving.
- Arcane Explosion: No substantive changes here--bots will run out
immediately and stay out of range until the cast finishes.
- Conjured Elementals: No substantive changes here--they will be marked
one-by-one by the skull icon, except that the marking will skip any
elemental that is banished.
- Ranged Positioning: I redid this strategy. Ranged bots will now
maintain a distance between 11 and 15 yards from the boss. This keeps
them out of the 10-yard radius in which Aran silences while also keeping
them from getting too far away and getting stuck in the alcoves.
### **Netherspite**
I significantly refactored the action methods here, but substantively
the original strategy remains mostly intact.
- Red (Tank) Beam: One tank will be assigned to block the beam for each
Portal Phase. The assigned tank will dance in and out of the beam (5
seconds in, 5 seconds out). Tanks intentionally do not avoid Void Zones
(it was the lesser of two evils for them to take that damage vs. trying
to dynamically avoid them, moving the boss, and possibly getting
everybody out of position.
- Blue (DPS) Beam: DPS other than Rogues and Warriors are eligible to be
assigned (one-by-one) to block this beam. When the assigned blocker
reaches 25 stacks of the debuff, they will leave the beam, and the next
assigned blocker will take their place. If a Void Zone drops under the
assigned blocker, the bot will move along the beam to get out of the
Void Zone so that they do not stop blocking.
- Green (Healer) Beam: This works the same way as the Blue Beam, except
that eligible blockers are healers, Rogues, and DPS Warriors. Healers
that are assigned to block will swap in the same way as Blue Beam
blockers. If a Rogue or DPS Warrior is the assigned blocker, however,
they will stand in the beam for the entire Portal Phase since they do
not suffer any adverse effects from the beam. In this PR, I made the
strategy prioritize Rogues and DPS Warriors over healers to try to avoid
the need for bots to swap (and to avoid the irritating scenario in which
a healer would block the beam for the first half of a phase and then tag
in a Rogue or DPS Warrior, which would be wasted by blocking only half
of a phase).
- Non-Blockers: They will stay at least 5 yards away from each beam
until called to be an assigned blocker. They will also avoid Void Zones.
- Banish Phase: The only strategy I implemented was for bots to avoid
residual Void Zones from the Portal Phase.
- Phase Transitions: Bots should pause DPS at the beginning of the
encounter and whenever Netherspite transitions back from the Banish
Phase to the Portal Phase (which is an aggro reset). Note that this
doesn't wipe DOTs, and there's not much I can do about that.
### **Prince Malchezaar**
The action methods are significantly refactored, but the strategy
substantively is not changed very much.
- Bots will maintain distance from Infernals. The tank has a larger
avoidance radius to give DPS a little bit of margin to work with.
Depending on Infernal placement, it is possible for bots to get stuck in
some bad positions. In that case, the best solution is to put them on
“flee” and lead them to a better position.
- Bots that get Enfeebled will run out of Shadow Nova range. They should
pick a path that does not cross within any Infernal's Hellfire radius.
- Added a multiplier to save Bloodlust/Heroism until Phase 3.
### **Nightbane**
**Disclaimer**: Bots are terrible at this encounter, in large part
because the map is awful (even before the recent Core changes). So the
strategies are not ideal because they need to operate within the bots’
limitations. I STRONGLY suggest you clear the entire Livery Stables
(including the upper level) because the mobs in them have a high risk of
pulling through the floor of the Master’s Terrace. Ideally, you should
clear out the Scullery too.
The strategy uses waypoints toward the Northeastern door to the Master’s
Terrace. I tried several different locations, and that worked best for
me based on where Nightbane lands (note that he has a different landing
spot for the encounter start vs. the start subsequent ground phases).
- Ground Phase, main tank: The main tank uses two waypoints after it
picks up the boss—the movement pattern should be kind of like a reverse
checkmark, where the tank moves back along the inner edge of the
terrace, then pivots and moves at a bit of an angle to the outer edge. I
did this as a way to get the tank to face Nightbane sideways across the
terrace, which is how he’s supposed to be tanked. The main tank will not
get out of Charred Earth. This is intended. The tank cannot move
dynamically enough to avoid it while also not turning the boss and
wiping the raid.
- Ground phase, ranged: Ranged bots rotate between three waypoints. They
start stacked at the same position. If Charred Earth is dropped on that
position, the bots will rotate to the second position. If Charred Earth
is dropped on that position, they will rotate to the third position. The
maximum number of Charred Earths that can be active is two, so if one is
dropped on the third position, the ranged bots should rotate back to the
first position.
- Ground Phase, other melee: Melee bots have no coded Charred Earth
avoidance strategy. They do decently enough with the general “avoid aoe”
strategy.
- Flight Phase: Bots move to Nightbane’s flight position—Nightbane is
bugged and cannot be attacked in the air in AC, but all bots still need
to stay near him or he will wipe the raid with Fireball Barrage. Bots
stack on the same position; when Rain of Bones is cast (one time,
snapshotted on the target’s location), all bots will move away to a
second nearby position. They will then kill the Restless Skeletons. The
Flight Phase lasts for 45 seconds, but Nightbane emotes after 35 seconds
and goes to land—during the final 10-second period, bots are freed from
all strategies and will follow the master. You need to lead them back to
the Northeastern part of the terrace before Nightbane lands so that bots
can get immediately positioned when he lands.
- Phase Changes: Whenever Nightbane lands, bots should pause DPS for the
main tank to get aggro.
- Managing bots/pets: During the Flight Phase, bots and pets have a
tendency to chase Nightbane outside of the boundaries of the map and
pull mobs from other parts of the instance as well as cause Restless
Skeletons to spawn out of bounds (and then further cause bots/pets to go
out of bounds to attack the skeletons). The strategy should solve for
this, but if there are still issues, it should be noted. My resolution
was to implement the following: (1) when Nightbane takes flight, bots
stop attacking and mark him with the moon icon, and Hunters and Warlocks
put pets on passive and recall them (they will put pets on defensive
again when Nightbane lands), and (2) all temporary pets are disabled for
the duration of the fight (Water Elementals, Shaman wolves, Druid
treants, etc.).
**Known Issues:**
- The approach to getting Nightbane to turn sideways is not always spot
on since it’s a workaround to account for what should be dynamic
movement. He can end up at a bit of an angle. I’ve tweaked the positions
such that if he is at an angle, it should not be a situation in which
any ranged position is exposed to Smoldering Breath or Cleave. That does
increase the risk that poor positioning may expose a ranged position to
Tail Sweep. This is obviously suboptimal, but that attack is much more
survivable.
- Ranged bots move between the three waypoints by reading the presence
of the Charred Earth aura on themselves. Sometimes, a bot may reach the
next waypoint with the Charred Earth aura from the previous waypoint
still on them (depending on timing of ticks), in which case the bot will
keep moving to the next waypoint. This can cause an issue in which the
ranged group gets split. So you could have Charred Earth dropped on
position 1, and some ranged bots will go to position 2 but others will
go to position 3, and then if the second Charred Earth is dropped on
position 3, the bots at position 3 will move back to position 1 (which
is still in Charred Earth) before then moving to position 2. Balancing
spacing between waypoints, positioning with respect to the boss, line of
sight, and maximum distance is very difficult to do. I messed with the
positioning a lot, and I am not sure if this possibility cannot be
entirely avoided without creating other issues. I have at least reached
a result in which I have not seen any bots cycle indefinitely (though if
testing observes this, it is obviously a problem).
Ultimately, I wouldn’t say I’m totally satisfied with the strategy.
Wipes are still possible on account of bad RNG. But I think it does make
the fight a lot more manageable, as it is a fight that is very difficult
with IP nerfs in the absence of any strategy. Previously, I needed to
bring 3 healers, and they would still all be out of mana by the first
Flight Phase and reliant on MP5 for the remainder of the fight, and I
would wipe multiple times before a kill.
# Fix: Arena PersonalRating and MMR issue for bot teams
## Problem
Bot arena teams are created with artificial random ratings (1000-2000
range), but when bots join these teams, their personal ratings and
matchmaker ratings (MMR) use default config values instead of being
adjusted to match the team's artificial rating. This causes matchmaking
issues since the system uses personal ratings for queue calculations.
## Root Cause
The issue occurred because `SetRatingForAll()` was called during team
creation but only affected the captain. When additional bots were added
later via `AddMember()`, they received default values from
`CONFIG_ARENA_START_PERSONAL_RATING` and
`CONFIG_ARENA_START_MATCHMAKER_RATING` instead of values appropriate for
the team's artificial rating.
## Solution
After bots are added to arena teams, the fix:
1. Uses `SetRatingForAll()` to align all personal ratings with team
rating
2. Adjusts matchmaker ratings based on team context vs default
configuration
3. Saves changes to both database tables with proper data types
## Impact
- Personal ratings now match team ratings for artificial bot teams
- MMR values are adjusted for artificial bot team ratings instead of
using default config values
- Arena matchmaking functions correctly for bot teams with random
ratings
- Only affects new arena team assignments after deployment
- Existing player teams and normal config behavior are unaffected
## Manual Database Update
For existing installations, the provided SQL script could be used to fix
bot teams created before this patch.
### Update personal rating
```sql
UPDATE arena_team_member atm
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
SET atm.personalRating = at.rating
WHERE a.username LIKE 'rndbot%'
AND atm.personalRating != at.rating;
```
### Update MMR for existing entries
```sql
UPDATE character_arena_stats cas
JOIN characters c ON cas.guid = c.guid
JOIN auth.account a ON c.account = a.id
JOIN arena_team_member atm ON cas.guid = atm.guid
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
SET
cas.matchMakerRating = GREATEST(at.rating, 1500), -- Use team rating or 1500 minimum
cas.maxMMR = GREATEST(cas.maxMMR, cas.matchMakerRating) -- Update maxMMR if needed
WHERE
a.username LIKE '%rndbot%'
AND (
-- Update if MMR doesn't match team context
(at.rating > 1500 AND cas.matchMakerRating < at.rating) OR
(at.rating <= 1500 AND cas.matchMakerRating != 1500) OR
cas.matchMakerRating IS NULL
)
AND (
-- Map arena team type to character_arena_stats slot
(at.type = 2 AND cas.slot = 0) OR -- 2v2 teams use slot 0
(at.type = 3 AND cas.slot = 1) OR -- 3v3 teams use slot 1
(at.type = 5 AND cas.slot = 2) -- 5v5 teams use slot 2
);
```
### Insert missing MMR records for bots without character_arena_stats
entries
```sql
INSERT INTO character_arena_stats (guid, slot, matchMakerRating, maxMMR)
SELECT
atm.guid,
CASE
WHEN at.type = 2 THEN 0 -- 2v2 -> slot 0
WHEN at.type = 3 THEN 1 -- 3v3 -> slot 1
WHEN at.type = 5 THEN 2 -- 5v5 -> slot 2
ELSE 0
END as slot,
GREATEST(at.rating, 1500) as matchMakerRating,
GREATEST(at.rating, 1500) as maxMMR
FROM arena_team_member atm
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
WHERE
a.username LIKE '%rndbot%'
AND NOT EXISTS (
SELECT 1 FROM character_arena_stats cas2
WHERE cas2.guid = atm.guid
AND cas2.slot = CASE
WHEN at.type = 2 THEN 0
WHEN at.type = 3 THEN 1
WHEN at.type = 5 THEN 2
ELSE 0
END
)
AND at.rating > 0;
```
## Related issues
Fixes: #1787Fixes: #1800
## Verification Queries
### Query 1: Check personal rating alignment
```sql
SELECT
'Personal Rating Check' as check_type,
COUNT(*) as total_bot_members,
SUM(CASE WHEN atm.personalRating = at.rating THEN 1 ELSE 0 END) as correct_ratings,
SUM(CASE WHEN atm.personalRating != at.rating THEN 1 ELSE 0 END) as incorrect_ratings,
ROUND(AVG(at.rating), 2) as avg_team_rating,
ROUND(AVG(atm.personalRating), 2) as avg_personal_rating
FROM arena_team_member atm
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
WHERE
a.username LIKE '%rndbot%';
```
### Query 2: Check MMR alignment
```sql
SELECT
'MMR Alignment Check' as check_type,
COUNT(*) as total_mmr_records,
SUM(CASE
WHEN at.rating > 1500 AND cas.matchMakerRating >= at.rating THEN 1
WHEN at.rating <= 1500 AND cas.matchMakerRating = 1500 THEN 1
ELSE 0
END) as correct_mmr,
SUM(CASE
WHEN at.rating > 1500 AND cas.matchMakerRating < at.rating THEN 1
WHEN at.rating <= 1500 AND cas.matchMakerRating != 1500 THEN 1
ELSE 0
END) as incorrect_mmr,
ROUND(AVG(at.rating), 2) as avg_team_rating,
ROUND(AVG(cas.matchMakerRating), 2) as avg_mmr,
ROUND(AVG(cas.maxMMR), 2) as avg_max_mmr
FROM arena_team_member atm
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
JOIN character_arena_stats cas ON atm.guid = cas.guid
WHERE
a.username LIKE '%rndbot%'
AND (
(at.type = 2 AND cas.slot = 0) OR
(at.type = 3 AND cas.slot = 1) OR
(at.type = 5 AND cas.slot = 2)
);
```
### Query 3: Detailed team-by-team analysis
```sql
SELECT
at.arenaTeamId,
at.name as team_name,
at.type as team_type,
at.rating as team_rating,
COUNT(atm.guid) as member_count,
GROUP_CONCAT(DISTINCT atm.personalRating) as personal_ratings,
GROUP_CONCAT(DISTINCT cas.matchMakerRating) as mmr_values,
CASE
WHEN COUNT(DISTINCT atm.personalRating) = 1 AND MIN(atm.personalRating) = at.rating THEN 'OK'
ELSE 'MISMATCH'
END as personal_rating_status,
CASE
WHEN COUNT(DISTINCT cas.matchMakerRating) = 1 AND (
(at.rating > 1500 AND MIN(cas.matchMakerRating) >= at.rating) OR
(at.rating <= 1500 AND MIN(cas.matchMakerRating) = 1500)
) THEN 'OK'
ELSE 'MISMATCH'
END as mmr_status
FROM arena_team at
JOIN arena_team_member atm ON at.arenaTeamId = atm.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
LEFT JOIN character_arena_stats cas ON atm.guid = cas.guid
AND cas.slot = CASE
WHEN at.type = 2 THEN 0
WHEN at.type = 3 THEN 1
WHEN at.type = 5 THEN 2
ELSE 0
END
WHERE
a.username LIKE '%rndbot%'
GROUP BY at.arenaTeamId, at.name, at.type, at.rating
ORDER BY at.rating DESC;
```
Stripped down version of #1818. No new features. Refactors
IsPossibleTarget in AttackersValue.cpp to a better style and makes sure
pets don't attack in prohibited zones.
Testing:
Confirmed that aggro pets no longer attack in PVP prohibited areas, but
still do outside them. Zim'Torga in Zul'Drak is a good example to test
this (ID 4323). Lookout for death knights with a Risen Ally
(uncontrolled and naturally aggro) now they respect PVP prohibition like
their master.
Note: If you manually teleport a bot that is in mid combat to a PVP
prohibited area, its aggro pet might still attack, because its master is
still in combat strategy. Otherwise the pet will not attack if its
master has switched to non-combat.
I removed bots checking if they should leave group every tick, and will
rely on the LeaveGroupFarAway action. I also increased the timer from 5
seconds to 20 seconds. No need to check this that often.
Fix the naming conventions.
Master should be reserved to identify a bots Master.
groupleaders are not necessarily group masters and it should be clear
what the bot is looking for. (In most solo cases leader=master)
Fixes crashes and race conditions when bots perform group/guild/arena
operations by moving thread-unsafe code to world thread.
Potentially fixes#1124
## Changes
- Added operation queue system that runs in world thread
- Group operations (invite, remove, convert to raid, set leader) now
queued
- Arena formation refactored to use queue
- Guild operations changed to use packet queueing
## Testing
Set `MapUpdate.Threads` > 1 in worldserver.conf to enable multiple map
threads, then test:
- Group formation and disbanding
- Arena team formation
- Guild operations (invite, promote, demote, remove)
- Run with TSAN
cmake ../ \
-DCMAKE_CXX_FLAGS="-fsanitize=thread -g -O1" \
-DCMAKE_C_FLAGS="-fsanitize=thread -g -O1" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=thread" \
-DCMAKE_INSTALL_PREFIX=/path/to/install \
-DCMAKE_BUILD_TYPE=RelWithDebInfo
build
export
TSAN_OPTIONS="log_path=tsan_report:halt_on_error=0:second_deadlock_stack=1"
./worldserver
The crashes/race conditions should no longer occur with concurrent map
threads.
## New Files
- `PlayerbotOperation.h` - Base class defining the operation interface
(Execute, IsValid, GetPriority)
- `PlayerbotOperations.h` - Concrete implementations:
GroupInviteOperation, GroupRemoveMemberOperation,
GroupConvertToRaidOperation, GroupSetLeaderOperation,
ArenaGroupFormationOperation
- `PlayerbotWorldThreadProcessor.h/cpp` - Singleton processor with
mutex-protected queue, processes operations in WorldScript::OnUpdate
hook, handles batch processing and validation
---------
Co-authored-by: blinkysc <blinkysc@users.noreply.github.com>
Co-authored-by: SaW <swerkhoven@outlook.com>
Co-authored-by: bash <hermensb@gmail.com>
fixes https://github.com/mod-playerbots/mod-playerbots/issues/1854
-----
Also includes fixes for:
-----
* Bots swimming with waterWalk kept switching between swimming and
walking, as result jittering effect swimming under water when water
walking active
* Bots flying close above water they would land on water and start
walking, now they stay flying unless on solid ground they will land and
start walking by design
-----
Moved all flag setting to updateMovementState:
* So all movement flag are handled in updateMovementState which also
contains the restricted movement logic.
* Handle restricted movement logic and preventing SendMovementFlagUpdate
while being restricted.
-----
Known issue when flying the following bots feel a bit jittering, wont
touch for now at least till core movement changes quirks has been dealt
with.
The current code is the extended version of what is originally was
before core merge with refactored movements. Once the core movement
refactors are settled a bit more i would like to revisit this code; as i
would expect more imperative code and less manual flag setting e.g.
bot->SetWaterWalking, SetGravitiy..SetCanFly etc.
I've had this problem for a long time, my bots only speak English even
though I'm playing on a French client.
I suppose this must be the case for some other people who do not have a
large number of players with the same local client.
If we use French DBCs, the bots bug because they only recognize US DBCs.
From what I understand, the language is chosen as follows:
On load, the module reads the entire `ai_playerbot_texts` table and
stores each text variant in a dictionary indexed by the locale ID: the
`text` column remains the default value (English), and the `text_loc1`
to `text_loc8` columns fill slots 1 through 8.
Whenever a real player connects, the module increments a counter for
that player's DBC locale using
`AddLocalePriority(player->GetSession()->GetSessionDbcLocale())`.
When a bot needs a text, `GetLocalePriority()` returns the most
frequently used locale index among currently connected players. The
corresponding string is then retrieved. if the box is empty, we fall
back to the English version (text[0]).
### This PR improve language detection.
**Summary**
- log both the client DBC locale and the account database locale when a
player logs in
- fall back to the account locale when the client reports enUS but the
account is configured for another locale
- keep the existing vote-based selection so bots always speak the
majority language among connected players
**Therefore, the original behavior is maintained. Bots still choose the
most represented language among connected players (the counter is simply
more efficient by prioritizing the account's locale when it differs from
the client's English). For example, if more English-speaking players are
connected, the language will revert to English, as the bots always share
the majority locale.**
## Summary
This PR fixes the Crash 1 Source from Issue
[#1840](https://github.com/mod-playerbots/mod-playerbots/issues/1840)
posted in a @Regrad posted logs, in `SeeSpellAction::Execute` when an
RTSC "see spell" event arrives with an empty or malformed `WorldPacket`.
In that case the code used to read from the packet without any
validation, causing a `ByteBufferException` and a crash in the map
thread.
## Fix
- Reset the packet read position and check that the RTSC header
(castCount + spellId + castFlags) fits into the packet before reading.
- Wrap `SpellCastTargets::Read` in a `try { } catch (ByteBufferException
const&) { }` block so truncated RTSC payloads are handled gracefully.
- Check that `targets.GetDst()` is not `nullptr` before accessing its
position.
For valid RTSC packets the behavior is unchanged; malformed packets are
now safely ignored instead of crashing the server.
## Testing
- Sent bots to multiple locations using RTSC and verified they still
move as before.
- Reproduced the previous crash scenario with malformed RTSC packets:
the worldserver no longer crashes and the event is simply ignored.
---------
Co-authored-by: bash <hermensb@gmail.com>
Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
- Move Starfall from default actions to AOE strategy only
- Require 2+ enemies for Starfall usage (prevents single-target casting)
- Add CC safety: avoid casting Starfall near current CC targets
- Prioritize Starfall over Hurricane in medium AOE situations
- Remove Starfall from pull/opener rotation to prevent early
single-target usage
This prevents Balance druids from wasting Starfall on single targets
and breaking crowd control effects in group content.
- Removed double "is" in acknowledgements
- Made the acknowledgements section more grammatical by using "based on"
instead of "based off"
- Corrected misspelling of "implemented"
- Standardized instances of "Playerbots" to `mod-playerbots` or properly
capitalized `Playerbots`
- Minor change of "for the continued contributions" to "for their
continued contributions" in the Acknowledgements section
# Fix bot mount behavior when master dismounts
## Summary
Improves bot mount/dismount logic to ensure better coordination with the
master player. The bot now remains mounted when closing distance to a
recently dismounted master and mounts up to assist the master in combat.
The changes have been tested using the testcases described in the second
half of the PR description, which provide some directions on how this PR
can be tested and verified.
Closes: #1660
## Changes
- Add masterInCombat variable to track master combat state
- Modify target-based logic to consider master combat state
- Change mount priority when bot is not in combat to favor
master-following
- Remove combatReach from distance calculations (duplicate)
## Implementation
Added two methods:
- `StayMountedToCloseDistance()` - prevents premature dismounting when
the master dismounts
- `ShouldMountToCloseDistance()` - determines when to mount for master
assistance, even if master is not mounted at this time
Modified Execute() method:
- Target-based shouldMount/shouldDismount considers the master's combat
state
- Combat assistance logic separated from general following
- Mount when master in combat, but the bot is not
Distance logic:
- Combat: dismount at CalculateDismountDistance() (18-25 yards)
- Non-combat: dismount at 10 yards
- Mount threshold: 21+ yards
## Result
- Bots mount to assist masters in combat
- Bots stay mounted longer during travel
- Different dismount distances based on context
- Existing mount selection logic unchanged
# Mount Behavior Testing
## Prerequisites
1. Add a test bot: `.playerbots bot add <charactername>` or `.playerbots
bot addclass <class>`
2. Test in a level-appropriate outdoor area (mobs should not die with
one hit, as this makes testing combat assistance impossible)
3. Both master and bot must have mounts available
## Test 1: Combat Assistance Mounting
**Objective**: Verify bot mounts to assist the master in combat
**Detailed Steps**:
1. Position both master and bot dismounted
2. Command bot to stay: `/w <botname> stay`
3. Move master 35+ yards away from bot
4. Target a nearby mob and attack the mob
5. Command bot to assist: `/w <botname> follow`
**Expected Results**:
- Bot immediately mounts up (within 1-2 seconds cast time)
- Bot rides toward master while mounted
- Bot dismounts at ~18-25 yards from master/mob
- Bot engages in combat to assist
**Failure Indicators**:
- Bot runs dismounted (old behavior)
- Bot never mounts despite distance
- Bot mounts but doesn't dismount at proper assist range
## Test 2: Non-Combat Dismount Distance
**Objective**: Verify bot stays mounted longer during peaceful travel
**Detailed Steps**:
1. Both master and bot start dismounted
2. Mount up: use any mount
3. Verify bot also mounts: `/w <botname> follow`
4. Travel together for 10+ seconds to establish following
5. While moving, dismount master but continue running
6. Observe bot behavior as you move away
**Expected Results**:
- Bot stays mounted while master runs dismounted
- Bot only dismounts when within ~10 yards of master
## Test 3: Target Interference Prevention
**Objective**: Verify target selection doesn't prevent mounting when
master needs help
**Detailed Steps**:
1. Position bot 35+ yards from master: `/w <botname> stay` then move
away
2. Find a mob visible to both master and bot
3. Target the mob (do not attack): click on mob to select it
4. Verify bot can see the target: `/w <botname> attack` (bot should
respond about target)
5. Cancel bot attack: `/w <botname> follow`
6. Now attack the mob yourself (master enters combat)
7. Observe bot behavior immediately after master engages
**Expected Results**:
- Bot mounts up despite having the same target selected
- Bot rides toward combat area while mounted
- Bot dismounts at assist range (~18-25 yards)
- Target selection does not prevent proper mount behavior
**Failure Indicators**:
- Bot runs dismounted toward target (target interference)
- Bot doesn't mount because it's "focused on target"
## Test 4: Basic Mount Following
**Objective**: Verify fundamental mount matching still works
**Detailed Steps**:
1. Start both master and bot dismounted
2. Ensure bot is following: `/w <botname> follow`
3. Mount up on any available mount
4. Wait 2-3 seconds and observe bot
5. Test different mount speeds if available (60%, 100%, 280% speed)
6. Test dismounting and remounting
**Expected Results**:
- Bot mounts within 2-3 seconds of master mounting
- Bot uses appropriate mount speed to match master
- Bot dismounts when master dismounts (basic following)
- No regression in basic mount following behavior
## Test 5: Distance-Based Mounting Threshold
**Objective**: Verify bot mounts at efficient distance threshold (21+
yards)
**Detailed Steps**:
1. Both master and bot start dismounted in safe area (no mobs)
2. Command bot to stay: `/w <botname> stay`
3. Record starting position: `.gps`
4. Walk exactly 15 yards away (short distance)
5. Command bot to follow: `/w <botname> follow`
6. Observe: bot should run dismounted (distance too short)
7. Command bot to stay again: `/w <botname> stay`
8. Walk to 25+ yards away from bot
9. Record new position: `.gps`
10. Command bot to follow: `/w <botname> follow`
**Expected Results**:
- At 15 yards: Bot runs dismounted (inefficient to mount)
- At 25+ yards: Bot mounts up immediately (efficient distance)
- Distance threshold should be ~21 yards based on mount cast time
efficiency
**Distance Calculation**: Use coordinates from `.gps` to verify exact
distances
## Test 6: Druid Form Integration (Druid Master Required)
**Objective**: Verify druid form compatibility with mount system
**Detailed Steps**:
1. Master must be druid with travel form available
2. Start both dismounted: `/w <botname> follow`
3. Shift master to travel form
4. Observe bot response (should mount or shift if druid)
5. Travel together for 10+ seconds
6. Shift master to normal form while moving
7. Observe bot dismount behavior
8. If available, test flight form in appropriate zones
**Expected Results**:
- Druid bot: matches master's form (travel form)
- Non-druid bot: uses equivalent mount speed
- Form changes trigger appropriate bot responses
- Speed matching works between forms and mounts
## Test 7: Battleground Mount Behavior
**Objective**: Verify mount behavior works in PvP environments
**Detailed Steps**:
1. Queue for battleground with bot in party
2. Enter battleground together
3. Test basic mount following in BG
4. Test flag-carrying restrictions (WSG/EotS)
5. Test mounting during BG combat scenarios
**Expected Results**:
- Bot mounts appropriately in battlegrounds
- Flag carrying prevents mounting
- Combat assistance mounting still works in PvP
Closer the original solution, i dont wanna drift to much away without
really good reason. At this point i still see NPC and bots moving
through the levels or even falling out the levels here and there. I
verified whether the MovePoint signature changes and related params
itself in playerbots has anything todo with it, even when params are
hardcoded the behavior remains. It could be deeper problem, but for now
it seems core problem. Therefore i dont wanna change to much until the
dust has settled a bit in core itself.
I havent implemented moveTakeOff or moveLand which are basically
responsible for the transitions phases between ground and air visa
versa. I have version where i use takeOff for the animation, which means
moving vertical. For now i am gonna leave for what it is.
PS: also includes additional movement fix for AreaTriggerAction which we
missed first time after the core update on movements.
@Wishmaster117 Been testing and trying a lot in the background on find
solutions and causes. The general solutions remains removed some tweaks,
altered code here and there. With the general idea to keep closer to the
original code for now at least.
Testing:
- Class abilities: Slow fall (priest), Flight Form (druid) : Green
- BG: Green
- Swimming and walking shallow waters: Green
- Takeoff and land when following master: Green
- Boat and zeppelins: Green
- Flymount and ground walking: Green
- Water Walking (shaman), Path of Frost (DK): Green
- Water Walking (shaman), Path of Frost (DK) transisions; flying,
swimming, water walking: Green
Skipping pets when group water walking, path of frost, once core pathing
changes has settled more i will add it. Which is easy but i dont wanna
add more edge cases and code branches for now.
I've noticed some sprawl in the README.md. The following edits have been
made around the goal of clarity, brevity, and emphases when needed:
- Removed dead link to the Spanish README.md at the top. The
README_ES.md file itself is not removed from the repo, but is however
out of date and does not seem useful at this time
- Removed the addons section. This seems to be covered by the Wiki in
the Documentation section unless I'm mistaken? We can add these back if
needed
- Reorganized installation instructions to emphasize the importance of
using the Playerbots branch of AzerothCore for all installations
- Moved the platform support from the Frequently Asked Questions section
to the installation instructions
- Modified punctuation of bulleted list. These can return if it irks
someone, but it seems easier to read without them
- Added a encouragement to star the project for updates and gain more
visibility
- Removed the Frequently Asked Questions section. I encourage this to be
covered in a wiki page but it can return if deemed necessary. I think a
lot of it can be moved to other sections if we really need them in there
- Added a "Contributing" section that replaces the Coding Standards
section
- Coding Standards are included in the Contributing section
- Added a second link to the Discord server in the Contributing section
- Removed a link to the main Playerbots branch from the introduction
section. This is covered and emphasized in the installation section
instead
- Migrated the encouragements to make bug reports from the introduction,
along with the message that this is still in active development, to the
contributing section
- Reduced redundant language when not necessary (e.g. "As noted above,")
- Updated language around custom branch and require branch for
uniformity. This will make it more clear to the users about the subject
- Removed "Classic" from the "Classic Installation" terminology for
being inaccurate. The subject is now known simply as "Cloning the
Repositories" while "Docker Installation" still remains distinct. This
will make what was formerly known as "Classic Installation" as de facto
default
- Appended the "Documentation" section with add-on information
- Unified all instances of AddOn to the Blizzard spelling without a
hyphen following the WoW 3.3.5a client spelling
- Appended "AzerothCore" to instances of "branch" to ensure readers they
are, in fact, installing AzerothCore here from our required branch
# Eye of the Storm Flag Capture Behavior
## Previous Behavior
- Bots used to interact with the Netherstorm flag the moment they
reached interaction range, leading to instant pickups even before they
were correctly positioned.
- They did not respect the requirement to stand within the capture ring
or dismount before channeling, so the interaction finished immediately
without the intended delay.
## Current Behavior
- Bots now verify they are inside the Eye of the Storm capture circle
and will reposition toward the center flag or base flag until they are
within 2.5 yards of the game object before starting the channel.
- Once inside the circle they dismount, drop shapeshift forms, and come
to a full stop before beginning the channel cast.
- When channeling the center flag capture spell, bots keep checking for
the ongoing `SPELL_CAPTURE_BANNER` cast and wait for it to finish
instead of attempting repeated instant interactions.
- They will be interrupted if they receice any damage
These adjustments align the Eye of the Storm flow with the retail
mechanics and prevent bots from taking the flag instantly when it
spawns.
Fixes#1700.
# Description
This addresses the infamous "Possible hacking attempt" error when bots
were furiously trying to interact with despawned game objects.
The problem was that the game objects were not being as spawned when
evaluating what the bot should do. It was only done when spells were
being cast on entities.
Fix warnings: -Wsign-compare and -Wsign-compare.
I would also like to mention that there are issues with the following
methods:
`IsMainTank` -- in the last loop, it returns the result of comparing the
first alive tank it finds with the current bot, which seems odd.
`IsBotMainTank` -- it is used in only two places in the code (Yogg-Saron
strategy) and has a completely different logic for checking. In the last
loop, it only checks for a suitable tank-bot with a lower index (if it's
not the bot itself). Additionally, there is a logic issue in the loop:
if none of the conditions are met after the first iteration, the method
returns `false`.
Can someone from the maintainers take a look at this section of the code
for possible errors and logic issues?
This update reorganizes and rewrites the random bot timing configuration
section for clarity and accuracy. The previous section was mislabeled as
"INTERVALS" and lacked precise descriptions. The new version:
1. Renames the header to RANDOM BOT TIMING AND BEHAVIOR
2. Adds concise, standardized comments for each parameter
3. Corrects misleading terminology (not all values are intervals)
4. Documents defaults and actual behavior clearly for easier tuning and
maintenance
5. No functional code changes — documentation and readability only.
Note, this is derived information from reading the code.
Please double check if I have captured each param accurately!
Adds a check for if current master left the BG and group, if so release
set master and carry on in BG.
This prevents multiple bots in (potentially multiple different) BG's to
still consider you as their master when you yourself have left.
- Applies when you join BGs with a party of bots.
Fix for issue #1768 where the bot master was not getting reset.
I also cleaned up leave group action to focus up function scope.
I moved the resets from #612 to the actual leaving function.
Disclosure: LLMs were NOT used in authoring this PR.
Test cases to consider for testers.
1. Master disbands group with random bots. Bots should go about their
business.
2. If you can dual box, create a raid where two real player both invite
random bots. One player leaves group, their bots should also leave.
(edge case, if a random bot that is supposed to leave the group becomes
leader they may disband the whole group.
I'm marking this as a draft for now because I haven't done a detailed
review of the code, but I'm posting it now in case anybody wants to give
it a try.
Here's what the strategy (should) do.
### **Channeler Phase**
While you can probably AoE down all five Hellfire Channelers, that's
more dicey with IP nerfs and it's no fun, so the strategy takes what
would have still been considered an aggressive approach back in the day
by (1) assigning the Main Tank to the first Channeler, (2) having
Hunters misdirect two more Channelers to the MT, and (3) one Off Tank
picking up each of the fourth and fifth Channelers and dragging them out
of Shadow Volley Range from the main group. Sometimes the pull gets a
little wonky and one of the OTs might end up with one of the Channelers
that was intended for the MT, but it should work out in the end.
DPS will move through Channelers from Square -> Star -> Circle ->
Diamond -> Triangle. Once Square, Star, and Circle are down, the MT will
go sit by Magtheridon and wait for him to become active instead of
helping with the last two Channelers. I could have made the MT help with
the fourth Channeler too, but it's not needed, and positioning to pick
up Magtheridon after the third Channeler is a failsafe for low DPS
groups that aren't able to get four down before Magtheridon breaks free.
The top priority for Warlocks is to banish/fear the Burning Abyssals,
and they will continue to do so even after Magtheridon becomes active
(you are not supposed to kill the Abyssals; they have a gazillion HP and
automatically despawn after a minute). Their next priority is to put
Curse of Tongues on the Channelers.
### **Magtheridon Positioning**
The MT will pick up Magtheridon and pull him (moving backwards because
Magtheridon kind of hits like a bus) to a position up against the far
wall. Ranged DPS will spread out from a point roughly in the center of
the room, and Healers will spread out from a point that is a little
closer to Magtheridon. I have not built in aoe avoidance (except for
cube clickers, see below) because the general avoid aoe strategy seems
to work fine for this fight.
### **Clicking Manticron Cubes**
Now, the fun part. Bots will be assigned to clicking cubes by standard
group selection order (reverse join order), but assignment is done via
two passes. The first pass will look to select five ranged DPS bots that
are _not_ Warlocks. This is because Warlocks may still be needed to keep
Abyssals banished/feared and because Warlocks of all three specs put out
by far the most damage of all ranged DPS at level 70 in pre-raid/T4
gear. If there are not five non-Warlock ranged DPS bots available, then
the logic goes to the second pass, which can pick any bot that is not a
Tank.
Cube clicking works on a timer:
1. 48 seconds after Magtheridon breaks free, assigned cube clickers move
near their cubes (but a few yards outside of interact distance). During
this time, they should move around still to avoid Debris (by maintaining
distance from the triggering NPC) and Conflagration (by maintaining
distance from the triggering gameobject). Blast Nova is on a 54.35s to
55.4s timer, and I found 48s to always be ample time to get to the
cubes, but YMMV so this is a good thing to test. Going to a cube too
early not only takes away DPS but also risks more hazards appearing
on/around the cube that will then cause problems when the cube needs to
be clicked.
2. Blast Nova is a 2s cast, followed by a 10s channel (if not
interrupted by the cubes). As soon as the cast begins, bots will move
into interaction range and click the cube. Well, there is a randomized
delay between 200ms (about the fastest possible human reaction time to
visual stimuli) and 1500ms. It didn’t happen to me in a few runs, but it
may be possible that the delay causes the raid to eat one tick of Blast
Nova (I’m not sure if the first blast comes as soon as the channel
starts). Again, another good thing to test, but also one tick is not
going to kill anybody, and it’s arguably good to introduce some degree
of imperfection.
3. Once Blast Nova stops channeling (i.e., all five cubes have been
clicked and channeled simultaneously), bots will interrupt their cube
clicking and go back to regularly scheduled activities. Again, I’ve
introduced a randomized delay, this time between 200ms and 3000ms. Note
that bots can easily be perfect at this—if I don’t do the randomized
delay, they click and let go so fast that you can barely even see the
beams appear. It’s so atrocious for immersion that I consider the lack
of any randomization to be totally unacceptable for this strategy.
4. 48s after Blast Nova, bots will go back to their near-cube positions,
rinse and repeat.
If an assigned cube clicker dies, another bot should be immediately
assigned. All bots in the raid track the same timer so the new bot
should step into the prior bot’s shoes. Of course, if Blast Nova is
about to go off and a clicker dies next to a cube, you’re probably
wiping because I didn’t assign backups to stand in place. That’s too
much of a dad guild-level strategy even for me.
And that’s about it. Figuring out the cubes was a tremendous pain in the
ass, but I’ve really enjoyed the learning process.
---------
Co-authored-by: bash <31279994+hermensbas@users.noreply.github.com>
* Check item score of rings/trinkets to determine the correct slot to equip
* Early return, removed unecessary if statements, single line statements
Simplify logic for equipping items by reducing nested conditions.
* Rewrite RandomPlayerbotFactory - rewrite constructor and utility methods, simplify checks and logic
* Update the comment to clarify the original logic for race selection
* Remove magic numbers from CombineRaceAndGender method (gender)
* Add checks for races and classes disabled during random bot creation
* Implement Gruul's Lair strategy
* minor non-gameplay tweaks to code
* Use multiplier for tank assist
* HKM warlock & Gruul tank tweaks
* Fixed declarations
* rewrote HKM + minor Gruul tweaks
* Update PlayerbotAI.cpp
* modernize code and address comments
* clean ups to tank logic
* Oops.
* Remove post-move delay
For actions like positioning bosses, the standard post-movement delay should be overridden IMO since a player would be sequencing their actions in this type of situation
* Update RaidGruulsLairActions.cpp
* Replace break statements with return true
* enum class to enum
* moved all isuseful checks to triggers
* Split multipliers and improved banish logic
* Update for comments
* changes to int
* use helpers for marking icons
* address compile errors
* correct MoveTo and use RTI helper
* address comments and rename actions/triggers
* adjust alignment of location constants
* fix some crappy returns
* allow return true when changing targets
* change indents and move enums inside namespace
* style changes, trim trailing whitespaces, address comments