Skip to content

Aq40 raid strategy module and encounter logic#2252

Draft
RovxBot wants to merge 53 commits intomod-playerbots:test-stagingfrom
RovxBot:AQ40
Draft

Aq40 raid strategy module and encounter logic#2252
RovxBot wants to merge 53 commits intomod-playerbots:test-stagingfrom
RovxBot:AQ40

Conversation

@RovxBot
Copy link
Copy Markdown

@RovxBot RovxBot commented Mar 28, 2026

Pull Request Description

This PR adds playerbot strategies for all AQ40 bosses, and some of the tougher trash. I will go through each boss strategy in a comment below.

Feature Evaluation

  • Describe the minimum logic required to achieve the intended behavior.
    • Detect that the raid is in an AQ40 encounter and identify which boss encounter is active.
    • Select a valid encounter target for each bot based on role.
      • Tanks need control targets.
      • DPS/healers need assist or safety-aware targets.
    • Override generic bot behavior only where the boss mechanics require it.
      • Target swaps
      • positioning
      • spread/stack rules
      • interrupt/CC reactions
      • add priority
    • Add only the smallest amount of encounter state needed to make those overrides stable.
      • recent teleport/blink windows
      • active phase flags
      • assigned side/tank role
      • temporary hold timers
    • Suppress conflicting generic actions during those mechanics.
      • generic assist target churn
      • unsafe chase movement
      • follow/formation behavior when it breaks the encounter
    • Fall back to normal attack behavior as soon as the special condition ends.
  • Describe the processing cost when this logic executes across many bots.
    The main costs are:
    • Repeated scans over attackers / encounterUnits / nearby units for every bot tick.
    • Name-based boss/add matching across those unit lists.
    • Per-bot role assignment checks like tank, backup tank, ranged, healer, warlock tank, side assignment.
    • Position and distance checks against bosses, adds, anchors, and nearby raid members.
    • Extra trigger evaluations during mechanic-heavy fights like Twins and C'Thun.

How to Test the Changes

Go to AQ40 with bots and run the raid. Twin emps will require warlock tanks

Impact Assessment

  • Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots?
      • No, not at all
      • Minimal impact (explain below)
      • Moderate impact (explain below)

The AQ40 logic does increase per-bot/per-tick work a little, because each bot does extra encounter-unit scans, role checks, and positioning/target evaluations during AQ40 fights. But it is scoped to raid encounters, and the unit sets involved are small enough that this should not scale badly in normal use.

  • Does this change modify default bot behavior?

      • No
      • Yes (explain why)
        Yes. This work intentionally changes default bot behavior inside AQ40 raid encounters.
  • Encounter-specific logic overrides default targeting, movement, spacing, add handling, interrupts, and temporary hold behavior.

  • Does this change add new decision branches or increase maintenance complexity?

      • No
      • Yes (explain below)
  • Each AQ40 boss now has encounter-specific branching for role, phase, target type, aggro state, and positional safety.

  • Shared helpers, triggers, actions, and multipliers all have to stay aligned, so changes in one area can affect encounter behavior elsewhere.

  • Fights like Twin Emperors and C'Thun especially add recovery and edge-case logic, which is harder to maintain than simple target selection.

Messages to Translate

  • Does this change add bot messages to translate?
      • No
      • Yes (list messages in the table)
Message key Default message

AI Assistance

  • Was AI assistance used while working on this change?
      • No
      • Yes (explain below)

I used GPT-5.4 for codebase review, strategy analysis, debugging, and code generation while implementing the AQ40 playerbot strategies.

  • inspect existing raid/playerbot patterns and explain how related strategies are structured
  • help identify likely causes of encounter failures from code and combat-log review
  • propose and generate parts of the AQ40 encounter logic, including triggers, actions, helpers, and follow-up refinements

Because I am not a C++ developer, implementation code was AI-generated, but I reviewed the outputs, tested changes incrementally, and adjusted them to stay consistent with existing playerbot strategy patterns and encounter behavior.

