mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
26 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
69207acf76 | feat(Core/Loot): Quest GO loot, bag-make-room, item-pursuit | ||
|
|
8ca6e42f10
|
Druid Overhaul (#2392)
<img width="1274" height="952" alt="druids" src="https://github.com/user-attachments/assets/7390d7e5-ed99-4eb3-8802-8c2f457d7c86" /> Hello playerbots community!! After my pvp gear update, I was itching to get back to class strategies. I was testing raids, and noticed that druids... Well, they kinda sucked. They had glaring issues, would randomly die from bugs, and overall felt bad. Looking at issues discussed on github/discord, I decided to start working on a druid update. I started with the boomkin, and made a boomkin PR, but there were some technical issues with the storing of the eclipse mapping not clearing, and it was not good... I closed that PR, and went back to the drawing board, with one goal in mind: Make the druid class function as best as possible WHILST keeping the code consistent with what already exists. There is a TON of _yoink and twist_ (copy and paste with or without slight edits), and anything that is custom/new is discussed in the section below. I am very proud and excited to release this though - after 45 days of coding and testing, the druid finally feels good to have in the group. Disclaimer - this PR aims to address bugs, utility, and overall performance of Druids. It will not magically make them top DPS. I have done hours of testing, and druids can occasionally top the charts - but inconsistently. Boomkins are inconsistent due to Eclipse (until later gear phases), and Feral Cats are incredibly dependent on positioning, timing, combo points, energy, clearcasting procs... The stars have to align for things to go right for the Cat (It doesn't help that all movement, targeting, and actions are ran through the same engine, so cats really suffer in boss fights with scripted movement) But the changes I have made help those situations occur a fair bit more frequently. Let's dive in! <!-- Thank you for contributing to mod-playerbots, please make sure that you... 1. Submit your PR to the test-staging branch, not master. 2. Read the guidelines below before submitting. 3. Don't delete parts of this template. DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND PREDICTABILITY over behavioral realism. Every action and decision executes PER BOT AND PER TRIGGER. Small increases in logic complexity scale poorly across thousands of bots and negatively affect all. We prioritize a stable system over a smarter one. Bots don't need to behave perfectly; believable behavior is the goal, not human simulation. Default behavior must be cheap in processing; expensive behavior must be opt-in. Before submitting, make sure your changes aligns with these principles. --> ## Pull Request Description <!-- Describe what this change does and why it is needed --> A druid overhaul across all four specs — new Cat stealth and CC systems, Eclipse tracking and rotation fixes for Balance, a Bear threat rotation rework, a Resto healing priority overhaul, and a restructured CC and AoE strategy architecture. --- ## Talent & Glyph Config - **Balance:** Moved points out of Improved Moonfire and into Nature's Reach for threat reduction and extended cast range. - **Bear:** Moved points out of King of the Jungle (15% enrage damage) and into Feral Instinct for increased Swipe damage and AoE threat. - **Cat:** Swapped the Glyph of Typhoon (useless for feral) for Glyph of Dash, which benefits the cat a ton in prowl. - **Resto:** Swapped Glyph of Rejuvenation for Glyph of Nourish (better HPS for difficult content), and Glyph of Typhoon (useless for resto) for Glyph of Dash. Moved one point from Nature's Bounty to Empowered Touch. --- ## Balance - **New skill - Typhoon:** Added Typhoon, triggered by "enemy within melee," using cone targeting logic ported from Cone of Cold. Typhoon is from the "balance pvp" spec only, and is housed in the shared AoE strategy. - **New skill - Cyclone:** Added Cyclone targeting the RTI CC-marked target (default moon). Incapacitates for 6 seconds with full damage immunity — cannot be broken by AoE. Priority 24.0f > Hibernate (23.0f) > Entangling Roots (22.0f). *(See CC Implementation in the code notes below.)* - **Bug fix - Eclipse cooldown tracking:** Eclipse procs referenced a cooldown not registered in the database, so boomkins immediately reverted to the wrong filler after an Eclipse buff fell off. Fixed with manual timestamp tracking. *(See Eclipse Cooldown Tracking in the code notes below.)* - **Bug fix — Starfall no longer pulls out-of-combat hostile enemies:** Previously fired on cooldown regardless of surroundings — its 36-yard radius (the largest AoE in the game) could silently pull entire unengaged packs. Now suppressed if any non-combat hostile NPC is within 40 yards. *(See Starfall Pull Safety in the code notes below.)* - **Filler changed to Starfire:** Starfire is now the filler (priority 5.4) over Wrath (5.3). Starfire has a 100% spellpower coefficient vs. Wrath's 12%, is more mana-efficient per point of damage, and has a 100% eclipse proc chance on crit vs. Wrath's 40%. In practice this significantly reduced mana consumption, especially before level 40 when Moonkin Form's mana-on-crit passive isn't available. - **Moonfire / Insect Swarm on Attacker rework:** Previously tied to the light AoE trigger (2+ enemies, 13.0f), causing low-level boomkins to multi-dot instead of casting fillers — mana-inefficient at low levels where targets rarely live long enough to tick the full DoT. Re-added as dedicated on-attacker triggers at lower priority than the fillers, so they fire only as a movement fallback. The triggers have been changed to override the TTL check (time to life), similar to the warlocks DoTs. - **Hurricane channel check rework:** Previously cancelled based on distance from the bot — enemies could leave the AoE but remain within 30 yards, keeping the channel alive. Now reads the Hurricane DynamicObject's actual radius and counts only attackers physically inside it. *(See Hurricane Channel Cancel in the code notes below.)* --- ## Cat - **Prowl (Stealth):** Implemented using the same logic as the existing Rogue stealth system. The bot enters Prowl when out of combat and a target is within range. Engagement distances are: - 30 yards baseline - −10 yards if the target already has a victim (engaged in combat) - −10 more yards if the target is also moving (minimum 10 yards) - +15 yards in Battlegrounds or Arenas - Enemy player targets take priority over grind/DPS targets when evaluating distance. - **Prowl openers:** The bot approaches the target in Prowl and opens based on approach angle and level: - **From behind:** Ravage (learned at level 32). Before Ravage is learned, Shred is used as the opener. - **From the front:** Pounce (stun + bleed, learned at level 36). Before Pounce is learned, Claw is used as the opener. - **New skill - Maim:** Added Maim as a 5 second stun-finisher at 5 combo points, but only against player targets. It will only fire when Rip and Savage Roar are already active. - **Innervate on healer:** Cats now cast Innervate when a healer drops below the low mana threshold (`AiPlayerbot.LowMana`, default 15%). *(See Healer Low Mana Framework in the code notes below for the shared value/trigger infrastructure backing this.)* - **Predator's Swiftness with CC spells:** Added a twotrigger pairing Predator's Swiftness (the instant-cast proc from finishing moves) with the existing CC triggers (Cyclone, Hibernate, Entangling Roots). Feral cats can now instant-cast CC the RTI CC-marked target (default moon) after a finisher using the Predator's Swiftness proc. - **Predator's Swiftness with Rebirth:** Added a twotrigger pairing Predator's Swiftness with the combat resurrection trigger. Cats can now use a Predator's Swiftness proc to instantly cast Rebirth on a dead party member. - **Bug fix - Autoattack no longer breaks prowl:** `MeleeAction::isUseful()` now returns false while the bot has the Prowl aura, preventing autoattack from breaking stealth before an opener spell fires. The code comment notes this pattern should be reused for a future Rogue autoattack in stealth fix. - **Bug fix - Non-prowl skills no longer break prowl:** `isUseful()` overrides were added to Feral Charge (Cat), Mangle (Cat), Swipe (Cat), Rake to return false while Prowl is active, preventing accidental prowl breaks before the opener fires. - **Bug fix - Clearcasting proc with energy spells:** Added dedicated `ClearcastingTrigger` / action pairings to ensure Clearcasting procs are consumed immediately. On single target, Shred is used; on AoE, Swipe (Cat) is used. This prevents the cat from using it's valuable clearcasting proc on a low energy spell (rake, feral charge - cat, cower, etc). This also fixes a bug where Clearcasting would sometimes linger for 4+ seconds without being used, as energy-based spells do not recognize the free cast and would not fire until their energy condition was met. - **Tiger's Fury rework:** TF previously fired on cooldown as a default action, meaning the bot would use it at full or near-full energy and gain no benefit from the energy it generates. The trigger now requires energy to be below 30 before firing, ensuring the bot recovers the full 60 energy granted by the King of the Jungle talent. - **Faerie Fire (Feral) rework for cat:** With Omen of Clarity, spams on cooldown to fish for Clearcasting procs. Without it, applies as a normal debuff and does not reapply while active. *(See Faerie Fire (Feral) Trigger in the code notes below.)* - **Feral Charge toggleable strategy:** Feral Charge (Cat) is now housed in a dedicated `feral charge` strategy, enabled by default for Cat druids. It can be disabled with `co -feral charge` and re-enabled with `co +feral charge`. Disabling this strategy can be useful for encounters where charging in would be unfavorable. - **Rake on Melee Attackers removed:** The Rake on Melee Attackers action was removed from the Cat AoE strategy. Applying Rake to multiple attackers and spreading out combo points produced far lower AoE DPS than simply continuing the single-target rotation. - **Antiquated Omen of Clarity framework removed:** `OmenOfClarityTrigger` and `CastOmenOfClarityAction` were not functional and have been removed. The `ClearcastingTrigger` appropriately tracks Omen of Clarity procs. I believe this was from TBC when Omen of Clarity was a spell. --- ## Bear - **Berserk tracking for Mangle:** A `berserk active` trigger fires Mangle (Bear) at priority 25.0f while Berserk is up. Previously, Mangle sat at 5.5f in the default actions while Swipe (Bear) sat at 25.0f on the light AoE trigger — meaning in any 2+ enemy encounter, Swipe would always win regardless of Berserk. Now Mangle (25.0f) sits above the AoE triggers (24.5f), so it takes priority during Berserk. It's pretty cool to see a Bear's dps on pull! - **Faerie Fire (Feral) rework:** Previously applied once and stopped. Now spams on cooldown for continuous threat generation (~3.5k threat per cast at level 80), and serves as a ranged soft-taunt fallback on the `lose aggro` trigger when Growl is on cooldown. *(See Faerie Fire (Feral) Trigger in the code notes below.)* - **Lacerate rework:** Previously, lacerate was a low priority default action and bears had no duration awareness. They would occasionally let 5 stacks of Lacerate fall off, resulting in pretty significant threat loss. Now, `LacerateTrigger` fires when the target has no Lacerate debuff, the stack count is below 5, or the remaining duration is ≤ 6 seconds. - **Demoralizing Roar on single target:** Previously, Demoralizing Roar only fired on the medium AoE trigger (3+ enemies, skipped on bosses). A dedicated trigger now applies it in any encounter, provided Vindication, Demoralizing Shout, or Curse of Weakness are not already present, as they don't stack with Demoralizing Roar. - **Bug fix - Rebirth on bears:** Bears no longer attempt to cast Rebirth in combat. The generic combat resurrection trigger was firing for all druid specs, causing bears to shift out of Dire Bear Form mid-fight to cast Rebirth — dropping their armor and HP while still holding aggro. Lots of sudden tank deaths... - **Feral Charge toggleable strategy:** Feral Charge (Bear) is now housed in a dedicated `feral charge` strategy, enabled by default for Bear druids. It can be disabled with `co -feral charge` and re-enabled with `co +feral charge`. Disabling this strategy can be useful for encounters where charging in would be unfavorable. --- ## Resto - **Blanketing strategy:** Added a `blanketing` strategy (enabled by default, `co -blanketing` to disable) that pre-HoTs group members with Wild Growth and Rejuvenation regardless of current health, prioritizing tanks → melee → ranged to maximize Revitalize uptime. *(See Blanketing Strategy in the code notes below.)* - **Nature's Swiftness → instant Healing Touch combo:** Nature's Swiftness was previously included in the boost strategy, where it would fire proactively on cooldown regardless of context. This wasted the proc on situations where it provided no benefit. It is now exclusively reactive — triggered at high priority (56.0f) when a party member hits critical health. A paired `nature's swiftness active` trigger then immediately fires Healing Touch (55.0f) on the lowest-health party member, consuming the proc as an instant-cast emergency heal. - **Lifebloom priority lowered (29.0f → 13.0f):** Lifebloom on the main tank is cast on Omen of Clarity procs. At 29.0f it previously outprioritised all low health reactive healing (21.4f), meaning a Clearcasting proc while a party member was at 25–44% HP would cause the bot to cast Lifebloom on the tank instead of Swiftmend or Nourish on the injured target. Lowered to 13.0f so it fires only when no reactive healing is queued. - **Healing spell priority order reworked:** All three reactive categories (critical, low, medium) now follow the same sequence: Swiftmend → Wild Growth → Nourish → Regrowth → Healing Touch. - **Tranquility toggleable strategy:** Tranquility is now housed in a dedicated `tranquility` strategy, enabled by default for Resto druids. It can be disabled with `co -tranquility`. In raids, Tranquility only heals the druid's own group — not the full raid — making it situationally poor during raid-wide damage or heavy movement phases. Disabling this strategy lets players suppress the cast on those encounters without affecting the rest of the healing rotation. --- ## CC & Strategy - **Boost strategy:** The boost strategy is assigned to all druid specs by default. It is spec-gated internally — Balance druids use it for Force of Nature (treants on cooldown), and Feral druids (both cat and bear) use it for Berserk. - **CC strategy enabled by default:** The CC strategy was previously not assigned to druids by default. It is now enabled for Balance and Feral Cat, with behavior gated by spec: - Balance receives the full RTI CC trigger set (Cyclone, Hibernate, Entangling Roots). - Feral cats only receive RTI CC triggers when Predator's Swiftness is active (see above). - **AoE strategy reorganized:** All AoE spells — Hurricane, Starfall, Typhoon, Swipe (Cat), and DoTs on attackers (Moonfire, Insect Swarm) — are now handled by the shared AoE strategy, consistent with how the rest of the playerbot project structures AoE logic. This does not affect Bear druids. - **Aquatic Form while submerged:** The non-combat strategy now shifts into Aquatic Form when the bot is fully submerged out of combat (`LIQUID_MAP_UNDER_WATER`). If the bot is in another shapeshift (Bear, Cat, Moonkin, Tree), it first shifts to caster form as a prerequisite before entering Aquatic Form. The trigger intentionally does not fire at the water surface (`LIQUID_MAP_IN_WATER`), or use the "swimming" trigger, because it caused the druid to loop caster form and aquatic form endlessly while surfaced. --- ## Code Consolidation & Refactoring - The Bear, Cat, Heal, and Caster strategy files have been renamed to Bear, Cat, Balance, and Resto respectively, to match the naming conventions used elsewhere in the project. - The Melee and Offheal strategy files have been deleted. The offheal healing logic is preserved in full — it now lives as an optional strategy (`CatOffhealStrategy`) inside `CatDruidStrategy`, sharing the same action node factories as the base cat strategy rather than duplicating them. - All action relevance values across the druid strategies have been converted from named constants (e.g. `ACTION_NORMAL`, `ACTION_HIGH + 4`) to explicit numerical floats (e.g. `10.0f`, `24.0f`). This makes priority ordering immediately visible in the source without needing to cross-reference the constant definitions. --- ## New Code & Project References ### Eclipse Cooldown Tracking (`DruidActions.cpp`) The previous implementation tracked the Eclipse cooldown using `EclipseSolarCooldownTrigger` and `EclipseLunarCooldownTrigger`, both of which extended `SpellCooldownTrigger` and called `bot->HasSpellCooldown(48517/48518)`. `SpellCooldownTrigger` is the standard project pattern for this — it works correctly for spells whose cooldowns are registered in the database. However, Eclipse (Solar) and Eclipse (Lunar) both have **Cooldown: n/a** in the DB. `HasSpellCooldown` always returned false, so boomkins never respected the cooldown and would revert to the wrong filler immediately after an Eclipse buff fell off. Since the cooldown can't be read from the DB, the fix tracks it manually. When `CastWrathAction::isUseful()` or `CastStarfireAction::isUseful()` detects that the corresponding Eclipse aura has become active, it records the current timestamp and suppresses the opposing filler for 30 seconds — the actual in-game cooldown duration. The timestamps are stored using `ManualSetValue<time_t>`, the same pattern as `LastSpellCastTimeValue` (`src/Ai/Base/Value/LastSpellCastTimeValue.h`), which is already used throughout the project to record when spells were last cast. Two new value classes — `EclipseSolarProcTimeValue` and `EclipseLunarProcTimeValue` — are registered in a new `DruidValueContextInternal` factory inside `DruidAiObjectContext.cpp`, following the same factory pattern as `DruidTriggerFactoryInternal` and `DruidAiObjectContextInternal` in the same file. Because these values live in the per-bot `AiObjectContext`, they are automatically destroyed when the bot logs out — no manual cleanup needed, and no shared state between bots. --- ### Healer Low Mana Framework (`PartyMemberToHeal.h/.cpp`, `HealthTriggers.h/.cpp`, `ValueContext.h`, `TriggerContext.h`) `HealerLowMana` and `HealerLowManaTrigger` are added to the shared base framework rather than the druid-specific code. Currently used by the Cat Innervate trigger; designed so Mana Tide Totem, Hymn of Hope, and similar spells from other classes can hook into the same trigger without duplicating the group-scanning logic. The pair follows the same pattern as the existing `PartyMemberToHeal` / `PartyMemberLowHealthTrigger` — the project's standard design for "scan the group for the most in-need member, then trigger when that member crosses a threshold." **Value** (`HealerLowMana : PartyMemberValue`): `Calculate()` walks the group reference list, skips non-healers via the existing `IsHeal()` check, and uses `MinValueCalculator` to return the lowest-mana healer as a `Unit*`. Registered in `ValueContext.h` under the key `"healer low mana"`. **Trigger** (`HealerLowManaTrigger : Trigger`): `GetTargetName()` returns `"healer low mana"`, which the base `Trigger::GetTarget()` resolves against the value context — exactly how `PartyMemberLowHealthTrigger::GetTargetName()` returns `"party member to heal"`. `IsActive()` calls `GetTarget()` and checks `GetPowerPct(POWER_MANA) < sPlayerbotAIConfig.lowMana`. The trigger doesn't extend `HealthInRangeTrigger` because that class is specifically for health (it reads the `"health"` value). Mana requires a direct `GetPowerPct(POWER_MANA)` call, so a plain `Trigger` with a custom `IsActive()` is used instead. Both are registered in the global `ValueContext.h` and `TriggerContext.h` rather than a class-specific factory, consistent with how all other `PartyMemberValue` subclasses are registered in the project. --- ### Blanketing Strategy (`RestoDruidStrategy.h/.cpp`, `DruidActions.h/.cpp`, `DruidAiObjectContext.cpp`) **Strategy structure:** `DruidBlanketStrategy` is a standalone `Strategy` overlay, not embedded inside `RestoDruidStrategy`. This is the same pattern as `DruidTranquilityStrategy`, `DruidBoostStrategy`, and `DruidCcStrategy` — additive overlays that layer behavior on top of the base strategy and can be toggled independently via `co +/-blanketing`. **Triggers:** Both `"wild growth blanket"` and `"rejuvenation blanket"` are instantiated as `BuffOnPartyTrigger(ai, spellName)` — the project's existing class from `GenericTriggers.h` for party-wide buff maintenance, used throughout the codebase for things like Blessings and Mark of the Wild. `BuffOnPartyTrigger` extends `BuffTrigger` and fires when any party member is missing the named aura. No custom trigger class was needed. **Actions:** Both actions inherit from a shared `CastBlanketHotAction` base that itself extends `CastSpellAction`. Inheriting from `CastSpellAction` means `isPossible()` is handled for free — spell known, off cooldown, target reachable, resources available. The constructor sets `range = botAI->GetRange("heal")` to use the standard healing range. **`GetBlanketTarget(auraName)`:** The custom part of the implementation. Walks the group in three prioritized passes — tanks first, then melee non-tanks, then ranged — returning the first eligible member found. Eligible is defined as: alive, not a GM, within `spellDistance`, and `!botAI->HasAura(auraName, member, false, true)` (not already carrying the HoT). Returns nullptr if every member is already covered. **`isUseful()`:** On both actions simply returns `GetTarget() != nullptr` — fires as long as `GetBlanketTarget` finds someone without the HoT, and suppresses itself the moment all targets are covered. --- ### CC Implementation — Cyclone, Hibernate, Entangling Roots (`DruidTriggers.h/.cpp`, `DruidActions.h/.cpp`, `GenericDruidStrategy.cpp`) The druid CC spells use the project's strict RTI-only pattern rather than the fallback "best candidate" pattern used by other classes (e.g., Mage Polymorph). **`"rti cc target"` value:** A direct raid icon lookup. Reads the `"rti cc"` string value (default `"moon"`, configurable per-bot via `rti cc <icon>`), converts it to a raid icon index, and returns the live `Unit*` for that GUID. If no CC icon is set, it returns `nullptr`. There is no fallback to a best-candidate scan. **Triggers** (`CycloneTrigger`, `HibernateTrigger`, `EntanglingRootsTrigger`): All three extend `HasCcTargetTrigger` and override `IsActive()`. The first check is always `"rti cc target"` — if it returns `nullptr`, the trigger is immediately silent. If an icon is set, it checks `"cc target"` (with the spell name as a qualifier) to verify the RTI target matches and delegates to `HasCcTargetTrigger::IsActive()`, which handles the "don't re-cast while already CC'd" check. **Actions** (`CastCycloneCcAction`, `CastHibernateCcAction`, `CastEntanglingRootsCcAction`): All three extend `CastCrowdControlSpellAction` rather than plain `CastSpellAction`. The action names are `"cyclone on cc"`, `"hibernate on cc"`, `"entangling roots on cc"` — not the raw spell names. This matters because `CastSpellAction` stores its constructor argument as both the action name and the spell name, and `isPossible()` calls `CanCastSpell(spell, target)` using that string. Passing `"cyclone on cc"` to `CastSpellAction` would resolve to spell ID 0 and silently return false forever. `CastCrowdControlSpellAction` keeps the spell name separate from the action name, avoiding this. `GetTargetValue()` on all three returns `context->GetValue<Unit*>("rti cc target")` directly. **Form prerequisite:** The action nodes for `"cyclone on cc"` and `"hibernate on cc"` have `NextAction("caster form")` as a prerequisite, so the bot automatically shifts out of Bear, Cat, or Moonkin form before casting. Entangling Roots has the same prerequisite. **Priority order:** Cyclone (24.0f) > Hibernate (23.0f) > Entangling Roots (22.0f). Cyclone is preferred because it works on any target type and the target is immune to all damage and healing while cycloned — it cannot be broken by AoE. Hibernate is beast/dragonkin only. Entangling Roots can be broken by damage. **Feral Cat CC:** Wired through `TwoTrigger` pairings with `"predator's swiftness"` (see Cat section above). Because the Predator's Swiftness proc makes the spell instant-cast, no form shift is needed — the cat casts directly from Cat Form after a finisher. --- ### Ferocious Bite Execute (`DruidTriggers.h`, `DruidCatActions.h`, `CatDruidStrategy.cpp`) Two separate triggers fire the same `CastFerociousBiteAction`, which is a plain `CastMeleeSpellAction` with no custom logic — all the intelligence lives in the triggers. **`FerociousBiteTimeTrigger`** ("ferocious bite time", 22.5f) — the normal rotation path. Requires 5 combo points, Savage Roar active with >10 seconds remaining, and Rip active on the target with >10 seconds remaining. The duration checks prevent spending combo points on Ferocious Bite when either buff is about to fall off and needs to be refreshed first. **`FerociousBiteExecuteTrigger`** ("ferocious bite execute", 24.0f) — the execute window, higher priority than the time trigger. Requires only 1 combo point, and fires when the target is below **both** 25% HP and 20,000 absolute HP. The dual condition is the key design detail: the 25% threshold alone would trigger on a raid boss at 25% health — which could still be millions of HP remaining. The 20,000 HP cap ensures the execute behavior only activates when the target is genuinely close to death, at which point dumping even a partial combo point buildup into Ferocious Bite is better than continuing a normal builder-spender cycle. --- ### Faerie Fire (Feral) Trigger (`DruidTriggers.h`) A single `FaerieFireFeralTrigger` class handles both Bear and Cat with spec-branched behavior inside `IsActive()`. It extends `DebuffTrigger` — the project's standard class for debuff maintenance on the current target — but overrides `IsActive()` to produce three distinct behaviors depending on form and talent state: **Bear:** Bypasses `DebuffTrigger::IsActive()` entirely. Returns true whenever the target is alive and in world, regardless of whether the debuff is already present. Every cast generates immediate threat and damage, so there is no reason to wait for it to fall off before recasting. **Cat with Omen of Clarity (talent aura 16864):** Same bypass — spams on cooldown to fish for Clearcasting procs. Faerie Fire (Feral) has no energy cost, making it a free input that can proc Omen of Clarity on any hit. **Cat without Omen of Clarity:** Falls through to `DebuffTrigger::IsActive()` — the standard base class behavior, which checks: target alive and in world, debuff not already present (`!botAI->HasAura("faerie fire (feral)", target)`), and estimated remaining lifetime of the target is at least `needLifeTime` seconds (default 8.0f — no point applying a 30-second debuff to something about to die). Applied as a normal debuff; does not reapply while active. Both spam paths additionally guard against Prowl — `IsActive()` returns false while the bot has the Prowl aura to prevent casting from breaking stealth. **Strategy wiring:** - Bear: standard rotation slot at 17.0f, plus wired into the `"lose aggro"` trigger at 25.5f as a soft-taunt fallback when Growl is on cooldown. - Cat: low-priority filler at 5.0f. --- ### Starfall Pull Safety (`DruidActions.cpp`) Starfall's 36-yard AoE radius is the largest in the game. A single cast near an unengaged patrol or mob pack would silently pull everything in that area. The previous implementation fired on cooldown with no awareness of the surrounding area. `CastStarfallAction::isUseful()` now applies two guards before allowing the cast: **CC safety check** (standard project pattern): reads `"current cc target"` and `"aoe position"`; suppresses the cast if the CC'd target is within `aoeRadius` of the bot's AoE position. **Unengaged hostile NPC scan (custom)**: reads `"nearest hostile npcs"` (`NearestHostileNpcsValue`), which uses the project's standard `Acore::AnyUnitInObjectRangeCheck` + `Cell::VisitObjects` grid searcher at `sightDistance` (~50 yards). The value pre-filters via `AcceptUnit()`: non-players only, and `unit->IsHostileTo(bot)` must be true — this excludes neutral-faction trigger creatures, dummies, and invisible spawns that would otherwise appear in a raw range scan. The loop then applies four additional filters: - Skip null / dead / out-of-world units (standard guard). - Skip the current target — it is the reason we're in combat; its in-combat flag is already covered. - Skip `!bot->IsValidAttackTarget(unit)` — safety net for hostile-faction trigger creatures carrying `UNIT_FLAG_NON_ATTACKABLE` that `IsHostileTo` alone doesn't filter. - Skip units beyond 40 yards — Starfall's listed radius is 36; 40 adds a small buffer for patrols about to enter range. If any remaining unit is `!unit->IsInCombat()`, the cast is suppressed — that mob is unengaged and would be pulled. **Why `"nearest hostile npcs"` and not `"attackers"`:** `attackers` only contains units currently targeting the bot. We need to scan all hostile units in the area, not just those already aggro'd. --- ### Hurricane Channel Cancel (`DruidTriggers.h/.cpp`, `GenericDruidStrategy.cpp`) The previous cancel condition checked whether fewer than 3 enemies were within 30 yards of the bot. This is a poor proxy — enemies could scatter laterally but still sit within that radius, keeping the channel alive while none of them were taking damage. The replacement is `HurricaneChannelCheckTrigger`, which locates the actual Hurricane `DynamicObject` on the field and measures from it directly. **`IsActive()` logic:** 1. Checks `bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL)` — if the bot isn't channeling at all, returns false immediately. If it is channeling but the spell isn't a Hurricane rank, also returns false. This check is necessary because `CURRENT_CHANNELED_SPELL` is a slot, not a specific spell — the same cancel action is reused for other channeled spells in the codebase, so the trigger must verify it's specifically Hurricane before acting. 2. Iterates through `HURRICANE_SPELL_IDS` (all five ranks: 16914, 17401, 17402, 27012, 48467) calling `bot->GetDynObject(spellId)` until a non-null result is found. Hurricane places a `DynamicObject` on the field that the server uses as the actual AoE cylinder — each damage tick queries which units are inside it. The DynamicObject is keyed by spell ID, so the trigger must try each rank to find whichever one the bot currently has learned and placed. 3. Reads `dynObj->GetRadius()` — the actual radius stored on the DynamicObject itself rather than a hardcoded constant. This matches exactly what the server uses to calculate damage, so the trigger's cancel condition is spatially identical to the server's hit detection. 4. Walks the `"attackers"` GuidVector and counts how many live attackers are within `dynObj->GetRadius()` of the DynamicObject's position using `unit->GetDistance(dynObj->GetPosition()) <= radius`. 5. Returns `count < minEnemies` (default 3). The trigger fires — cancelling the channel — when fewer than 3 attackers are physically inside the Hurricane AoE. **Why `"attackers"` and not a full area scan:** Hurricane only deals damage to units that are attacking the bot (or in its threat list). Scanning all nearby hostile units would cause premature cancellation if non-aggro'd enemies happened to be standing outside the AoE. Attackers is the right scope. **Strategy wiring:** The trigger is paired with `NextAction("cancel channel", 22.0f)` in the AoE strategy for both Balance and Resto druids. The cancel priority (22.0f) sits below the Hurricane cast priority (23.0f), so if the medium AoE trigger re-activates on the same tick the cancel fires — meaning enemies came back into range — the new cast wins over the cancel. --- ## Feature Evaluation <!-- If your PR is very minimal (comment typo, wrong ID reference, etc), and it is very obvious it will not have any impact on performance, you may skip these question. If necessary, a maintainer may ask you for them later. --> <!-- Please answer the following: --> - Describe the **minimum logic** required to achieve the intended behavior. Most new triggers are simple aura or cooldown checks. The heavier ones are the group scans (for the blanketing HoTs and the healer mana check), but these are identical in cost to group scans already running throughout the project (all of the party member health checks). The Starfall safety check is the only genuinely new scan — it looks for nearby hostile NPCs before allowing a cast, using the same grid search the project already uses elsewhere. That being said, it's loaded on the end of the trigger/action pairing - so in the StarfallNoCDTrigger, the bot has to already have learned starfall, already be in combat, and have Starfall off of cooldown and ready to use. The Hurricane cancel check only runs while the bot is actively channeling, so it's tightly gated. - Describe the **processing cost** when this logic executes across many bots. Negligible for almost everything in this PR. The vast majority of new logic is aura/buff/debuff lookups and cooldown checks that cost nothing at scale. The group scans for blanketing and healer mana follow the same pattern as existing party scans that already run on every healer bot every tick. No new unbounded operations, no shared state between bots. ## How to Test the Changes <!-- - Step-by-step instructions to test the change. - Any required setup (e.g. multiple players, number of bots, specific configuration). - Expected behavior and how to verify it. --> All druids perform a bit better now - I'd say test the branch out with the druids y'all currently use. JUST REMEMBER TO DO reset botAI or talents spec "x" again, since there have been some strategies changed!! The big one being the blanketing strategy for resto druids. They heal so much better now. Also being able to control when they pre-hot is really great. ## Impact Assessment <!-- As a generic test, before and after measure of pmon (playerbot pmon tick) can help you here. --> - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) Tested before an after with the same performance logs. I tested it with a 25 man group of only druids versus my normal 25 man group on several raid bosses - no difference in pmon. - Does this change modify default bot behavior? - - [ ] No - - [x] Yes (**explain why**) Druid bots currently have several bugs/issues with them. This doesn't exactly change the skills they were already using - just refines the scenarios in which they should be used. For example, a boomkin won't use starfall when there is a pack within range but not aggro'd. You can turn off feral charge for cat druids now, so they don't fly into a bosses aoe (locust swarm on anub, overload on iron council). Bear druids don't battle rez anymore. They just feel less clunky and heal/hold aggro better. - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) There are only 2 changes to files outside of the druid strategy, which is the healer low mana framework and the modification to autoattack not being used while in prowl. ## AI Assistance <!-- AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor. We expect contributors to be honest about what they do and do not understand. --> Was AI assistance used while working on this change? - - [ ] No - - [x] Yes (**explain below**) <!-- If yes, please specify: - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation). - Which parts of the change were influenced or generated, and whether it was thoroughly reviewed. --> AI was used heavily in the process to make this PR. First in the research necessary into how systems work, to the initial code implementation, to the testing results (explaining the outcome/why it sucks), to the fix, and then to the review of the code at the end. I will say that after I started researching how to use AI, use .md files for context, clearing sessions, I got a lot better results. I'll be the first to admit that it is 10 times easier to introduce a bug with AI than it is to solve one or implement something new. That is why every time it proposed a change, I asked it if the code was consistent with the project (Already present somewhere else) and if it wasn't, it was heavily scrutinized. It was written with Claude Code with Sonnet 4.6 (high), and peer reviewed by Github copilot. AI also made the description part of the PR, in which I modified myself. <!-- TRANSLATIONS: Anything new that the bots say in chat must be in a translatable format. This is done using GetBotTextOrDefault, which you can search for in the codebase to find examples. Your code needs to have English as the default fallback, while the full translations need to be in an SQL update file. The languages in the file are the nine language options supported by AzerothCore: English, Korean, French, German, Chinese, Taiwanese, Spanish, Spanish Mexico, and Russian. See data/sql/playerbots/updates/2025_12_27_ai_playerbot_fishing_text.sql as an example of a translation SQL update, whose content are called within the codebase at src/strategy/actions/FishingAction.cpp --> ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Any new bot dialogue lines are translated. - - [x] Documentation updated if needed (Conf comments, WiKi commands). **Wiki commands** @Dreathean While this PR does add strategies, they are all enabled by default: co +feral charge (feral druids, both cat and bear) - enabled by default, allows/prevents the use of feral charge co +tranquility (resto druids) - enabled by default, allows/prevents the use of tranquility co +blanketing (resto druids) - enabled by default, allows the druid to pre-hot with wild growth and rejuvenation But it would be worth a mention on the wiki - there are scenarios where having these strategies disabled would be beneficial. ## Notes for Reviewers <!-- Anything else that's helpful to review or test your pull request. --> @kadeshar @Celandriel @brighton-chi Thank you for taking the time to look this over. There is a lot of copied code, a bit of new code (which is explained in the code explanation part of it, but please still ask questions), and a lot of refactoring. Please remember to reset the bot strategies before/after you test this branch, due to the several changes (blanketing, feral charge strategies). Reset with reset botAI or "talents spec balance pve" for any testers out there that didn't know. If/When this PR goes to the master branch, it will need to be noted to the people this same thing about resetting strategies. |
||
|
|
0e0d9fbde2
|
Hand of Freedom fix for Stealth (#2388)
<!-- Thank you for contributing to mod-playerbots, please make sure that you... 1. Submit your PR to the test-staging branch, not master. 2. Read the guidelines below before submitting. 3. Don't delete parts of this template. DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND PREDICTABILITY over behavioral realism. Every action and decision executes PER BOT AND PER TRIGGER. Small increases in logic complexity scale poorly across thousands of bots and negatively affect all. We prioritize a stable system over a smarter one. Bots don't need to behave perfectly; believable behavior is the goal, not human simulation. Default behavior must be cheap in processing; expensive behavior must be opt-in. Before submitting, make sure your changes aligns with these principles. --> ## Pull Request Description <!-- Describe what this change does and why it is needed --> Paladin no longer using Hand of Freedom on Rogue with Stealth Related with: #2385 ## How to Test the Changes <!-- - Step-by-step instructions to test the change. - Any required setup (e.g. multiple players, number of bots, specific configuration). - Expected behavior and how to verify it. --> 1. Invite paladin and rogue to group 2. Start fight 3. Rogue should use Stealth on fight beginning, Paladin should cast Hand of Freedom 4. Apply some snare effect to Rogue bot (for example .aura 1715) 5. Paladin bot should use hand of freedom ## Impact Assessment <!-- As a generic test, before and after measure of pmon (playerbot pmon tick) can help you here. --> - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) - Does this change modify default bot behavior? - - [x] No - - [ ] Yes (**explain why**) - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) ## AI Assistance <!-- AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor. We expect contributors to be honest about what they do and do not understand. --> Was AI assistance used while working on this change? - - [x] No - - [ ] Yes (**explain below**) <!-- If yes, please specify: - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation). - Which parts of the change were influenced or generated, and whether it was thoroughly reviewed. --> <!-- TRANSLATIONS: Anything new that the bots say in chat must be in a translatable format. This is done using GetBotTextOrDefault, which you can search for in the codebase to find examples. Your code needs to have English as the default fallback, while the full translations need to be in an SQL update file. The languages in the file are the nine language options supported by AzerothCore: English, Korean, French, German, Chinese, Taiwanese, Spanish, Spanish Mexico, and Russian. See data/sql/playerbots/updates/2025_12_27_ai_playerbot_fishing_text.sql as an example of a translation SQL update, whose content are called within the codebase at src/strategy/actions/FishingAction.cpp --> ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Any new bot dialogue lines are translated. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers <!-- Anything else that's helpful to review or test your pull request. --> |
||
|
|
94195c3b9b
|
Bots Don't Autoequip Tools & Other Misc Weapons (#2346)
<!-- Thank you for contributing to mod-playerbots, please make sure that you... 1. Submit your PR to the test-staging branch, not master. 2. Read the guidelines below before submitting. 3. Don't delete parts of this template. DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND PREDICTABILITY over behavioral realism. Every action and decision executes PER BOT AND PER TRIGGER. Small increases in logic complexity scale poorly across thousands of bots and negatively affect all. We prioritize a stable system over a smarter one. Bots don't need to behave perfectly; believable behavior is the goal, not human simulation. Default behavior must be cheap in processing; expensive behavior must be opt-in. Before submitting, make sure your changes aligns with these principles. --> ## Pull Request Description <!-- Describe what this change does and why it is needed --> Solve the rest of #2344 Now, bots won't autoequip any weapon from ITEM_SUBCLASS_WEAPON_MISC, which includes all of the basic tools and some other crap that they have no need to autoequip, either. Bots are still eligible to equip those weapons (such as through the "e" command). Note that MISC includes the Argent Tournament lances. I've not played WotLK, but I assume those might be relevant for a strategy. It shouldn't be a problem though because I've intentionally not made bots ineligible for MISC weapons; they just won't consider them upgrades on their own. I also cleaned up ItemUsageValue::QueryItemUsageForEquip to consolidate checks and so on. None of that should be functional, or I screwed up. The check for MISC is on lines 219 through 221. ## Feature Evaluation <!-- If your PR is very minimal (comment typo, wrong ID reference, etc), and it is very obvious it will not have any impact on performance, you may skip these question. If necessary, a maintainer may ask you for them later. --> <!-- Please answer the following: --> - Describe the **minimum logic** required to achieve the intended behavior. - Describe the **processing cost** when this logic executes across many bots. ## How to Test the Changes <!-- - Step-by-step instructions to test the change. - Any required setup (e.g. multiple players, number of bots, specific configuration). - Expected behavior and how to verify it. --> Activate selfbot. Unequip all weapons and have nothing in the inventory except for a MISC weapon such as a skinning knife. Whisper self "equip upgrade"--nothing should happen. Whisper self "e [LINK TO WEAPON]"--the bot should equip the weapon. ## Impact Assessment <!-- As a generic test, before and after measure of pmon (playerbot pmon tick) can help you here. --> - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [ ] No, not at all - - [x] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) There's an extra check but totally meaningless with respect to performance. - Does this change modify default bot behavior? - - [ ] No - - [x] Yes (**explain why**) They won't auto-equip crap that will prevent them from using abilities. - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) ## AI Assistance <!-- AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor. We expect contributors to be honest about what they do and do not understand. --> Was AI assistance used while working on this change? - - [ ] No - - [x] Yes (**explain below**) <!-- If yes, please specify: - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation). - Which parts of the change were influenced or generated, and whether it was thoroughly reviewed. --> I had GPT-5.4 evaluate different spots where I thought an exclusion could be added before settling on this one. <!-- TRANSLATIONS: Anything new that the bots say in chat must be in a translatable format. This is done using GetBotTextOrDefault, which you can search for in the codebase to find examples. Your code needs to have English as the default fallback, while the full translations need to be in an SQL update file. The languages in the file are the nine language options supported by AzerothCore: English, Korean, French, German, Chinese, Taiwanese, Spanish, Spanish Mexico, and Russian. See data/sql/playerbots/updates/2025_12_27_ai_playerbot_fishing_text.sql as an example of a translation SQL update, whose content are called within the codebase at src/strategy/actions/FishingAction.cpp --> ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Any new bot dialogue lines are translated. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers <!-- Anything else that's helpful to review or test your pull request. --> |
||
|
|
ed5791eabf
|
Pull target overlap fix (#2335)
<!-- Thank you for contributing to mod-playerbots, please make sure that you... 1. Submit your PR to the test-staging branch, not master. 2. Read the guidelines below before submitting. 3. Don't delete parts of this template. DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND PREDICTABILITY over behavioral realism. Every action and decision executes PER BOT AND PER TRIGGER. Small increases in logic complexity scale poorly across thousands of bots and negatively affect all. We prioritize a stable system over a smarter one. Bots don't need to behave perfectly; believable behavior is the goal, not human simulation. Default behavior must be cheap in processing; expensive behavior must be opt-in. Before submitting, make sure your changes aligns with these principles. --> ## Pull Request Description <!-- Describe what this change does and why it is needed --> Fixed "pull target" value which was overlap with new pull strategy. Related with #2334 ## How to Test the Changes <!-- - Step-by-step instructions to test the change. - Any required setup (e.g. multiple players, number of bots, specific configuration). - Expected behavior and how to verify it. --> 1. Invite tank bot to party 2. Use `nc +debug` 3. Use command `do attack my target` 4. In debug shouldnt be `reach pull` or similar ## Impact Assessment <!-- As a generic test, before and after measure of pmon (playerbot pmon tick) can help you here. --> - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) - Does this change modify default bot behavior? - - [x] No - - [ ] Yes (**explain why**) - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) ## AI Assistance <!-- AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor. We expect contributors to be honest about what they do and do not understand. --> Was AI assistance used while working on this change? - - [ ] No - - [x] Yes (**explain below**) <!-- If yes, please specify: - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation). - Which parts of the change were influenced or generated, and whether it was thoroughly reviewed. --> To analyze problem with value <!-- TRANSLATIONS: Anything new that the bots say in chat must be in a translatable format. This is done using GetBotTextOrDefault, which you can search for in the codebase to find examples. Your code needs to have English as the default fallback, while the full translations need to be in an SQL update file. The languages in the file are the nine language options supported by AzerothCore: English, Korean, French, German, Chinese, Taiwanese, Spanish, Spanish Mexico, and Russian. See data/sql/playerbots/updates/2025_12_27_ai_playerbot_fishing_text.sql as an example of a translation SQL update, whose content are called within the codebase at src/strategy/actions/FishingAction.cpp --> ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Any new bot dialogue lines are translated. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers <!-- Anything else that's helpful to review or test your pull request. --> |
||
|
|
605f1d7aaa
|
PvP Gear, Autogear Tuning, and Stat Weight Corrections (#2322)
<!-- Thank you for contributing to mod-playerbots, please make sure that you... 1. Submit your PR to the test-staging branch, not master. 2. Read the guidelines below before submitting. 3. Don't delete parts of this template. DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND PREDICTABILITY over behavioral realism. Every action and decision executes PER BOT AND PER TRIGGER. Small increases in logic complexity scale poorly across thousands of bots and negatively affect all. We prioritize a stable system over a smarter one. Bots don't need to behave perfectly; believable behavior is the goal, not human simulation. Default behavior must be cheap in processing; expensive behavior must be opt-in. Before submitting, make sure your changes aligns with these principles. --> ## Pull Request Description <!-- Describe what this change does and why it is needed --> Hello playerbots community! I have been working diligently whilst on vacation to help get pvp gear up and running for pvp specs. Throughout this process, I have looked at our current autogear system, tested it through and through, and made some changes to make gearing more appropriate per spec. _I am going to have my description of the changes in italics_, **and the AI description overview will be bolded.** Let's begin! **This PR makes some improvements to the bot autogear system across item scoring, spec tracking(pvp specs and gear), and stat weights. Changes are split between those that are always active and those controlled by new config options.** **Mandatory Changes:** **PvP Spec Detection (IsSpecPvp) A new method RandomPlayerbotMgr::IsSpecPvp(botGuid, cls) checks the bot's stored specNo against the spec name string defined in config. If the name contains "pvp", the bot is treated as a PvP spec throughout the entire gear pipeline. This is the single source of truth used by both InitEquipment() and ItemUsageValue. In the future this detection can be expanded to drive bot behavior decisions — such as prioritizing dueling players in the world, joining Wintergrasp, or preferring BG and Arena queues over PvE content.** _This is scalable, so if someone were to create their own pvp spec in the config, it would still be tracked if the name contains "pvp". I like the idea of pvp specced random bots having an identifier for pvp events._ **PvP Weights Applied During Loot Evaluation ItemUsageValue::QueryItemUsageForEquip() now calls IsSpecPvp() before scoring a looted item. If the bot is on a PvP spec, it passes SetPvpSpec(true) to the StatsWeightCalculator, ensuring looted items are evaluated with PvP stat priorities (including resilience weighting) rather than PvE weights. Previously, a PvP-specced bot would score loot identically to a PvE bot.** _So, during autogear and upgrade equips, pvp specced bots will now heavily prioritize resilience. On the flip side, pve bots really don't want resilience gear, so a negative weight modifier (penalty for resilience items) has been applied to pve autogearing and upgrade equips. This is important, because you can switch a bot from a pve spec to a pvp spec, and it will automatically consider resilience items in it's inventory as upgrades, and equip them. Same for when you switch a bot from a pvp spec back to a pve spec - the resilience penalty will encourage the bot to switch back to the best available pve gear._ **Resilience Weighting After all per-spec weights are generated in GenerateBasicWeights(), a global resilience modifier is applied unconditionally:** **PvP specs: +7.0 resilience weight — strongly prioritizes resilience gear Non-PvP specs: −3.0 resilience weight — actively discourages resilience gear Resilience is additionally excluded entirely from trinket slot scoring via SetExcludeResilience(true), preventing the PvP resilience bonus from inflating the scores of non-CC trinkets.** _I tried several different numbers here - as high as 10 and as low as 3 for resilience. I ended up with 7 so nearly all specs will slot resilience in every slot EXCEPT for trinkets. I stopped weighing resilience on trinkets because they ended up being garbage trinkets for the most part - other endgame pve trinkets were way more impactful. In my testing, the only class/specs that wont use 100% resilience gears are the tanks, since defense rating/parry/block/dodge weights are so high._ **CC-Break Trinket Cache At server startup, PlayerbotFactory::BuildCcBreakTrinketCache() queries the world database for all trinkets (InventoryType=12, Quality≥2) whose spell IDs include spell 42292 — the CC-break / PvP trinket effect shared by items like Medallion of the Alliance/Horde. Results are sorted by item level descending and cached in a static vector, ready for fast lookup during gearing.** _This creates a cache of cc trinkets on startup, for this:_ **CC-Break Trinket Force-Equip During InitEquipment(), PvP-specced bots at level 50 or higher (level minimum for autogear to apply trinkets) run a pre-selection pass over ccBreakTrinketCache to find the best CC-break trinket they meet the level requirement and quality limit for. Human and Undead bots are excluded from this — they have racial abilities (Every Man for Himself, Will of the Forsaken) that share the PvP trinket cooldown, making a dedicated trinket redundant.** **If a suitable trinket is found, it is stored as pvpTrinket1 and force-equipped into TRINKET1 before the main gear loop runs. If an item already occupies the slot, it is moved to bags first. The second-chance pass also skips TRINKET1 when pvpTrinket1 is set, so the CC trinket is never overwritten.** _This is the catch-all forced pvp trinket for trinket slot 1. In my testing, I really found out how few cc trinkets there are - most of them are epic, and blue ones start showing up super late in the game. An heirloom patch would really help the lower levels, being able to equip a pvp trinket at level 10 or something. Keep in mind, that if your bot isn't getting a pvp trinket with autogear, make sure they aren't human or undead, and check your config for what quality items are allowed with autogear. NOTE - PVP TRINKET STRATEGIES ARE NOT CURRENTLY CODED, SAME WITH CC RACIALS. They will not break out of stun/cc currently. This is for future updates if/when I make a trinketstrategy._ **Enhancement Shaman Dual Wield Fix Classes like Rogues, Frost DKs, and Fury Warriors have their dual wield capability established through class initialization code in the core. Enhancement Shamans acquire Dual Wield only through a specific talent (spell 30798, learned around level 40), and the bot factory had no code to detect and apply this. The result was that Enhancement Shaman bots would sometimes have their offhand weapon unequipped — despite having the talent. After talents are applied in both InitTalentsTree() and InitTalentsBySpecNo(), the code now checks for spell 30798 and explicitly grants SKILL_DUAL_WIELD and SetCanDualWield(true) when present.** _When testing the weapon speed preferences, I noticed that randombot enhancement shamans were unequipping their offhand randomly. They would just walk around with a single 1-hand weapon. This is because they were not considered in the system as dual wielding, so when initequipment or autoequipupgrades was ran, it would unequip the offhand through a function, despite having the dual wield talent. Looking at the code, the other classes already have this flag (warriors, rogues, dks, hunters) because they didn't acquire it through talents._ **CalculateItem() Slot Awareness StatsWeightCalculator::CalculateItem() now accepts an optional slot parameter (default -1). When provided and the item is a weapon, ApplyWeaponSpeedGovernance() can be called. Both item scoring calls inside InitEquipment() — the candidate scoring loop and the incremental old-item comparison — now pass the current equipment slot.** _This change allows the calculate item function to know what slot it's working with, and that's how it modifies it's decision making for some of the optional features below._ **Holy Paladin Weapon Scoring Fix Prior to this change, Holy Paladin could end up equipping 2H weapons because haste and crit sticks (2H weapons) were outscoring appropriate 1H caster weapons — the item type penalty was not catching them correctly. Holy Paladin is now explicitly added to the dual-wield penalty group (preventing 2H weapons from being viable), excluded from the generic caster 1H penalty (since they use 1H + shield rather than a staff), and given a 0.8x soft preference for 1H weapons.** _In autogear testing, sometimes 2h weps with high crit/haste would win over caster gear - this is especially noticeable at lower levels, with shallower item pools (greens only). You'd hit autogear and the holy paladin would equip a 2h axe with crit :( So this makes it so holy paladins only use 1h weapons. They can use either a shield or an offhand, depending on stat weights._ **PvP Spec Slots Added for All Classes The existing RandomClassSpecProb / RandomClassSpecIndex config entries control what percentage of random bots in the world are assigned each spec. Previously only PvE specs (indices 0–2, or 0–3 for Druids) were defined, giving server operators no way to introduce PvP-specced random bots into the world population. This PR adds PvP spec slots for every class (indices 3–6 depending on class), all defaulting to 0 probability. Server operators can raise these values to spawn PvP-specced random bots — e.g., setting RandomClassSpecProb.1.3 = 20 would make 20% of Warrior bots run Arms PvP. Two additional PvE specs have also been added: Death Knight index 3: Double-aura Blood (a hybrid Blood/Frost PvE tank variant) Mage index 3: Frostfire (a PvE hybrid spec) All existing spec entries have been annotated with comments identifying each one (e.g., # arms pve, # holy pve) for readability.** _This change was actually added at the start - I realized that there was no way for pvp-specced randombots to spawn naturally, so I added optional probabilities to the config. They are currently set at 0% by default, but giving the user the option I feel is necessary. Also, it would have been impossible for me to test the init on randombots with pvp gear otherwise. Also, I noticed that the frostfire mage and the dual-aura dk didn't have an option, so I added them in as well, as well as names above each option for quality of life._ **Stat Weight Corrections The following per-spec stat weights were adjusted to better reflect actual WotLK priorities. Entries marked NEW did not previously exist; unmarked rows show old → new values.** <img width="795" height="268" alt="arms warrior" src="https://github.com/user-attachments/assets/cb0deb00-a985-432d-81a1-133fc953088b" /> _Arms warriors would prefer leather/ap gear about half of the time - the combined weights of both would often beat strength gear, especially at lower levels, or where the item pool was shallow. Also, they continued to spawn with spell power gear and defense gear occasionally, especially on gear with resilience (resilience, spell power, crit, haste, stam items)._ <img width="796" height="301" alt="fury warrior" src="https://github.com/user-attachments/assets/715ff3a3-3d20-4e0e-a953-7ed6fd9386db" /> _Fury warriors had the same issues as arms warrior, but really can't afford to lose a strength item - beserker stance increases strength by 20%. Also had to reduce haste here because haste really isn't nearly as important as strength, crit, arp. Haste items would win often over strength/crit/arp gear._ <img width="796" height="300" alt="prot tanks" src="https://github.com/user-attachments/assets/624de09a-2506-4aee-95aa-c49cbc5b85d3" /> _So, prot paladins and prot warriors currently are weighed identically fyi. Look at that whopping 2.0 agility - twice as important as strength? I noticed that my prot paladins/warriors were equipping agility/haste/crit items instead of defense gear on their neck, rings, trinkets, and back. This adjustment pretty much ensures that defense gear takes those slots if it's available. Removed the crit/haste weightings, because realistically if a tank wants more damage, it will just get strength. Lastly added the spell power penalty because prot paladins would spawn in fully holy gear if they were pvp specced (resilience is weighted so high, resilience/spellpower/stam/haste gear would often win). This aims to prevent that._ <img width="802" height="421" alt="dps dks" src="https://github.com/user-attachments/assets/371d1344-2382-4460-b3a7-f38b33025b73" /> _Same issue with plate dps as the warriors had. Spell power gear would occasionally spawn on crit/hit items in pve, and a ton of spell power resilience gear would spawn. There is no scenario where a DK wants spell power, this isn't patch 3.0.1..._ <img width="796" height="447" alt="blood dk" src="https://github.com/user-attachments/assets/c84a2bbf-7daa-4805-acf3-cd3bf815eda4" /> _Similar issues to prot paladin/warrior. I was really tired of seeing block rating/value gear as a result of getting gear with defense/stam. This results in a lot more defense rating/expertise/hit/dodge/parry gear, and basically makes shield stats nearly non-existent (unless the upgrade is good enough, it could still win)_ <img width="794" height="226" alt="ret paladin" src="https://github.com/user-attachments/assets/b09f40ed-b25f-4945-940c-2ce92f81c7c4" /> _Prior to this PR, the positive spellpower and int weights were enough for ret paladins to spawn with spellpower/int/haste/crit gear. This is unlikely now. And agility/ap was reduced to favor more strength gear._ <img width="795" height="306" alt="Enhancement Shaman" src="https://github.com/user-attachments/assets/1e5231fd-36ea-4b7e-a546-cf0075d17bd4" /> _While spell power is a decent stat on enhancment shamans, it was appearing on too much gear, especially on items that were haste/crit/spell power. And for elemental shamans, they were getting agi/haste/crit gear, so this aims to get rid of those items entirely without reducing haste/crit._ <img width="800" height="119" alt="shaman pally" src="https://github.com/user-attachments/assets/6ea3300a-effd-4a03-8f6f-4ae13c5383a5" /> _Holy paladins and resto shamans are scored the same, but this prevents attack power/haste/crit gear, since haste and crit are weighted high._ <img width="1025" height="385" alt="mage" src="https://github.com/user-attachments/assets/03191dfd-dc09-477d-8424-8fd56f3e0d71" /> _Prevents mages from equipping/autogearing items with attack power, some attack power/crit/haste/hit items were winning with shallow item pools._ <img width="1022" height="502" alt="hunter rogue" src="https://github.com/user-attachments/assets/06fa67c9-7709-4ee8-a0e2-34de18594018" /> _Prevents hunters and rogues from getting spell power leather gear with hit/crit. Crit is very heavy for hunters so this was decently common._ **Optional Changes (Config-Controlled)** **AiPlayerbot.PreferClassArmorType (default: 0) Applies a 3x score multiplier to armor matching the bot's class-appropriate type (plate/mail/leather/cloth). A significantly better off-type item can still win — this is a soft preference, not a hard filter.** _Are you tired of your fury warrior being a leather daddy? Are you tired of your holy paladin running around in cloth lingerie? This will fix that. For mail classes (hunters/shamans) and plate classes, this only kicks in after level 40. But it really helps adhere to the highest armor class available. This would be the perfect solution to the quarterly question "Why is my paladin wearing leather?". This definitely should remain optional, as quite a few BIS lists would disagree with it. Leather at certain stages is great for hunters/shamans/warriors/dks._ **AiPlayerbot.AutogearAllowsQuestRewards (default: 0) Builds a cache of equippable armor and weapon quest rewards at startup. Bots can then equip these items during autogear, using the quest's minimum level as the effective required level gate.** _So, I noticed that autogear didn't allow items without a level requirement (quest rewards), because it didn't know how to handle that when giving out gear. It would previously just flat out reject all quest rewards, as they wouldn't be a part of the item pool. This option enables quest rewards to be considered in the item pool, and the level correlates to the lowest level you could get the quest. I have tested this for about 3 hours across all specs and using blue/green gear, it seems like a really nice bonus. Keep in mind that I do 0 quests on my way to 80, so players like me could still benefit from those items. I think this should remain optional._ **AiPlayerbot.EquipAllSlotsAtAnyLevel (default: 0) Bypasses the low-level slot restrictions in InitEquipment(): Trinkets normally locked until level 50 Head/Neck until level 30 Rings until level 20 All other non-weapon slots until level 5** _Autogear currently has level floors for slots - they will not ever give items below the above thresholds. This config option bypasses that. I have not tested this as much as I should have, so as people test this, they could let us know of items that should be blacklisted._ **AiPlayerbot.WeaponSpeedGovernance (default: 0) When enabled, ApplyWeaponSpeedGovernance() applies a 3x score multiplier to weapons matching the spec's ideal attack speed profile. Applies to mainhand, offhand, and ranged slots only. Per-spec preferences: Arms Warrior: Slow 2H (>=3400ms) in mainhand; poleaxes and axes preferred (Axe Specialization) Ret Paladin / Blood & Unholy DK: Slow 2H (>=3400ms) in mainhand Prot Warrior & Paladin: Slow 1H (>=2600ms) in mainhand Fury Warrior dual wield: Slow 1H (>=2600ms) in both hands Fury Warrior titan's grip: Slow 2H (>=3400ms) in both hands Frost DK: Slow 1H (>=2600ms) in both hands; 2H excluded Enhancement Shaman (dual wield): Slow 1H (>=2600ms) in both hands; synchronized MH/OH speeds for flurry procs Enhancement Shaman (pre-dual wield): Slow 2H (>=3400ms) in mainhand Combat Rogue: Slow MH (>=2600ms) + Fast OH (<=1500ms) Assassination / Subtlety Rogue: Slow dagger MH (>=1700ms) + Fast dagger OH (<=1500ms) Hunter: Slow ranged (>=2600ms); melee is a stat stick, speed ignored Feral Druid: No preference (forms normalize attack speed)** _Besides pvp gearing for pvp specs, I feel like this is one of the nicest additions. It was really frustrating to see an enhancement shaman put windfury on a 1.5 dagger. Without this, weights for melee dps are calculated on dps alone, not weapon speed. You'll see 2h specs use fast 2h weapons (3.0), rogues use 2 fast weapons or slow weapons, frost dks occasionally using 2h weapons while having dual wield talents. I tested this for about 6 hours across all mentioned specs at levels 20, 30, 40, 50, 60, 65, 70, 75, and 80, with 3 quality types (greens, blues, purples). I would actually consider making this mandatory, simply because of the impact I saw in the dps charts. Super happy and proud of this._ <img width="1021" height="470" alt="files changes" src="https://github.com/user-attachments/assets/f55d955c-8760-4adf-b4d9-84797da2dc65" /> ## Feature Evaluation <!-- If your PR is very minimal (comment typo, wrong ID reference, etc), and it is very obvious it will not have any impact on performance, you may skip these question. If necessary, a maintainer may ask you for them later. --> <!-- Please answer the following: --> - Describe the **minimum logic** required to achieve the intended behavior. _Two caches are built upon startup - the pvp trinket cache and the quest reward cache. From there, this directly modifies the stat weight calculations involving initequipement (autogear) and autoequipupgrades, as both go off of stat weight calculations. I tried to implement these changes with as little custom functions and coding as possible, and relied as much as I could on the pre-existing framework._ - Describe the **processing cost** when this logic executes across many bots. _Fortunately most of the gates are boolean so it shouldn't impact performance much at all. I ran these changes on my local server with stock 500 bots, noticed no pmon difference from the main branch. Did a 24h stress test on my server yesterday, stats looked consistent with the stress test I did prior to making any changes on 3-31-26._ _It helps that it uses pre-existing functions such as initequipment and autoequipupgrades, and it really just modifies them with slightly more logic. That being said, autogear didn't lag my server at all, nor did the bots equipping upgrades._ ## How to Test the Changes <!-- - Step-by-step instructions to test the change. - Any required setup (e.g. multiple players, number of bots, specific configuration). - Expected behavior and how to verify it. --> _So, with the basic stock playerbots config (do not forget to copy the new config!), the only thing that should change is the pvp gear appearing on pvp specs, and the classes preferring more appropriate stats across the board. You can load into the game, level a bot to 20, autogear, and notice the difference. Same at level 40, 60, 75, or whatever. You could add in the optional config settings to further streamline the gear you want. I currently run with all 4 enabled, 2 of which increase the item pool, and 2 of which help guide them to more appropriate gear (armor/weps)._ ## Impact Assessment <!-- As a generic test, before and after measure of pmon (playerbot pmon tick) can help you here. --> - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) _The code is only used on startup (cache generation) and when autogear/autoequipupgrades is called. Not all the time, and not per tick. I noticed no performance impact after these changes._ - Does this change modify default bot behavior? - - [ ] No - - [x] Yes (**explain why**) _It modifies the decision making as far as equipment goes, but as far as priority/strategies, this does not affect that._ - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) _Not to my knowledge, but I'll rely on testers and the community to let me know if it does._ ## AI Assistance <!-- AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor. We expect contributors to be honest about what they do and do not understand. --> Was AI assistance used while working on this change? - - [ ] No - - [x] Yes (**explain below**) <!-- If yes, please specify: - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation). - Which parts of the change were influenced or generated, and whether it was thoroughly reviewed. --> _AI was used in the research of the initequipment system, stat weights, and cache building. As far as generating the code, using AI was 2 steps forward, 1 step back. I used Claude Code with Sonnet 4.6 (high) and had gemini/copilot review the work. **AI did generate a large portion of the code being used.** I have personally reviewed every line, and a lot was removed out of being obsolete/new system that copied an old one/too many comments. I don't think anything else can be trimmed, though. I also used AI in the PR description, and made my own comments in italics below each entry. I hate explaining/writing._ <!-- TRANSLATIONS: Anything new that the bots say in chat must be in a translatable format. This is done using GetBotTextOrDefault, which you can search for in the codebase to find examples. Your code needs to have English as the default fallback, while the full translations need to be in an SQL update file. The languages in the file are the nine language options supported by AzerothCore: English, Korean, French, German, Chinese, Taiwanese, Spanish, Spanish Mexico, and Russian. See data/sql/playerbots/updates/2025_12_27_ai_playerbot_fishing_text.sql as an example of a translation SQL update, whose content are called within the codebase at src/strategy/actions/FishingAction.cpp --> ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Any new bot dialogue lines are translated. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers <!-- Anything else that's helpful to review or test your pull request. --> _I would like atleast 5-10 people to review this over the next 1-6 months. The big problem I used to have with my PRs was I was acting like they were a sprint, when it's really a marathon - good changes take time, and I was too quick to bust out new content. The old PRs I made introduced just as many new bugs as they did features. I learned my lesson, and have tested this extensively (code was pretty much complete on 4-10-26, been testing alone for the last 11 days) and it's ready for the test realm for others to try out. I think it's going to be a good step forward when it comes to gear decision making for bots as a whole. PvPers have come and gone too much from this project due to the lack of options, and this helps captivate that audience. Please reach out to me on discord at Zhur#4391, I am happy to hear results/suggestions there as well as here._ --------- Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com> |
||
|
|
1967b63bc1
|
Cleanups for Shaman weapon enchant refactor (#2315)
<!--
Thank you for contributing to mod-playerbots, please make sure that
you...
1. Submit your PR to the test-staging branch, not master.
2. Read the guidelines below before submitting.
3. Don't delete parts of this template.
DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND
PREDICTABILITY over behavioral realism.
Every action and decision executes PER BOT AND PER TRIGGER. Small
increases in logic complexity scale
poorly across thousands of bots and negatively affect all. We prioritize
a stable system over a smarter
one. Bots don't need to behave perfectly; believable behavior is the
goal, not human simulation.
Default behavior must be cheap in processing; expensive behavior must be
opt-in.
Before submitting, make sure your changes aligns with these principles.
-->
## Pull Request Description
<!-- Describe what this change does and why it is needed -->
I forgot to include some clean-ups relating to the recent commit to
refactor Shaman weapon enchants. This is just deleting some now unneeded
code and cleaning up a bit of other code.
## Feature Evaluation
<!--
If your PR is very minimal (comment typo, wrong ID reference, etc), and
it is very obvious it will not have
any impact on performance, you may skip these question. If necessary, a
maintainer may ask you for them later.
-->
<!-- Please answer the following: -->
- Describe the **minimum logic** required to achieve the intended
behavior.
- Describe the **processing cost** when this logic executes across many
bots.
## How to Test the Changes
<!--
- Step-by-step instructions to test the change.
- Any required setup (e.g. multiple players, number of bots, specific
configuration).
- Expected behavior and how to verify it.
-->
## Impact Assessment
<!-- As a generic test, before and after measure of pmon (playerbot pmon
tick) can help you here. -->
- Does this change increase per-bot/per-tick processing or risk scaling
poorly with thousands of bots?
- - [x] No, not at all
- - [ ] Minimal impact (**explain below**)
- - [ ] Moderate impact (**explain below**)
- Does this change modify default bot behavior?
- - [x] No
- - [ ] Yes (**explain why**)
- Does this change add new decision branches or increase maintenance
complexity?
- - [x] No
- - [ ] Yes (**explain below**)
## AI Assistance
<!--
AI assistance is allowed, but all submitted code must be fully
understood, reviewed, and owned by the contributor.
We expect contributors to be honest about what they do and do not
understand.
-->
Was AI assistance used while working on this change?
- - [x] No
- - [ ] Yes (**explain below**)
<!--
If yes, please specify:
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation).
- Which parts of the change were influenced or generated, and whether it
was thoroughly reviewed.
-->
<!--
TRANSLATIONS:
Anything new that the bots say in chat must be in a translatable format.
This is done using GetBotTextOrDefault,
which you can search for in the codebase to find examples. Your code
needs to have English as the default fallback,
while the full translations need to be in an SQL update file. The
languages in the file are the nine language
options supported by AzerothCore: English, Korean, French, German,
Chinese, Taiwanese, Spanish, Spanish Mexico, and
Russian. See
data/sql/playerbots/updates/2025_12_27_ai_playerbot_fishing_text.sql as
an example of a translation SQL
update, whose content are called within the codebase at
src/strategy/actions/FishingAction.cpp
-->
## Final Checklist
- - [x] Stability is not compromised.
- - [x] Performance impact is understood, tested, and acceptable.
- - [x] Added logic complexity is justified and explained.
- - [x] Any new bot dialogue lines are translated.
- - [x] Documentation updated if needed (Conf comments, WiKi commands).
## Notes for Reviewers
<!-- Anything else that's helpful to review or test your pull request.
-->
---------
Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com>
Co-authored-by: bash <hermensb@gmail.com>
Co-authored-by: Revision <tkn963@gmail.com>
Co-authored-by: kadeshar <kadeshar@gmail.com>
|
||
|
|
866a73dfbf
|
Clean up unused variables (#2268)
<!--
Thank you for contributing to mod-playerbots, please make sure that
you...
1. Submit your PR to the test-staging branch, not master.
2. Read the guidelines below before submitting.
3. Don't delete parts of this template.
DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND
PREDICTABILITY over behavioral realism.
Every action and decision executes PER BOT AND PER TRIGGER. Small
increases in logic complexity scale
poorly across thousands of bots and negatively affect all. We prioritize
a stable system over a smarter
one. Bots don't need to behave perfectly; believable behavior is the
goal, not human simulation.
Default behavior must be cheap in processing; expensive behavior must be
opt-in.
Before submitting, make sure your changes aligns with these principles.
-->
## Pull Request Description
<!-- Describe what this change does and why it is needed -->
Clean up a bunch of additional unused variable warnings.
## Feature Evaluation
<!--
If your PR is very minimal (comment typo, wrong ID reference, etc), and
it is very obvious it will not have
any impact on performance, you may skip these question. If necessary, a
maintainer may ask you for them later.
-->
<!-- Please answer the following: -->
- Describe the **minimum logic** required to achieve the intended
behavior.
- Describe the **processing cost** when this logic executes across many
bots.
## How to Test the Changes
<!--
- Step-by-step instructions to test the change.
- Any required setup (e.g. multiple players, number of bots, specific
configuration).
- Expected behavior and how to verify it.
-->
## Impact Assessment
<!-- As a generic test, before and after measure of pmon (playerbot pmon
tick) can help you here. -->
- Does this change increase per-bot/per-tick processing or risk scaling
poorly with thousands of bots?
- - [x] No, not at all
- - [ ] Minimal impact (**explain below**)
- - [ ] Moderate impact (**explain below**)
- Does this change modify default bot behavior?
- - [x] No
- - [ ] Yes (**explain why**)
- Does this change add new decision branches or increase maintenance
complexity?
- - [x] No
- - [ ] Yes (**explain below**)
## Messages to Translate
<!--
Bot messages have to be translatable, but you don't need to do the
translations here. You only need to make sure
the message is in a translatable format, and list in the table the
message_key and the default English message.
Search for GetBotTextOrDefault in the codebase for examples.
-->
- Does this change add bot messages to translate?
- - [x] No
- - [ ] Yes (**list messages in the table**)
| Message key | Default message |
| --------------- | ------------------ |
| | |
| | |
## AI Assistance
<!--
AI assistance is allowed, but all submitted code must be fully
understood, reviewed, and owned by the contributor.
We expect contributors to be honest about what they do and do not
understand.
-->
- Was AI assistance used while working on this change?
- - [ ] No
- - [x] Yes (**explain below**)
<!--
If yes, please specify:
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation).
- Which parts of the change were influenced or generated, and whether it
was thoroughly reviewed.
-->
Claude reviewed the warnings log from a build and suggested a series of
changes. I focused just on these warnings for now. Every line was
reviewed. Some sections need to be reviewed by author for intent.
## Final Checklist
- - [x] Stability is not compromised.
- - [x] Performance impact is understood, tested, and acceptable.
- - [x] Added logic complexity is justified and explained.
- - [x] Documentation updated if needed (Conf comments, WiKi commands).
## Notes for Reviewers
<!-- Anything else that's helpful to review or test your pull request.
-->
|
||
|
|
ae9b76aaa5
|
Fix Undead/Draenei bots stuck in starting zones (#2298)
## Pull Request Description
Undead and Draenei bots get stuck in an idle/rest loop in their starting
zones because the default NPC scan range (150f) and quest giver filter
(80f) are too small and not enough. NPCs fall within range for
`WANDER_NPC` to activate (requires >= 3).
This adds a configurable area-based override that increases both ranges
to 200f only in affected areas. All other zones remain at default
values.
## Feature Evaluation
- **Minimum logic**: One `std::set::count()` lookup per `Calculate()`
call to check if the bot's current area is in the override list. If yes,
scan range is 200f instead of 150f.
- **Processing cost**: `GetAreaId()` is a cached uint32 read (~1ns).
`std::set::count()` on a 2-element set is O(log n) ≈ 1 comparison.
Negligible compared to the grid scan itself (~33,000-53,000ns).
## How to Test the Changes
1. Create Undead or Draenei bots (level 1)
2. Observe that they pick up quests and start moving in Deathknell/Ammen
Vale
3. Without this fix, they sit in REST status indefinitely
4. Optionally add/remove area IDs via
`AiPlayerbot.RpgScanRangeOverrideAreaIds` in playerbots.conf
## Impact Assessment
- Does this change increase per-bot/per-tick processing or risk scaling
poorly with thousands of bots?
- [x] Minimal impact
- pmon data (500 bots, extended run):
- Default 150f: 0.033ms avg
- Global 200f: 0.053ms avg
- Area check (this PR): 0.042ms avg
- The 0.009ms increase over default is caused by bots currently in
starting zones scanning at 200f. Bots outside override areas are
unaffected.
- Does this change modify default bot behavior?
- [x] No
- Does this change add new decision branches or increase maintenance
complexity?
- [x] No
- Uses the existing `LoadSet`/`std::set` config pattern already used
throughout the codebase.
## AI Assistance
- [x] Yes
- Used AI to speed up understanding the codebase, locate relevant
functions, and compare with the cmangos playerbots implementation. All
code was reviewed and tested manually.
## Final Checklist
- [x] Stability is not compromised.
- [x] Performance impact is understood, tested, and acceptable.
- [x] Added logic complexity is justified and explained.
- [x] Any new bot dialogue lines are translated.
- [x] Documentation updated if needed (Conf comments, WiKi commands).
## Notes for Reviewers
The root cause is that `WANDER_NPC` requires `possibleTargets.size() >=
3`, but sparse starting zones have fewer than 3 NPC-flagged units within
150f. Increasing the scan range to 200f brings enough NPCs into range
for the status check to pass. The override is configurable via
`AiPlayerbot.RpgScanRangeOverrideAreaIds` so server admins can add more
areas without code changes.
|
||
|
|
7cc00e6283
|
Focus heal targets strategy migration (#2254)
<!--
Thank you for contributing to mod-playerbots, please make sure that
you...
1. Submit your PR to the test-staging branch, not master.
2. Read the guidelines below before submitting.
3. Don't delete parts of this template.
DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND
PREDICTABILITY over behavioral realism.
Every action and decision executes PER BOT AND PER TRIGGER. Small
increases in logic complexity scale
poorly across thousands of bots and negatively affect all. We prioritize
a stable system over a smarter
one. Bots don't need to behave perfectly; believable behavior is the
goal, not human simulation.
Default behavior must be cheap in processing; expensive behavior must be
opt-in.
Before submitting, make sure your changes aligns with these principles.
-->
## Pull Request Description
<!-- Describe what this change does and why it is needed -->
Migration for "focus heal targets" strategy which order healer to focus
only on specified targets
Commands:
`nc +focus heal targets`
`co +focus heal targets`
`focus heal +botName`
`focus heal -botName`
`focus heal ?`
## How to Test the Changes
<!--
- Step-by-step instructions to test the change.
- Any required setup (e.g. multiple players, number of bots, specific
configuration).
- Expected behavior and how to verify it.
-->
- create bots party with at least one healer
- apply to healer strategy
- order healer focus on single bot
- start fight (for example with dummy)
- use `.damage 10000` to bots a watch which are healed directly and
which one only via aoe healing
## Impact Assessment
<!-- As a generic test, before and after measure of pmon (playerbot pmon
tick) can help you here. -->
- Does this change increase per-bot/per-tick processing or risk scaling
poorly with thousands of bots?
- - [x] No, not at all
- - [ ] Minimal impact (**explain below**)
- - [ ] Moderate impact (**explain below**)
- Does this change modify default bot behavior?
- - [x] No
- - [ ] Yes (**explain why**)
- Does this change add new decision branches or increase maintenance
complexity?
- - [x] No
- - [ ] Yes (**explain below**)
## Messages to Translate
<!--
Bot messages have to be translatable, but you don't need to do the
translations here. You only need to make sure
the message is in a translatable format, and list in the table the
message_key and the default English message.
Search for GetBotTextOrDefault in the codebase for examples.
-->
- Does this change add bot messages to translate?
- - [ ] No
- - [x] Yes (**list messages in the table**)
| Message key | Default message |
| --------------- | ------------------ |
focus_heal_not_healer | I''m not a healer or offhealer (please change my
strats to heal or offheal)
focus_heal_provide_names | Please provide one or more player names
focus_heal_no_targets | I don''t have any focus heal targets
focus_heal_current_targets | My focus heal targets are %targets
focus_heal_cleared | Removed focus heal targets
focus_heal_add_remove_syntax | Please specify a + for add or - to remove
a target
focus_heal_not_in_group | I''m not in a group
focus_heal_not_in_group_with | I''m not in a group with %player_name
focus_heal_added | Added %player_name to focus heal targets
focus_heal_removed | Removed %player_name from focus heal targets
## AI Assistance
<!--
AI assistance is allowed, but all submitted code must be fully
understood, reviewed, and owned by the contributor.
We expect contributors to be honest about what they do and do not
understand.
-->
- Was AI assistance used while working on this change?
- - [ ] No
- - [x] Yes (**explain below**)
<!--
If yes, please specify:
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation).
- Which parts of the change were influenced or generated, and whether it
was thoroughly reviewed.
-->
OpenCode, to help migrate strategy
## Final Checklist
- - [x] Stability is not compromised.
- - [x] Performance impact is understood, tested, and acceptable.
- - [x] Added logic complexity is justified and explained.
- - [ ] Documentation updated if needed (Conf comments, WiKi commands).
## Notes for Reviewers
<!-- Anything else that's helpful to review or test your pull request.
-->
From tests:
<img width="515" height="471" alt="obraz"
src="https://github.com/user-attachments/assets/ed6a2bce-e3b1-4fce-ba6f-1a2b10673c61"
/>
Its optional strategy mostly for raiders then performance is not a
issue.
---------
Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com>
Co-authored-by: bash <hermensb@gmail.com>
Co-authored-by: Revision <tkn963@gmail.com>
|
||
|
|
76dd91c4fa
|
Hand of Freedom support (#2233)
<!-- Thank you for contributing to mod-playerbots, please make sure that you... 1. Submit your PR to the test-staging branch, not master. 2. Read the guidelines below before submitting. 3. Don't delete parts of this template. DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND PREDICTABILITY over behavioral realism. Every action and decision executes PER BOT AND PER TRIGGER. Small increases in logic complexity scale poorly across thousands of bots and negatively affect all. We prioritize a stable system over a smarter one. Bots don't need to behave perfectly; believable behavior is the goal, not human simulation. Default behavior must be cheap in processing; expensive behavior must be opt-in. Before submitting, make sure your changes aligns with these principles. --> ## Pull Request Description Added Hand of Freedom action for paladin. Related with: #2002 ## How to Test the Changes <!-- - Step-by-step instructions to test the change. - Any required setup (e.g. multiple players, number of bots, specific configuration). - Expected behavior and how to verify it. --> - invite paladin bot to party - start fight (can use dummy target) - apply some snare effect to bot or yourself (for example `.aura 1715`) - bot should use hand of freedom ## Impact Assessment <!-- As a generic test, before and after measure of pmon (playerbot pmon tick) can help you here. --> - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) - Does this change modify default bot behavior? - - [ ] No - - [x] Yes (**explain why**) Yes, paladin bots start using Hand of Freedom - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) ## Messages to Translate <!-- Bot messages have to be translatable, but you don't need to do the translations here. You only need to make sure the message is in a translatable format, and list in the table the message_key and the default English message. Search for GetBotTextOrDefault in the codebase for examples. --> - Does this change add bot messages to translate? - - [x] No - - [ ] Yes (**list messages in the table**) | Message key | Default message | | --------------- | ------------------ | | | | | | | ## AI Assistance <!-- AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor. We expect contributors to be honest about what they do and do not understand. --> - Was AI assistance used while working on this change? - - [ ] No - - [x] Yes (**explain below**) <!-- If yes, please specify: - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation). - Which parts of the change were influenced or generated, and whether it was thoroughly reviewed. --> OpenCode, as helper to create and review code ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers <!-- Anything else that's helpful to review or test your pull request. --> <img width="424" height="93" alt="obraz" src="https://github.com/user-attachments/assets/3cac4454-35af-474d-8ea0-67c462973c79" /> |
||
|
|
bbd9d3e37a
|
Wait for attack strategy migration (#2211)
## Pull Request Description Migration of "wait for attack" strategy from cmangos playerbots. Resolves: https://github.com/mod-playerbots/mod-playerbots/issues/990 ## Feature Evaluation Optional strategy for bots which are in party with real player. ## How to Test the Changes - add strategy to bot "nc +wait for attack" and "co +wait for attack" - set time via command "wait for attack time x" where x is time which they wait in seconds (you should get response from bot) - attack any target (for example dummy in main city)(bot should wait with attack) ## Impact Assessment - [ ] No, not at all - [x] Minimal impact (**explain below**) - [ ] Moderate impact (**explain below**) Performance wise only bots having this optinal strategy have additional cost in multiplier which check every attack action that should be execute. - Does this change modify default bot behavior? - [x] No - [ ] Yes (**explain why**) - Does this change add new decision branches or increase maintenance complexity? - [x] No - [ ] Yes (**explain below**) ## Messages to Translate Does this change add bot messages to translate? - [ ] No - [x] Yes (**list messages in the table**) | Message key | Default message | | --------------- | ------------------ | 1740 | Please provide a time to set (in seconds) 1741 | Please provide valid time to set (in seconds) between 0 and 99 1742 | Wait for attack time set to %new_time seconds ## AI Assistance Was AI assistance used while working on this change? - [ ] No - [x] Yes (**explain below**) <!-- If yes, please specify: - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation). - Which parts of the change were influenced or generated, and whether it was thoroughly reviewed. --> Copilot CLI - help with migration ## Final Checklist - [x] Stability is not compromised. - [x] Performance impact is understood, tested, and acceptable. - [x] Added logic complexity is justified and explained. - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers <!-- Anything else that's helpful to review or test your pull request. --> |
||
|
|
d0d1171e06
|
Fixed typo (#2230)
<!--
Thank you for contributing to mod-playerbots, please make sure that
you...
1. Submit your PR to the test-staging branch, not master.
2. Read the guidelines below before submitting.
3. Don't delete parts of this template.
DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND
PREDICTABILITY over behavioral realism.
Every action and decision executes PER BOT AND PER TRIGGER. Small
increases in logic complexity scale
poorly across thousands of bots and negatively affect all. We prioritize
a stable system over a smarter
one. Bots don't need to behave perfectly; believable behavior is the
goal, not human simulation.
Default behavior must be cheap in processing; expensive behavior must be
opt-in.
Before submitting, make sure your changes aligns with these principles.
-->
## Pull Request Description
<!-- Describe what this change does and why it is needed -->
Fixed typo
## How to Test the Changes
<!--
- Step-by-step instructions to test the change.
- Any required setup (e.g. multiple players, number of bots, specific
configuration).
- Expected behavior and how to verify it.
-->
- compile test-staging with 20260320-ac-merge
## Impact Assessment
<!-- As a generic test, before and after measure of pmon (playerbot pmon
tick) can help you here. -->
- Does this change increase per-bot/per-tick processing or risk scaling
poorly with thousands of bots?
- - [x] No, not at all
- - [ ] Minimal impact (**explain below**)
- - [ ] Moderate impact (**explain below**)
- Does this change modify default bot behavior?
- - [x] No
- - [ ] Yes (**explain why**)
- Does this change add new decision branches or increase maintenance
complexity?
- - [x] No
- - [ ] Yes (**explain below**)
## Messages to Translate
<!--
Bot messages have to be translatable, but you don't need to do the
translations here. You only need to make sure
the message is in a translatable format, and list in the table the
message_key and the default English message.
Search for GetBotTextOrDefault in the codebase for examples.
-->
Does this change add bot messages to translate?
- - [x] No
- - [ ] Yes (**list messages in the table**)
| Message key | Default message |
| --------------- | ------------------ |
| | |
| | |
## AI Assistance
<!--
AI assistance is allowed, but all submitted code must be fully
understood, reviewed, and owned by the contributor.
We expect contributors to be honest about what they do and do not
understand.
-->
Was AI assistance used while working on this change?
- - [x] No
- - [ ] Yes (**explain below**)
<!--
If yes, please specify:
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation).
- Which parts of the change were influenced or generated, and whether it
was thoroughly reviewed.
-->
## Final Checklist
- - [x] Stability is not compromised.
- - [x] Performance impact is understood, tested, and acceptable.
- - [x] Added logic complexity is justified and explained.
- - [x] Documentation updated if needed (Conf comments, WiKi commands).
## Notes for Reviewers
<!-- Anything else that's helpful to review or test your pull request.
-->
|
||
|
|
9f875a7c81
|
CoreUpdate - ThreatMgr (#2228)
<!--
Thank you for contributing to mod-playerbots, please make sure that
you...
1. Submit your PR to the test-staging branch, not master.
2. Read the guidelines below before submitting.
3. Don't delete parts of this template.
DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND
PREDICTABILITY over behavioral realism.
Every action and decision executes PER BOT AND PER TRIGGER. Small
increases in logic complexity scale
poorly across thousands of bots and negatively affect all. We prioritize
a stable system over a smarter
one. Bots don't need to behave perfectly; believable behavior is the
goal, not human simulation.
Default behavior must be cheap in processing; expensive behavior must be
opt-in.
Before submitting, make sure your changes aligns with these principles.
-->
## Pull Request Description
<!-- Describe what this change does and why it is needed -->
Modification to threat system required for current core update PR.
## Feature Evaluation
<!--
If your PR is very minimal (comment typo, wrong ID reference, etc), and
it is very obvious it will not have
any impact on performance, you may skip these question. If necessary, a
maintainer may ask you for them later.
-->
<!-- Please answer the following: -->
- Describe the **minimum logic** required to achieve the intended
behavior.
- Describe the **processing cost** when this logic executes across many
bots.
## How to Test the Changes
<!--
- Step-by-step instructions to test the change.
- Any required setup (e.g. multiple players, number of bots, specific
configuration).
- Expected behavior and how to verify it.
-->
## Impact Assessment
<!-- As a generic test, before and after measure of pmon (playerbot pmon
tick) can help you here. -->
- Does this change increase per-bot/per-tick processing or risk scaling
poorly with thousands of bots?
- - [x] No, not at all
- - [ ] Minimal impact (**explain below**)
- - [ ] Moderate impact (**explain below**)
- Does this change modify default bot behavior?
- - [x] No
- - [ ] Yes (**explain why**)
- Does this change add new decision branches or increase maintenance
complexity?
- - [x] No
- - [ ] Yes (**explain below**)
## Messages to Translate
<!--
Bot messages have to be translatable, but you don't need to do the
translations here. You only need to make sure
the message is in a translatable format, and list in the table the
message_key and the default English message.
Search for GetBotTextOrDefault in the codebase for examples.
-->
Does this change add bot messages to translate?
- - [x] No
- - [ ] Yes (**list messages in the table**)
| Message key | Default message |
| --------------- | ------------------ |
| | |
| | |
## AI Assistance
<!--
AI assistance is allowed, but all submitted code must be fully
understood, reviewed, and owned by the contributor.
We expect contributors to be honest about what they do and do not
understand.
-->
Was AI assistance used while working on this change?
- - [ ] No
- - [x] Yes (**explain below**)
<!--
If yes, please specify:
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation).
- Which parts of the change were influenced or generated, and whether it
was thoroughly reviewed.
-->
Claude. Module search for changes made. It also identified a section of
dead code in EnemyPlayerValue due to incorrect ref that was fixed.
## Final Checklist
- - [X] Stability is not compromised.
- - [X] Performance impact is understood, tested, and acceptable.
- - [X] Added logic complexity is justified and explained.
- - [X] Documentation updated if needed (Conf comments, WiKi commands).
## Notes for Reviewers
<!-- Anything else that's helpful to review or test your pull request.
-->
|
||
|
|
2ce8993986
|
Correct Loot rolling behavior (#2190)
# Pull Request This fixes the loot rolling behavior issue created by #2068 . Introduce the ability for enchanter bots to disenchant items they dont need, and roll need on recipes they also need. Make it so ITEM_USAGE_AH ensures the item is not BOP. Try to reduce the call for item_usage in CalculateRollVote by passing usage if available. --- ## Design Philosophy We prioritize **stability, performance, and predictability** over behavioral realism. Complex player-mimicking logic is intentionally limited due to its negative impact on scalability, maintainability, and long-term robustness. Excessive processing overhead can lead to server hiccups, increased CPU usage, and degraded performance for all participants. Because every action and decision tree is executed **per bot and per trigger**, even small increases in logic complexity can scale poorly and negatively affect both players and world (random) bots. Bots are not expected to behave perfectly, and perfect simulation of human decision-making is not a project goal. Increased behavioral realism often introduces disproportionate cost, reduced predictability, and significantly higher maintenance overhead. Every additional branch of logic increases long-term responsibility. All decision paths must be tested, validated, and maintained continuously as the system evolves. If advanced or AI-intensive behavior is introduced, the **default configuration must remain the lightweight decision model**. More complex behavior should only be available as an **explicit opt-in option**, clearly documented as having a measurable performance cost. Principles: - **Stability before intelligence** A stable system is always preferred over a smarter one. - **Performance is a shared resource** Any increase in bot cost affects all players and all bots. - **Simple logic scales better than smart logic** Predictable behavior under load is more valuable than perfect decisions. - **Complexity must justify itself** If a feature cannot clearly explain its cost, it should not exist. - **Defaults must be cheap** Expensive behavior must always be optional and clearly communicated. - **Bots should look reasonable, not perfect** The goal is believable behavior, not human simulation. Before submitting, confirm that this change aligns with those principles. --- ## Feature Evaluation Please answer the following: - Describe the **minimum logic** required to achieve the intended behavior? -- Add a new check that downgrades greed rolls to desired levels, or bools for the other two options. - Describe the **cheapest implementation** that produces an acceptable result? -- As implemented. - Describe the **runtime cost** when this logic executes across many bots? -- Same as before. Item usage is the heaviest part, and that hasnt changed to accommodate this. --- ## How to Test the Changes - multiple bots in a group with group loot on, do a dungeon or something. One bot should be an enchanter. ## Complexity & Impact Does this change add new decision branches? - - [ ] No - - [x] Yes (**explain below**) Does this change increase per-bot or per-tick processing? - - [X] No - - [ ] Yes (**describe and justify impact**) Could this logic scale poorly under load? - - [X] No - - [ ] Yes (**explain why**) --- ## Defaults & Configuration Does this change modify default bot behavior? - - [ ] No - - [X] Yes (**explain why**) - - - Corrects the looting behavior to original design. If this introduces more advanced or AI-heavy logic: - - [ ] Lightweight mode remains the default - - [X] More complex behavior is optional and thereby configurable --- ## AI Assistance Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change? - - [x] No - - [ ] Yes (**explain below**) --- ## Final Checklist - - [x] Stability is not compromised - - [x] Performance impact is understood, tested, and acceptable - - [x] Added logic complexity is justified and explained - - [x] Documentation updated if needed --- ## Notes for Reviewers Anything that significantly improves realism at the cost of stability or performance should be carefully discussed before merging. |
||
|
|
439293e100
|
Warnings PR 2 clean unused variables (#2107)
# Pull Request
Removed unused variables and fixed styling issues.
## How to Test the Changes
- Step-by-step instructions to test the change
- Any required setup (e.g. multiple players, bots, specific
configuration)
- Expected behavior and how to verify it
## Complexity & Impact
- Does this change add new decision branches?
- [x] No
- [] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [x] No
- [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [x] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [x] No
- [ ] Yes (**explain why**)
If this introduces more advanced or AI-heavy logic:
- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
- [x] No
- [ ] Yes (**explain below**)
---
## Final Checklist
- [x] Stability is not compromised
- [x] Performance impact is understood, tested, and acceptable
- [x] Added logic complexity is justified and explained
- [x] Documentation updated if needed
---
## Notes for Reviewers
This was filtered from the code provided by SmashingQuasar. Eliminated
variables were confirmed to be not used, but unclear at times if that is
due to mistakes in writing.
---------
Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
|
||
|
|
629aa19dbd
|
Add aggressive non combat targeting strategy (#2117)
# Pull Request Tired of failing that escort quest because your bots stood and watched while the escort npc got swarmed and killed? Tired of your bots standing around doing nothing while the npc you are supposed to be guarding for 5 minutes is getting attacked? Don't want to use the grind strategy because it is too heavy-handed and has too many restrictions? Look no further! Just do "nc +aggressive" and your bots will pick a fight with anything they can in a 30 yard radius. The aggressive targetting is a stripped down version of the grind target. ## Feature Evaluation Please answer the following: - Describe the **minimum logic** required to achieve the intended behavior? Add a strategy, action, and targetting that will cause bots to attack nearby enemies when out of combat. - Describe the **cheapest implementation** that produces an acceptable result? Hopefully this is the cheapest. - Describe the **runtime cost** when this logic executes across many bots? Minimal runtime cost as this strategy needs to be added specifically to bots. --- ## How to Test the Changes - Add a bot to party, or use selfbot - Give them the aggressive strategy via "nc +aggressive" - They should attack anything within 30 yards. - If it is a bot with a master, the 30 yards should be centered around the master not the bot (prevent chaining from enemy to enemy) ## Complexity & Impact Does this change add new decision branches? ``` [] No [x] Yes (**explain below**) Only for bots that have the added strategy, adds decision to attack nearby targets when out of combat. ``` Does this change increase per-bot or per-tick processing? ``` [] No [x] Yes (**describe and justify impact**) Minimal increase to only bots that have this strategy added. ``` Could this logic scale poorly under load? ``` [x] No [ ] Yes (**explain why**) ``` --- ## Defaults & Configuration Does this change modify default bot behavior? ``` [x] No [ ] Yes (**explain why**) ``` If this introduces more advanced or AI-heavy logic: ``` [x] Lightweight mode remains the default [ ] More complex behavior is optional and thereby configurable ``` --- ## AI Assistance Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change? ``` [ ] No [x] Yes (**explain below**) ``` Claude is used to explore the codebase to find similar implementations to be used for examples. --- ## Final Checklist - [x] Stability is not compromised - [x] Performance impact is understood, tested, and acceptable - [x] Added logic complexity is justified and explained - [x] Documentation updated if needed --- ## Notes for Reviewers Anything that significantly improves realism at the cost of stability or performance should be carefully discussed before merging. |
||
|
|
2f7dfdbbfc
|
Fix rest of trainers' related stuff + codestyle changes and corrections (#2104)
# Pull Request
* Fix the rest of the trainer-related functionality: list spells and
learn (cast vs. direct learn) spells.
* Rewrite `TrainerAction`: split the logic between appropriate methods
(`GetTarget`, `isUseful`, `isPossible`) instead of pushing everything
inside a single `Execute` method.
* Change method definitions to remove unnecessary declarations and
parameters overhead.
* Move the `Trainer` header into the implementation. Rewrite
`RpgTrainTrigger` to fit the original logic and move all validation to
`RpgTrainAction` (`isUseful` + `isPossible`).
* Implement "can train" context value calculation to use with
`RpgTrainTrigger`.
* Update and optimize "train cost" context value calculation -- it
should be much faster.
* Replace `AiPlayerbot.AutoTrainSpells` with
`AiPlayerbot.AllowLearnTrainerSpells` and remove the "free" value
behavior — please use `AiPlayerbot.BotCheats` if you want bots to learn
trainer's spells for "free".
* Add `nullptr` checks wherever necessary (only inside targeted
methods/functions).
* Make some codestyle changes and corrections based on the AC codestyle
guide.
---
## Design Philosophy
We prioritize **stability, performance, and predictability** over
behavioral realism.
Complex player-mimicking logic is intentionally limited due to its
negative impact on scalability, maintainability, and
long-term robustness.
Excessive processing overhead can lead to server hiccups, increased CPU
usage, and degraded performance for all
participants. Because every action and
decision tree is executed **per bot and per trigger**, even small
increases in logic complexity can scale poorly and
negatively affect both players and
world (random) bots. Bots are not expected to behave perfectly, and
perfect simulation of human decision-making is not a
project goal. Increased behavioral
realism often introduces disproportionate cost, reduced predictability,
and significantly higher maintenance overhead.
Every additional branch of logic increases long-term responsibility. All
decision paths must be tested, validated, and
maintained continuously as the system evolves.
If advanced or AI-intensive behavior is introduced, the **default
configuration must remain the lightweight decision
model**. More complex behavior should only be
available as an **explicit opt-in option**, clearly documented as having
a measurable performance cost.
Principles:
- **Stability before intelligence**
A stable system is always preferred over a smarter one.
- **Performance is a shared resource**
Any increase in bot cost affects all players and all bots.
- **Simple logic scales better than smart logic**
Predictable behavior under load is more valuable than perfect decisions.
- **Complexity must justify itself**
If a feature cannot clearly explain its cost, it should not exist.
- **Defaults must be cheap**
Expensive behavior must always be optional and clearly communicated.
- **Bots should look reasonable, not perfect**
The goal is believable behavior, not human simulation.
Before submitting, confirm that this change aligns with those
principles.
---
## How to Test the Changes
Force bots to learn spells from trainers using the chat command `trainer
learn` or `trainer learn <spellId>`. Bots should properly list available
spells (`trainer` command) or learn them (based on configuration and
command).
## Complexity & Impact
- Does this change add new decision branches?
- [x] No
- [ ] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [x] No
- [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [x] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [x] No
- [ ] Yes (**explain why**)
If this introduces more advanced or AI-heavy logic:
- [x] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
- [x] No
- [ ] Yes (**explain below**)
If yes, please specify:
- AI tool or model used (e.g. ChatGPT, GPT-4, Claude, etc.)
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation)
- Which parts of the change were influenced or generated
- Whether the result was manually reviewed and adapted
AI assistance is allowed, but all submitted code must be fully
understood, reviewed, and owned by the contributor.
Any AI-influenced changes must be verified against existing CORE and PB
logic. We expect contributors to be honest
about what they do and do not understand.
---
## Final Checklist
- [x] Stability is not compromised
- [x] Performance impact is understood, tested, and acceptable
- [x] Added logic complexity is justified and explained
- [x] Documentation updated if needed
---
## Notes for Reviewers
Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.
---------
Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
|
||
|
|
441f9f7552
|
Warnings PR 1: Event warnings and headers (#2106)
# Pull Request
This is the first in a series of PRs intended to eliminate warnings in
the module. The design intent is to eliminate the calling event when not
needed in the body of the function. Based off of SmashingQuasars work.
---
## How to Test the Changes
- Step-by-step instructions to test the change
- Any required setup (e.g. multiple players, bots, specific
configuration)
- Expected behavior and how to verify it
## Complexity & Impact
- Does this change add new decision branches?
- [x] No
- [ ] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [x] No
- [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [x] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [x] No
- [ ] Yes (**explain why**)
If this introduces more advanced or AI-heavy logic:
- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
- [x] No
- [ ] Yes (**explain below**)
---
## Final Checklist
- [x] Stability is not compromised
- [x] Performance impact is understood, tested, and acceptable
- [x] Added logic complexity is justified and explained
- [x] Documentation updated if needed
---
## Notes for Reviewers
Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.
---------
Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
|
||
|
|
25800f54e8
|
Fix/Feat: PVP with master and PVP probablity system (thread-safe remake) (#2008)
This is a remake of #1914 that had to be reverted. Original PR had a thread-safe issue where a crash happens if multiple threads access the cache at the same time. Unfortunately this problem was not caught in earlier testing. I don't know if because I was testing on a month old branch, if my settings had only ~2000, or if I needed test runs longer than an hour to find out. Regardless, this has all been addressed. Test have been run on the latest commits from today (2026/1/11), with all 7500 of my bots active, with a test run that lasted 15 hours. All stable and bots are following the probability system without issue. ~~The new edit uses mutex locking, preventing simultaneous access of the cache by multiple threads.~~ The new edit uses deterministic hashing, thereby not having issues with cache thread safety to begin with. Thank you @hermensbas for catching and reverting the original problem PR. Apologies for not catching the issue myself. --- Original PR description: There are two related PVP components in this PR. First is the simple yet fundamental change to bot behaviour when they are in party. Right now bots with a master will go into PVP when there's a nearby PVP target, even if master is not in PVP. This absolutely should not happen. Bots should not consider PVP at all if master is not in PVP. The fix is only 3 lines in EnemyPlayerValue The second component is introducing PVP probabilities, to make decisions more realistic. Right now even a level 1 bot will 100% go into PVP if it sees a level 80 PVP target. They can't help themselves. So the change here addresses that insanity. Several thresholds (subject to community review) are introduced: 1. Bots will not fight a target 5 or more levels higher than them 2. Bots have a 25% chance starting a fight with a target +/- 4 levels from them. 3. Bots have a 50% chance starting a fight with a target +/- 3 levels from them. 4. Bots have a 75% chance starting a fight with a target +/- 2 levels from them. 5. Bots have a 100% chance starting a fight with a target +/- 1 level from them. 6. Bots have a 25% chance starting a fight with a target 5 or more levels below them (ganking. thought it would be funny, and technically realistic of player behaviour) Exception of course exist for BG/Arena/Duel, and in capitals where bots will always PVP. Also bots will always defend themselves if attacked. Few notes: 1. The if/ else if logic can be further simplified, but only if we use thresholds that are different by one. So current logic allows for flexibility of using values like 10/7/5/3 instead of 5/4/3/2. 2. The caching system is per-bot basis. So for some target X, if some bot decides to attack it, another bot will make its own decision. At first I used a simplified global system (thinking there might be performance concerns) where if one bot decides to attack a target then they all do, but when I switched to the more realistic per-bot basis, I didn't see an effect on performance. 3. Variables are obviously not configurable right now. I'm starting to see Bash's POV that maybe we have too many configs 😬 Still, they can be easily exposed in the future, and if someone is reading this then, remember to change constexpr to const. --------- Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com> |
||
|
|
ee2a399ac8
|
Refactor newrpginfo data union to std::variant (#2079)
# Pull Request
As I began modifying the newrpginfo to change the types of data it
stored, or add new data I found myself with the issue of ending up
either with garbage memory if the information wasnt properly stored on
status change, or needing complicated destructor patterns for non
trivial data sets.
---
## Design Philosophy
Make rpginfo able to handle more complicated information in a strongly
---
## Feature Evaluation
No Feature changes
---
## How to Test the Changes
- Server should be stable for an extended period of time.
- Bots should be able to complete quests, fly, etc as they did before.
## Complexity & Impact
- Does this change add new decision branches?
- [X ] No
- [ ] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [ ] No
- [ X] Yes (**describe and justify impact**)
Potentially as there can be more memory involved in the object.
- Could this logic scale poorly under load?
- [X ] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [ X] No
- [ ] Yes (**explain why**)
If this introduces more advanced or AI-heavy logic:
- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
- [ ] No
- [ X] Yes (**explain below**)
If yes, please specify:
- Gemini suggested the use of std::variant as an alternative data
structure. I found additinal external references that correlated with
the same suggestion of moving away from a union.
- Implementation was performed manually with Co-pilot auto-complete
---
## Final Checklist
In progress.
- [ ] Stability is not compromised
- [ ] Performance impact is understood, tested, and acceptable
- [ ] Added logic complexity is justified and explained
- [ ] Documentation updated if needed
---
## Notes for Reviewers
Im not 100% sure if this is a good design choice. There are some things
I didnt quite like by the end of this, specifically having to double
check whenever accessing data whether exists or not even though an
action has already been triggered. But I have a PR in the works where I
want to store a full flight path vector, and the union was giving me
issues. (It appears that state changes may be occuring in the same tick
between RPG status update and the stated action, leading to incorrect
data gathering.
I ended up solving it by first checking a pointer to the object, and
then getting the reference.
```c++
auto* dataPtr = std::get_if<NewRpgInfo::DoQuest>(&info.data);
if (!dataPtr)
return false;
auto& data = *dataPtr;
```
---------
Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
|
||
|
|
610fdc16d7
|
Fix bug with GetCreature + GetGameObject = use ObjectAccessor's methods instead (#2105)
# Pull Request https://en.cppreference.com/w/cpp/algorithm/equal_range.html > second is an iterator to the first element of the range [first, last) ordered after value (or last if no such element is found). The original code uses `return bounds.second->second`, which causes the wrong creature/gameobject to be returned. Instead, both methods (`GetCreature` and `GetGameObject`) now utilize ObjectAccessor's methods to retrieve the correct entities. These built-in methods offer a safer way to access objects. Additionally, `GetUnit` no longer includes redundant creature processing before checks and now has the same logic as the `ObjectAccessor::GetUnit` method. Furthermore, `GuidPosition::isDead` method has been renamed to `GuidPosition::IsCreatureOrGOAccessible` and updated, as it is used only for creatures (NOT units) and gameobjects. --- ## Design Philosophy We prioritize **stability, performance, and predictability** over behavioral realism. Complex player-mimicking logic is intentionally limited due to its negative impact on scalability, maintainability, and long-term robustness. Excessive processing overhead can lead to server hiccups, increased CPU usage, and degraded performance for all participants. Because every action and decision tree is executed **per bot and per trigger**, even small increases in logic complexity can scale poorly and negatively affect both players and world (random) bots. Bots are not expected to behave perfectly, and perfect simulation of human decision-making is not a project goal. Increased behavioral realism often introduces disproportionate cost, reduced predictability, and significantly higher maintenance overhead. Every additional branch of logic increases long-term responsibility. All decision paths must be tested, validated, and maintained continuously as the system evolves. If advanced or AI-intensive behavior is introduced, the **default configuration must remain the lightweight decision model**. More complex behavior should only be available as an **explicit opt-in option**, clearly documented as having a measurable performance cost. Principles: - **Stability before intelligence** A stable system is always preferred over a smarter one. - **Performance is a shared resource** Any increase in bot cost affects all players and all bots. - **Simple logic scales better than smart logic** Predictable behavior under load is more valuable than perfect decisions. - **Complexity must justify itself** If a feature cannot clearly explain its cost, it should not exist. - **Defaults must be cheap** Expensive behavior must always be optional and clearly communicated. - **Bots should look reasonable, not perfect** The goal is believable behavior, not human simulation. Before submitting, confirm that this change aligns with those principles. --- ## How to Test the Changes The behavior has not changed after all. ## Complexity & Impact - Does this change add new decision branches? - [x] No - [ ] Yes (**explain below**) - Does this change increase per-bot or per-tick processing? - [x] No - [ ] Yes (**describe and justify impact**) - Could this logic scale poorly under load? - [x] No - [ ] Yes (**explain why**) --- ## Defaults & Configuration - Does this change modify default bot behavior? - [x] No - [ ] Yes (**explain why**) If this introduces more advanced or AI-heavy logic: - [ ] Lightweight mode remains the default - [ ] More complex behavior is optional and thereby configurable --- ## AI Assistance - Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change? - [x] No - [ ] Yes (**explain below**) If yes, please specify: - AI tool or model used (e.g. ChatGPT, GPT-4, Claude, etc.) - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation) - Which parts of the change were influenced or generated - Whether the result was manually reviewed and adapted AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor. Any AI-influenced changes must be verified against existing CORE and PB logic. We expect contributors to be honest about what they do and do not understand. --- ## Final Checklist - [x] Stability is not compromised - [x] Performance impact is understood, tested, and acceptable - [x] Added logic complexity is justified and explained - [x] Documentation updated if needed --- ## Notes for Reviewers Anything that significantly improves realism at the cost of stability or performance should be carefully discussed before merging. --------- Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com> |
||
|
|
3db2a5a193
|
Refactor of EquipActions (#1994)
#PR Description The root cause of issue #1987 was the AI Value item usage becoming a very expensive call when bots gained professions accidentally. My original approach was to eliminate it entirely, but after inputs and testing I decided to introduce a more focused Ai value "Item upgrade" that only checks equipment and ammo inheriting directly from item usage, so the logic is unified between them. Upgrades are now only assessed when receiving an item that can be equipped. Additionally, I noticed that winning loot rolls did not trigger the upgrade action, so I added a new package handler for that. Performance needs to be re-evaluated, but I expect a reduction in calls and in the cost of each call. I tested with bots and selfbot in deadmines and ahadowfang keep. --------- Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com> |
||
|
|
13fff46fa0
|
Improper singletons migration to clean Meyer's singletons (cherry-pick) (#2082)
# Pull Request
- Applies the clean and corrected singletons, Meyer pattern. (cherry
picked from @SmashingQuasar )
Testing by just playing the game in various ways. Been tested by myself
@Celandriel and @SmashingQuasar
---
## Complexity & Impact
- Does this change add new decision branches?
- [x] No
- [ ] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [x] No
- [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [x] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [x] No
- [ ] Yes (**explain why**)
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
- [x] No
- [ ] Yes (**explain below**)
---
## Final Checklist
- [x] Stability is not compromised
- [x] Performance impact is understood, tested, and acceptable
- [x] Added logic complexity is justified and explained
- [x] Documentation updated if needed
---
## Notes for Reviewers
Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.
---------
Co-authored-by: Nicolas Lebacq <nicolas.cordier@outlook.com>
Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com>
|
||
|
|
3d467ce3bb
|
Added some additional defense checks around isHostile and unit/target (#2056)
Needs second pair of eyes, they appear in crash logs here and there. Its merely a patch on a open wound. ---- As in aslong there multithreads in mapupdate, which we need for decent performance and core calls are not done correctly due various reasons. These type of issues remain. Although i am planning to experiment a little with threadsafe execution of our strategies vs performance. The most effective thing we could do is check every single action and check its stateless and where it does effect the state or read the state of a core object its done in the safest way. flags, worldthread where possible and/ot simply taking into account the state might be invalid. |
||
|
|
41c53365ae
|
[HOT FIX] MS build issues regarding folder / command lenght usage or rc.exe (#2038) |