Skip to content

Conversation

@NoxMax
Copy link
Owner

@NoxMax NoxMax commented Dec 8, 2025

No description provided.

Celandriel and others added 6 commits December 3, 2025 13:25
…ots#1875)

Fix the naming conventions. 
Master should be reserved to identify a bots Master. 
groupleaders are not necessarily group masters and it should be clear
what the bot is looking for. (In most solo cases leader=master)
I removed bots checking if they should leave group every tick, and will
rely on the LeaveGroupFarAway action. I also increased the timer from 5
seconds to 20 seconds. No need to check this that often.
This is my first attempt of implementing playerbot strategies.

A team of 40 can steamroll Molten Core relatively easy, even with lower
item levels.
Regardless, this PR adds resistance triggers and actions to mitigate
some damage.
Additionally, improvements were made for the encounters with Garr, Baron
Geddon, Shazzrah and Golemagg.
A short summary per boss is listed below.
All planned features are included, but feedback is of course
appreciated.

### Lucifron
- Shadow resistance: mitigate damage from [Impending
Doom](https://www.wowhead.com/classic/spell=19702/impending-doom) and
[Shadow
Shock](https://www.wowhead.com/classic/spell=19460/shadow-shock).

### Magmadar
- Fire resistance: mitigate damage from [Lava
Bomb](https://www.wowhead.com/classic/spell=19411/lava-bomb) and [Magma
Spit](https://www.wowhead.com/classic/spell=19450/magma-spit).
- Like King Dred and the fraction commander (Nexus), this fight might
profit from an anti-fear strategy in order to counter
[Panic](https://www.wowhead.com/classic/spell=19408/panic). Not
implemented here.

### Gehennas
- Shadow resistance: mitigate damage from [Shadow
Bolt](https://www.wowhead.com/classic/spell=19728/shadow-bolt) and
increase the chance to resist [Gehennas'
Curse](https://www.wowhead.com/classic/spell=19716/gehennas-curse).

### Garr
- Fire resistance: mitigate damage from the Firesworn adds
([Immolate](https://www.wowhead.com/classic/spell=20294/immolate) and
[Eruption](https://www.wowhead.com/classic/spell=19497/eruption)).
- Disabled dps aoe abilities via multiplier. This one is important
because multiple exploding adds at once might delete bots rather
quick...

### Baron Geddon
- Refactored the existing strategy.
- Fire resistance: mitigate damage from [Ignite
Mana](https://www.wowhead.com/classic/spell=19659/ignite-mana),
[Inferno](https://www.wowhead.com/classic/spell=19695/inferno) and
[Living Bomb](https://www.wowhead.com/classic/spell=20475/living-bomb).
- Better Inferno handling: Before moving away, bots stop attacking and
interrupt their spells. Additionally, the new multiplier prevents bots
from running back to Geddon while Inferno is still active.

### Shazzrah
- Ranged bots now position themselves in a sweet spot that prevents them
from getting hit with [Arcane
Explosion](https://www.wowhead.com/classic/spell=19712/arcane-explosion)
but still close enough to dps and heal.

### Sulfuron Harbinger
- Fire resistance: mitigate damage from [Hand of
Ragnaros](https://www.wowhead.com/classic/spell=19780/hand-of-ragnaros)
and [Immolate](https://www.wowhead.com/classic/spell=20294/immolate). To
be fair, this one is quite negligible...

### Golemagg
- Fire resistance: mitigate damage from [Magma
Splash](https://www.wowhead.com/classic/spell=13880/magma-splash) and
[Pyroblast](https://www.wowhead.com/classic/spell=20228/pyroblast).
- Disabled dps aoe abilities via multiplier. Kind of a preference on my
side. Otherwise, the Core Ragers spam emotes about not wanting to die.

### Majordomo Executus
- Shadow resistance: mitigate damage from [Aegis of
Ragnaros](https://www.wowhead.com/classic/spell=20620/aegis-of-ragnaros),
[Shadow Shock](https://www.wowhead.com/classic/spell=20603/shadow-shock)
and [Shadow
Bolt](https://www.wowhead.com/classic/spell=21077/shadow-bolt). This one
is also negligible, TBF.

### Ragnaros
- Fire resistance: mitigate damage from [Wrath of
Ragnaros](https://www.wowhead.com/classic/spell=20566/wrath-of-ragnaros)
and [Lava
Burst](https://www.wowhead.com/classic/spell=21158/lava-burst).
…1829)

Stripped down version of mod-playerbots#1818. No new features. Refactors
IsPossibleTarget in AttackersValue.cpp to a better style and makes sure
pets don't attack in prohibited zones.

Testing:
Confirmed that aggro pets no longer attack in PVP prohibited areas, but
still do outside them. Zim'Torga in Zul'Drak is a good example to test
this (ID 4323). Lookout for death knights with a Risen Ally
(uncontrolled and naturally aggro) now they respect PVP prohibition like
their master.

Note: If you manually teleport a bot that is in mid combat to a PVP
prohibited area, its aggro pet might still attack, because its master is
still in combat strategy. Otherwise the pet will not attack if its
master has switched to non-combat.
…ts#1789)

# Fix: Arena PersonalRating and MMR issue for bot teams

## Problem
Bot arena teams are created with artificial random ratings (1000-2000
range), but when bots join these teams, their personal ratings and
matchmaker ratings (MMR) use default config values instead of being
adjusted to match the team's artificial rating. This causes matchmaking
issues since the system uses personal ratings for queue calculations.

## Root Cause
The issue occurred because `SetRatingForAll()` was called during team
creation but only affected the captain. When additional bots were added
later via `AddMember()`, they received default values from
`CONFIG_ARENA_START_PERSONAL_RATING` and
`CONFIG_ARENA_START_MATCHMAKER_RATING` instead of values appropriate for
the team's artificial rating.

## Solution
After bots are added to arena teams, the fix:

1. Uses `SetRatingForAll()` to align all personal ratings with team
rating
2. Adjusts matchmaker ratings based on team context vs default
configuration
3. Saves changes to both database tables with proper data types

## Impact
- Personal ratings now match team ratings for artificial bot teams
- MMR values are adjusted for artificial bot team ratings instead of
using default config values
- Arena matchmaking functions correctly for bot teams with random
ratings
- Only affects new arena team assignments after deployment
- Existing player teams and normal config behavior are unaffected

## Manual Database Update

For existing installations, the provided SQL script could be used to fix
bot teams created before this patch.

### Update personal rating
```sql
UPDATE arena_team_member atm
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
SET atm.personalRating = at.rating
WHERE a.username LIKE 'rndbot%'
  AND atm.personalRating != at.rating;
```

### Update MMR for existing entries
```sql
UPDATE character_arena_stats cas
JOIN characters c ON cas.guid = c.guid
JOIN auth.account a ON c.account = a.id
JOIN arena_team_member atm ON cas.guid = atm.guid
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
SET
    cas.matchMakerRating = GREATEST(at.rating, 1500),  -- Use team rating or 1500 minimum
    cas.maxMMR = GREATEST(cas.maxMMR, cas.matchMakerRating)  -- Update maxMMR if needed
WHERE
    a.username LIKE '%rndbot%'
    AND (
        -- Update if MMR doesn't match team context
        (at.rating > 1500 AND cas.matchMakerRating < at.rating) OR
        (at.rating <= 1500 AND cas.matchMakerRating != 1500) OR
        cas.matchMakerRating IS NULL
    )
    AND (
        -- Map arena team type to character_arena_stats slot
        (at.type = 2 AND cas.slot = 0) OR  -- 2v2 teams use slot 0
        (at.type = 3 AND cas.slot = 1) OR  -- 3v3 teams use slot 1
        (at.type = 5 AND cas.slot = 2)     -- 5v5 teams use slot 2
    );
```

### Insert missing MMR records for bots without character_arena_stats
entries
```sql
INSERT INTO character_arena_stats (guid, slot, matchMakerRating, maxMMR)
SELECT
    atm.guid,
    CASE
        WHEN at.type = 2 THEN 0  -- 2v2 -> slot 0
        WHEN at.type = 3 THEN 1  -- 3v3 -> slot 1
        WHEN at.type = 5 THEN 2  -- 5v5 -> slot 2
        ELSE 0
    END as slot,
    GREATEST(at.rating, 1500) as matchMakerRating,
    GREATEST(at.rating, 1500) as maxMMR
FROM arena_team_member atm
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
WHERE
    a.username LIKE '%rndbot%'
    AND NOT EXISTS (
        SELECT 1 FROM character_arena_stats cas2
        WHERE cas2.guid = atm.guid
        AND cas2.slot = CASE
            WHEN at.type = 2 THEN 0
            WHEN at.type = 3 THEN 1
            WHEN at.type = 5 THEN 2
            ELSE 0
        END
    )
    AND at.rating > 0;
```

## Related issues

Fixes: mod-playerbots#1787 
Fixes: mod-playerbots#1800


## Verification Queries

### Query 1: Check personal rating alignment
```sql
SELECT
    'Personal Rating Check' as check_type,
    COUNT(*) as total_bot_members,
    SUM(CASE WHEN atm.personalRating = at.rating THEN 1 ELSE 0 END) as correct_ratings,
    SUM(CASE WHEN atm.personalRating != at.rating THEN 1 ELSE 0 END) as incorrect_ratings,
    ROUND(AVG(at.rating), 2) as avg_team_rating,
    ROUND(AVG(atm.personalRating), 2) as avg_personal_rating
FROM arena_team_member atm
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
WHERE
    a.username LIKE '%rndbot%';
```

### Query 2: Check MMR alignment
```sql
SELECT
    'MMR Alignment Check' as check_type,
    COUNT(*) as total_mmr_records,
    SUM(CASE
        WHEN at.rating > 1500 AND cas.matchMakerRating >= at.rating THEN 1
        WHEN at.rating <= 1500 AND cas.matchMakerRating = 1500 THEN 1
        ELSE 0
    END) as correct_mmr,
    SUM(CASE
        WHEN at.rating > 1500 AND cas.matchMakerRating < at.rating THEN 1
        WHEN at.rating <= 1500 AND cas.matchMakerRating != 1500 THEN 1
        ELSE 0
    END) as incorrect_mmr,
    ROUND(AVG(at.rating), 2) as avg_team_rating,
    ROUND(AVG(cas.matchMakerRating), 2) as avg_mmr,
    ROUND(AVG(cas.maxMMR), 2) as avg_max_mmr
FROM arena_team_member atm
JOIN arena_team at ON atm.arenaTeamId = at.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
JOIN character_arena_stats cas ON atm.guid = cas.guid
WHERE
    a.username LIKE '%rndbot%'
    AND (
        (at.type = 2 AND cas.slot = 0) OR
        (at.type = 3 AND cas.slot = 1) OR
        (at.type = 5 AND cas.slot = 2)
    );
```

### Query 3: Detailed team-by-team analysis
```sql
SELECT
    at.arenaTeamId,
    at.name as team_name,
    at.type as team_type,
    at.rating as team_rating,
    COUNT(atm.guid) as member_count,
    GROUP_CONCAT(DISTINCT atm.personalRating) as personal_ratings,
    GROUP_CONCAT(DISTINCT cas.matchMakerRating) as mmr_values,
    CASE
        WHEN COUNT(DISTINCT atm.personalRating) = 1 AND MIN(atm.personalRating) = at.rating THEN 'OK'
        ELSE 'MISMATCH'
    END as personal_rating_status,
    CASE
        WHEN COUNT(DISTINCT cas.matchMakerRating) = 1 AND (
            (at.rating > 1500 AND MIN(cas.matchMakerRating) >= at.rating) OR
            (at.rating <= 1500 AND MIN(cas.matchMakerRating) = 1500)
        ) THEN 'OK'
        ELSE 'MISMATCH'
    END as mmr_status
FROM arena_team at
JOIN arena_team_member atm ON at.arenaTeamId = atm.arenaTeamId
JOIN characters c ON atm.guid = c.guid
JOIN auth.account a ON c.account = a.id
LEFT JOIN character_arena_stats cas ON atm.guid = cas.guid
    AND cas.slot = CASE
        WHEN at.type = 2 THEN 0
        WHEN at.type = 3 THEN 1
        WHEN at.type = 5 THEN 2
        ELSE 0
    END
WHERE
    a.username LIKE '%rndbot%'
GROUP BY at.arenaTeamId, at.name, at.type, at.rating
ORDER BY at.rating DESC;
```
@NoxMax NoxMax merged commit 2a4c49d into UNMERGED-no-pvp-near-fly-inn Dec 8, 2025
1 check passed
@NoxMax NoxMax deleted the true-master branch December 8, 2025 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants