adamqqqplay / dota2ai

Ranked Matchmaking AI: An improved Dota2 AI based on Valve's default AI. Has more than 3 million subscribers on Steam.
http://steamcommunity.com/sharedfiles/filedetails/?id=855965029
GNU General Public License v3.0
315 stars 85 forks source link

Bot Match Extreme Slowdown ~= 20 Minutes #49

Closed sneakypeterson closed 3 years ago

sneakypeterson commented 3 years ago

I believe that I've been able to isolate the source of your problem. The ~= 20 minute mark usually coincides with the time that an Armlet carrier bot manages to get their armlet. I suspect that the game is slowing down due to the bots spamming an armlet toggle.

Every time I've seen this issue, it occurs under 2 conditions:

  1. One of the bots (not necessarily the armlet carrier) gets below 50% hp.
  2. Any of the bots has an armlet. The armlet carrier can be either on your team or the other team.

In this recent match (https://www.dotabuff.com/matches/5991207100) we focused on killing the CK whenever he respawned. Whenever we did so, the lag would stop. It would come right back the second he respawned. In games where I've been less lucky and it isn't a full 5v5, the armlet carrier is on my team and there's no recourse.

Hope that helps!

sneakypeterson commented 3 years ago

@adamqqqplay So, I'm not an expert in Dota scripts by any means, but in https://github.com/adamqqqplay/dota2ai/blob/master/util/ItemUsageSystem.lua in the Armlet toggle logic from 580 - 632,

Doesn't this block

if itemArmlet then
    if itemArmlet.lastOpenTime == nil and IsUsingArmlet then
        itemArmlet.lastOpenTime = DotaTime()
        return
    end
    if not IsUsingArmlet then
        itemArmlet.lastOpenTime = nil
        return
    end
end

conflict with

if itemArmlet and itemArmlet:IsFullyCastable() and notBlasted then
    if AbilityExtensions:IsFarmingOrPushing(npcBot) then
        local target = npcBot:GetAttackTarget()
        if target and target:IsAlive() and (AbilityExtensions:GetHealthPercent(npcBot) >= 0.45 or npcBot:GetHealth() <= 400 or npcBot:GetUnitName() == "npc_bot_hero_huskar" and npcBot:GetLevel() >= 7) then
            if not IsUsingArmlet then
                npcBot:Action_UseAbility(itemArmlet)
                itemArmlet.lastOpenTime = DotaTime()
                return
            else
                if npcBot:GetHealth() <= 250 and not npcBot:WasRecentlyDamagedByAnyHero(0.8) then
                    npcBot:Action_UseAbility(itemArmlet)
                    itemArmlet.lastOpenTime = DotaTime()
                end
            end
        else
            if IsUsingArmlet then
                npcBot:Action_UseAbility(itemArmlet)
                itemArmlet.lastOpenTime = nil
                return
            end
        end
    elseif AbilityExtensions:IsAttackingEnemies(npcBot) or AbilityExtensions:IsRetreating(npcBot) then
        if not IsUsingArmlet then
            if #npcBot:GetNearbyHeroes(1599, true, BOT_MODE_NONE) > 0 or npcBot:WasRecentlyDamagedByAnyHero(2.5) then
                npcBot:Action_UseAbility(itemArmlet)
                itemArmlet.lastOpenTime = DotaTime()
                return
            end
        else
            if npcBot:GetHealth() <= 300 then
                local projectiles = npcBot:GetIncomingTrackingProjectiles()
                if (#projectiles == 0 or AbilityExtensions:CannotBeKilledNormally(npcBot)) and DotaTime() - itemArmlet.lastOpenTime >= 0.6 then
                    npcBot:Action_UseAbility(itemArmlet)
                    npcBot:ActionQueue_UseAbility(itemArmlet)
                    itemArmlet.lastOpenTime = DotaTime()
                    return
                end
            end
        end
    end
end

And wouldn't the first block just lead to the bots infinitely toggling? There's something in that logic that's causing it, I'm pretty sure.

sneakypeterson commented 3 years ago

Thanks for the fix @bensusman

adamqqqplay commented 3 years ago

Thanks for raising this question. It seems that some kind of logic error has indeed occurred, leading to an infinite loop. As a result, the game frame rate has dropped significantly. I hope @bensusman 's repair can temporarily solve this problem, and we are looking for a way to completely solve the problem. At the same time, further discussions are welcome.

AaronSong321 commented 3 years ago

We temporarily remove the usage of armlet. The API provided by Valve crashes when turning off armlet, and gives an console error when turning off ring_of_basilius. There's no way of fixing the issues without discarding the usage of these items.