Final Checklist

    • Stability is not compromised.
    • Performance impact is understood, tested, and acceptable.
    • Added logic complexity is justified and explained.
    • Documentation updated if needed (Conf comments, WiKi commands).

Notes for Reviewers

This strategy is currently under development, and AQ40 is still not fully clearable. I have been able to get boss strategies working for bosses up to Twin emps, as well as all the harder trash logic.

Twin emps logic is starting to come together and I have been having better pulls now but it still needs work.
Trash after Twin emps is nightmare fuel, and Cthun has not been tested at all yet.

I am looking for some help and guidance from people far smarter than myself when it comes to this kind of thing.

Thank you!

@RovxBot
Copy link
Copy Markdown
Author

RovxBot commented Mar 28, 2026

AQ40 Trash

  • Bots focus the most dangerous trash first, especially caster and control mobs.
  • They quickly interrupt Mind Blast and react when Mind Flay becomes a threat.
  • If a player gets mind-controlled, bots try to control or peel that target safely.
  • Bots move out of dangerous close-range trash AoE instead of standing in it.
  • Hunters use Tranquilizing Shot on enraged Slayers when they can.
  • Bots dispel Champion vengeance effects when they have the right tools.
  • Fear protection such as Fear Ward and Tremor Totem is used when relevant.
  • Tanks lean toward stabilizing dangerous targets, while non-tanks follow normal kill priority.
  • Bots will not spread for Meteor.
  • Bots will peel off and remove themself from the group if they get plague.

The Prophet Skeram

  • After each blink or teleport, bots quickly find Skeram again.
  • Non-tanks give tanks a brief moment to re-establish control after teleports.
  • Bots interrupt Arcane Explosion when they can.
  • If raid members get mind-controlled, bots switch to controlling those targets.
  • Late in the fight, bots try to focus the real Skeram and finish the weakest valid target cleanly.

Battleguard Sartura

  • The main tank stays on Sartura while backup tanks pick up the Royal Guards.
  • DPS prefer targets that are already under control instead of creating extra chaos.
  • Non-tanks move away during Whirlwind.
  • Ranged and healers give extra space if a spinning target is closing in on them.

Bug Trio

  • Bots stick to a stable kill target instead of bouncing between bosses.
  • They keep the skull-marked target as the focus until it dies.
  • Princess Yauj heal casts are treated as a high interrupt priority.
  • Bots avoid Kri poison clouds, especially near death or while clouds are active.
  • Fear support is used when Yauj starts putting more fear pressure on the raid.

Fankriss the Unyielding

  • Ranged DPS help deal with Spawn of Fankriss.
  • Melee DPS generally stay on Fankriss to keep boss damage going.
  • Tanks only leave the boss for worms when they are free to do so.
  • When possible, tanks split worm pickups instead of piling onto the same one.

Princess Huhuran

  • Bots stay focused on Huhuran during the normal phase.
  • During the poison and frenzy portion of the fight, ranged and healers spread out around the boss.
  • Melee DPS stay in their role instead of drifting into the ranged spread.
  • Tanks keep their normal boss position and do not follow the backline spread pattern.
  • Bots also support the encounter's nature-resistance setup where applicable.

Twin Emperors (In progress)

  • Melee and tanks stay on Emperor Vek'nilash.
  • Ranged DPS focus Emperor Vek'lor.
  • Warlock tanks handle the caster side when that setup is available.
  • Bots try hard to keep the emperors separated and react quickly if Heal Brother becomes a risk.
  • Before teleport, they pre-position so recovery after the swap is smoother.
  • Each role tries to hold its proper side and spacing, with fallback positions if the ideal spot is not reachable.
  • Ranged and healers on the caster side move out for Arcane Burst and react to Blizzard.
  • Some DPS attention is reserved for side bugs on the correct side of the room.
  • Pets are managed so they help on useful side targets and do not grief the encounter by hitting the wrong boss.
  • Non-tank DPS that pull the melee emperor try to move away safely instead of dragging him across the room.
  • Bots also support the encounter's shadow-resistance setup where applicable.

Ouro (not tested)

  • Melee try to stay in contact with Ouro to reduce bad submerge behavior.
  • Scarabs are picked up and killed quickly when they appear.
  • Non-tanks avoid Sweep and Sand Blast.
  • Bots move away from submerge and dirt-mound danger zones instead of standing on them.

Viscidus

  • Bots switch between the boss and globs depending on the current phase.
  • Ranged apply frost damage before Viscidus is frozen.
  • When the split phase starts, bots swap to cleaning up globs.
  • Bots also support the encounter's nature-resistance setup where applicable.

C'Thun (not tested)

  • Tanks hold their assigned positions, while non-tanks outside the stomach spread around the room.
  • Bots avoid clustering near Eye Beam targets so the beam is less likely to chain through the raid.
  • When Dark Glare starts, bots move sideways around the room rather than trying to run straight through it.
  • In phase 2, bots switch to the most dangerous tentacles and adds first.
  • Non-tanks may briefly wait for tanks to secure dangerous claw tentacles before committing.
  • Bots inside the stomach focus flesh tentacles and leave when acid stacks become too risky for their role.
  • During vulnerable windows, bots swap back to burst the main body if add pressure allows it.
  • Eye tentacle casts are interrupted when reachable.
  • While inside the stomach, bots stop trying to do normal spread or room movement and stay focused on stomach jobs.
  • Bots avoid unsafe pathing toward C'Thun or the Eye, especially movement that could send them onto bad vertical geometry.

RovxBot and others added 11 commits April 2, 2026 08:13
Flee corrections
Tank staging corrections
The ChooseTarget early-out check required both current target AND
GetVictim() to match before returning false (no-op).  For melee bots
that had their target set but hadn't reached melee range yet,
GetVictim() returned nullptr — so Attack() re-fired every tick,
consuming the engine's single action slot and permanently blocking
reach-melee from running.

Remove the GetVictim() requirement so the action returns false once
the target is already set, allowing lower-priority movement actions
(reach melee at ACTION_HIGH+1) to execute and walk the bot into range.

Fixed in Aq40TrashChooseTargetAction, Aq40SarturaChooseTargetAction,
and Aq40FankrissChooseTargetAction.
The Aq40TwinEmperorsMultiplier guard used IsTwinRaidCombatActive() as a
fallback, which returns true whenever ANY group member is fighting inside
the 150-yard twin room bounds.  During trash packs near the Twin Emperors
room this made the multiplier activate even though the actual Twin Emperor
bosses were never engaged.

Once active, the multiplier zeroed out reach-melee, dps-assist, charge,
set-behind, combat-formation-move, tank-assist, and follow — leaving
melee bots standing at range with 'no actions executed' every tick.

Fix: remove the twinCombatActive fallback from the guard.  The multiplier
now only activates when Emperor Vek'nilash or Emperor Vek'lor are
actually present in GetTwinEncounterUnits(), which already enriches the
attackers list with visible twins from possible-targets-no-los.  During
the real Twin Emps fight the bosses stay on the threat table through
teleports, so they remain detectable in activeUnits without needing the
room-combat heuristic.
… Flay and Thunderclap

- Replace broad GetAq40TrashDanger with role-aware IsAq40TrashMovementCase
- Remove Eradicator Shock Blast and Warder Fire Nova from trash movement
- Keep only Defender Thunderclap (24y) and Mindslayer Mind Flay (30y)
- Gate trash AoE avoidance on ranged/healer role; melee stay on target
- Replace MoveAway with tank-anchored ComputeTankRetreatPosition helper
  to prevent bots fleeing deeper into uncleared rooms
- Allow ranged/healers with Defender Plague to keep casting/healing when
  already at safe separation distance instead of idling
- Plague separation, Mindslayer interrupt/retarget, and Cause Insanity CC
  paths remain unchanged
- Remove warlock tank skip in IsTwinAssignedTankReady so healers
  position within range during pull instead of waiting 62y away
- Change EnforceSeparation collision fallback to MoveAway(otherBoss)
  instead of MoveTo(desiredBoss) to actively push bosses apart
- Add angle retry loop (±0.3/±0.6 rad) in GetTwinFarSidePosition
  before returning false on collision near walls
- Prioritize Shadow Ward over Curse of Doom in WarlockTankAction
- Grant free Prayer of Shadow Protection (+70 SR) to all warlocks
  during Twin Emperors via the resistance management system
…strategy

- Warlock tank isUseful() now mirrors Execute()'s safety net, allowing
  Searing Pain threat when Vek'lor is reachable but sideEmperor mapping
  disagrees after a teleport swap
- HoldSplit early-out when wanted boss is already in engage range,
  closing the 1-2 tick idle gap after teleport
- HoldSplit returns false at anchor to free action slot for utility
  (Shadow Ward, healthstone) while waiting for teleport
- Separation triggers and action use role-based boss matching
  (warlock->Vek'lor, melee->Vek'nilash) instead of
  IsTwinPrimaryTankOnActiveBoss, fixing the post-swap blind spot
  where neither tank enforced separation
- Separation trigger gate changed from && to || so tanks don't try to
  enforce separation on a boss that is out of LOS or beyond 45y
- Melee DPS positions near Vek'nilash during pre-teleport staging
  instead of running to room centre for zero damage
- ShouldReserveForTwinBug uses proximity-based IsLikelyOnSameTwinSide
  instead of sideEmperor pointer comparison to avoid false positives
  during teleport windows
- Blizzard trigger radius tightened from 36y to 28y to match actual
  effect radius, preventing movement suppression across the entire
  Vek'lor side
- Blizzard avoidance trigger and action check aura presence first,
  bypassing stale sideEmperor mapping so bots dodge even during
  teleport transitions
RovxBot and others added 24 commits April 9, 2026 16:06
Overwrite all src/Ai/Raid/Aq40/ files on AQ40 branch with the exact
versions from master so the PR branch matches the development branch.
…overy

Implement Twin Emperors encounter as a five-state machine:
PrePullStage, OpenerHold, SteadySplit, PreTeleportStage, TeleportRecovery.

Key changes:
- Tanks stay on their side after teleport; far-side tanks hold position
  while same-side tanks engage the boss that teleported in
- ChooseTarget guards against cross-room chasing during recovery by
  checking IsLikelyOnSameTwinSide before moving toward a boss
- HoldSplit uses same-side proximity check instead of tight distance
  thresholds to decide when to yield to engage vs hold at anchor
- Pickup establishment checks (warlock + melee) bypass stale side-index
  filtering and check all designated tanks against boss identity directly
- Melee tank pickup max range widened 10y -> 15y for Uppercut knockback
  tolerance; outer-anchor dot-product relaxed at close range
- Pre-pull staging uses 1200ms retry throttle and collision-aware
  fallback with 7 angle offsets
- Pre-teleport staging suppressed during recovery or unhealthy encounter
- DPS suppressed during OpenerHold and TeleportRecovery until both
  side tanks are established
- Multiplier correctly boosts warlock tank (2.8), hold split (2.4),
  and choose target (2.1) during recovery windows
- HoldSplitAction never returns false during active combat; falls back to
  room-center waypoint with 1200ms retry throttle to prevent dead state
- Reorder role mismatch trigger: hold-split now runs at higher priority
  than choose-target so positioning fires before target pinning
- Identity-based sideEmperor for tanks: warlock tank always assigned
  Vek'lor, melee tank always assigned Vek'nilash regardless of room-side
  mapping, eliminating post-teleport oscillation
- MoveAwayFromBrother returns true when already 55y+ from aggro'd boss,
  preventing EMERGENCY trigger from endlessly consuming ticks
…, warlock pickup speed

- Add isTankBackup flag to TwinAssignments so backup tanks (warlock mod-playerbots#2,
  off-tank) stage on the opposite room-side from their boss, ready for
  immediate pickup after teleport swaps
- Add isUseful() to Aq40EraseTimersAndTrackersAction and IsAlive() guard
  to trigger, preventing priority-91 cleanup from blocking AI ticks
- Reorder warlock tank pickup: Searing Pain first when in range for
  faster threat, Shadow Ward deferred or cast during repositioning
…nd tank far-side chase

Phase 1 - Race condition fix:
- Add IsAnyGroupMemberInTwinRoom() helper to check if any group member
  is inside the Twin Emperors room bounds
- Guard GetStableTwinRoleIndex() cache wipe: don't erase instance-level
  caches (sTwinAssignments, sCachedTwinSplitByX, sTwinSideZeroIsLowSide,
  sTwinKnownTwinBosses) when any group member is in the twin room
- Guard ShouldRunOutOfCombatMaintenance(): return false while any group
  member is in the twin room, preventing erase-timers trigger from firing
- Guard ResetEncounterState() in EraseTimersAndTrackersAction::Execute():
  skip encounter state wipe when group members are staging

Phase 2 - Tank far-side chase fix:
- WarlockTankAction::Execute(): during pickup hold states, if Vek'lor is
  on the far side of the room, hold position and pre-cast Shadow Ward
  instead of chasing across the room
- HoldSplitAction::Execute(): when a tank's designated boss is on the far
  side and out of range/LOS, stop attack and hold instead of MoveNear chase

Phase 3 - Dead code removal:
- Remove unused GetTwinBossSideIndex() from anonymous namespace
- ChooseTarget now handles movement to range on every tick instead of
  returning false when already on correct target. DPS will actually
  move to their boss and attack.
- Hunters prioritize mutate bugs before their normal target.
- Multiplier now suppresses FollowAction during combat (was only
  suppressed during pre-pull), fixing tank oscillation back to player.
- Removed ReachTarget suppression so class AI can move bots to range.
- Removed isUseful() heal filter from ChooseTarget (handled in Execute).
- HoldSplit now properly pins and engages for primary melee tank,
  and pre-casts Shadow Ward for backup warlock tanks.
… and skull marker

Phase 4 - Fix post-Skeram stuck state:
- Remove side-effect in GetObservedSkeramEncounterUnits() that erased
  sSkeramPostBlinkHoldUntilByInstance from within a getter, causing a race
  condition between trigger and action evaluation. The cleanup path in
  ShouldRunOutOfCombatMaintenance() already handles this correctly.

Phase 1 - Add trash target distance cap:
- FindTrashTarget() now pre-filters attackers by 45y distance before
  iterating priority tiers. Falls back to closest active combat unit if
  no priority target is within range. Prevents bots running past nearby
  mobs to chase distant priority targets.

Phase 2 - Prevent Skeram body-pull during trash:
- Aq40SkeramMultiplier suppresses Skeram-specific actions (0.0x) when
  trash is still active alongside Skeram, so bots finish trash first.

Phase 3 - Skull marker for real Skeram:
- Tank marks real Skeram with skull icon (matching Bug Trio pattern).
- FindSkeramTarget() checks skull target first before aggro-based sort.
- Non-tanks skip tank-aggro prerequisite when skull marker exists,
  reducing focus-real-boss failures after blinks.
…vement robustness

- Warlock tank: add 45y distance override to bypass broken IsLikelyOnSameTwinSide
  check from room center (was off by 0.56y, trapping warlock in far-side hold)
- Warlock tank: suppress offensive class AI spells (Corruption/CoA/Shadow Bolt/etc)
  via multiplier so Searing Pain threat rotation isn't overridden
- Healers: position 28y from assigned side boss (outside 18y Arcane Burst, within
  40y heal range) instead of staying at lethal room center
- Movement: all MoveNear/MoveTo calls return true while bot is still en route,
  preventing 'no actions executed' spam from IsDuplicateMove dedup
- Follow: suppress in entire Twin room (IsInTwinEmperorRoom) not just when
  IsTwinPrePullReady is true, fixing pre-pull oscillation
- RTI: mark bosses Diamond (Vek'nilash) / Square (Vek'lor) during pre-pull,
  SetRtiTarget per DPS bot for base AI integration
- Follow suppression: revert to IsTwinPrePullReady gate (LOS to bosses
  required) so bots can still follow through the corridor. The 150y
  IsInTwinEmperorRoom radius was catching bots in the hallway.
- GetTwinSideAnchor: stage 40y from boss toward room center instead of
  at the boss spawn position. Prevents early aggro during pre-pull.
- WarlockTankAction: when far from Vek'lor, MoveNear directly instead
  of pathing to far-side anchor (which sent warlock toward the wall).
  Far-side anchor only used for backing away (too close) and soft
  reposition between casts.
Fix 1 - WarlockTankAction cast-first priority:
  Restructure Execute() so that threat generation (Searing Pain) fires
  BEFORE repositioning whenever the warlock is within 30y with LOS.
  Widen safe casting range from 21-30y to 15-30y (just outside 18y
  Arcane Burst).  The old 9y window caused movement oscillation that
  prevented any casts from firing.

Fix 2 - Pre-pull boss marking:
  PrePullStageAction marking code now falls back to HasTwinVisibleEmperors
  when GetTwinEncounterUnits returns empty (which it always does during
  pre-pull since the attackers list is empty before combat).  Export
  HasTwinVisibleEmperors in the header.

Note: backup tank promotion was removed — tanks stay on their assigned
side permanently.  Each side has one warlock + one melee tank.  The
backup picks up after teleport, not after the other tank dies.
RovxBot added 2 commits April 19, 2026 16:34
Fix 1 - Healer positioning oscillation:
  Replace MoveNear(healBoss, 28y) with MoveTo(exact far-side position).
  MoveNear picks a random angle around the boss, which rarely matches
  the GetFarSidePosition check point.  The healer oscillated between
  'moving' and 'almost in position' every tick, returning true each
  time and consuming the action slot — preventing any heals from
  firing.  Now healers move to the exact computed safe position and
  use 8y tolerance to stay put once arrived.

Fix 2 - Warlock tank GCD gap:
  When Searing Pain is on GCD, the cast-first block now returns true
  immediately (holding the action slot) instead of falling through to
  the positioning code.  Previously, GCD ticks would fall through to
  soft-reposition → return true without casting, creating 41-second
  gaps where the warlock was alive and in range but not casting.
  Now the only movement during GCD is retreat if too close (<15y).

Fix 3 - Shadow Ward during approach:
  Re-add Shadow Ward pre-cast while moving toward Vek'lor from >30y.
…s/pets

Phase 1: Fix warlock side assignment after death/resurrection.
  - GetStableTwinRoleIndex now uses side-aware assignment instead of
    slot-counting. When a warlock returns from death, they get assigned
    to the first unoccupied side, preventing both warlocks on same side.

Phase 2: Melee tank drags Vek'nilash away from Vek'lor.
  - HoldSplitAction primary melee tank uses GetFarSidePosition to tank
    on the far side of Vek'nilash from Vek'lor. This naturally pulls
    Vek'nilash away, preventing Heal Brother (17 clusters in test 4).

Phase 3: Hunter targeting expanded to prioritize Explode Bugs first,
  then Mutate Bugs. Hunter fallback target changed from Vek'lor to
  Vek'nilash (physical damage is IMMUNE on Vek'lor).

Phase 4: Hunter pet redirection. ChooseTargetAction now redirects
  hunter pets to the hunter's target, preventing IMMUNE spam on Vek'lor
  and reducing Shadow Bolt aggro from pets.

Phase 5: Warlock staging distance reduced from 40y to 28y so warlocks
  start within Searing Pain range on pull (fixes 31s engagement delay).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants