首页 > 代码库 > Dota2 AI 开发 (二)定制AI阵容 配置英雄出装

Dota2 AI 开发 (二)定制AI阵容 配置英雄出装

在Dota2 AI 开发(一)环境配置 中介绍了如何搭建 Dota2 AI 的开发环境,在这篇文章中,主要介绍Dota2中AI的常规控制方式,并介绍如何在人机比赛中配置一个裸跳刀的Sven。

常用指令

  • 重新加载Lua脚本:dota_bot_reload_scripts
  • 加速游戏:host_timescale 4.0
  • 开启作弊:sv_cheats 1

控制选人

在bots目录下创建一个名为 hero_selection.lua的脚本,在其中输入如下内容:

function Think()


    if ( GetTeam() == TEAM_RADIANT )
    then
        print( "selecting radiant" );
        SelectHero( 0, "npc_dota_hero_antimage" );
        SelectHero( 1, "npc_dota_hero_lina" );
        SelectHero( 2, "npc_dota_hero_sven" );
        SelectHero( 3, "npc_dota_hero_bloodseeker" );
        SelectHero( 4, "npc_dota_hero_crystal_maiden" );
    elseif ( GetTeam() == TEAM_DIRE )
    then
        print( "selecting dire" );
        SelectHero( 5, "npc_dota_hero_drow_ranger" );
        SelectHero( 6, "npc_dota_hero_earthshaker" );
        SelectHero( 7, "npc_dota_hero_juggernaut" );
        SelectHero( 8, "npc_dota_hero_mirana" );
        SelectHero( 9, "npc_dota_hero_nevermore" );
    end

end

这就是自定义的英雄阵容了,己方阵容为:

  • 敌法
  • 火女
  • 斯文
  • 血魔
  • 冰女

敌方为:

  • 小黑
  • 小牛
  • 剑圣
  • 白虎
  • 影魔

阵容当然是可以换的,那么如何知道想要的英雄叫什么呢?

更改为英文

在游戏属性设置>设置启动项中添加 -language english即可将界面改成英文,这样就可以知道所有东西的名称了。

比如在上面的敌方阵营中没有T,我希望把影魔换掉,所以我找到DK,它的名字如下:


技术分享

所以将上面函数选人的最后一行改为:

SelectHero( 9, "npc_dota_hero_abaddon" );

改好后保存,然后在控制台运行

dota_bot_reload_scripts

然后再次创建房间开游戏,就会发现预选的角色变化了


技术分享

通过这样的方式,相信大家能找到一个合适的阵容,以提高游戏乐趣。当然这也是制作特定角色AI的基础。

控制购买装备

在 Dota2 ai 中,是可以制定不同英雄的出装套路的。只要按照命名规范创建item_purchase_xxxx.lua即可。不过我发现有的道具名字并不是显示的英文名。例如跳刀明明是:


技术分享

结果到了配置里就是item_blink,这是怎么回事呢?我查了一下午,终于搞明白其中的缘由了。因为道具名称可能会随着道具描述更改,为了保持底层数据的稳定,官方制定了一个对照表。我在gamepedia上找到了一个版本。 应该是比较全的了,另外这个页面里也有英雄名哦。

我觉得有时候找起来实在是麻烦了,所以会直接通过指令给自己调装备测试,例如我刚刚的跳刀,我可以通过指令来尝试来找到名字,如果装备名正确,自己使用的角色身上就会获得它。

-item item_blink_dagger //wrong
-item item_blink //correct

弄清楚了道具名称,我们就可以开始着手制作自己的AI出装了。这里我以Sven为例。

实现

我希望Sven,买完吃喝之后,裸一个跳刀,然后出相位鞋、连击刀、bkb、撒旦、龙心。首先我先在bots目录下创建一个名为:item_purchase_sven.lua的文件,然后编辑如下内容:

local tableItemsToBuy = { 
        "item_tango",
        "item_clarity",
        "item_flask",
        ----------------------
        "item_blink",
        ---------------------
        "item_boots", 
        "item_blades_of_attack",
        "item_blades_of_attack",
        ----------------------
        "item_ogre_axe",
        "item_quarterstaff",
        "item_sobi_mask",
        "item_robe",
        ---------------------- 
        "item_ogre_axe",
        "item_mithril_hammer",
        "item_recipe_black_king_bar",
        -----------------------
        "item_lifesteal",
        "item_mithril_hammer",
        "item_reaver",
        ----------------------
        "item_reaver",
        "item_vitality_booster",
        "item_recipe_heart",
    };


-----------------------------------------------------------------------------

local secretShopThreshold = 100000;
local distanceBuyShop = 500;

function ItemPurchaseThink()

    local npcBot = GetBot();

    if ( #tableItemsToBuy == 0 )
    then
        npcBot:SetNextItemPurchaseValue( 0 );
        return;
    end

    local sNextItem = tableItemsToBuy[1];

    npcBot:SetNextItemPurchaseValue( GetItemCost( sNextItem ) );

    if ( npcBot:GetGold() >= GetItemCost( sNextItem ) )
    then
        if ( IsItemPurchasedFromSecretShop(sNextItem) and 
            npcBot:DistanceFromSecretShop() <= secretShopThreshold )
        then
            --print("Money is enough,Will Move to secret shop for: ",sNextItem);
            npcBot.secretShopMode = true;

            local shop_top = Vector(-4600, 1200);
            local shop_bot = Vector(4600,  -1200);

            local dist_top = GetUnitToLocationDistance( npcBot, shop_top );
            local dist_bot = GetUnitToLocationDistance( npcBot, shop_bot );

            if (dist_top < dist_bot) then
                npcBot:Action_MoveToLocation(shop_top);
            else
                npcBot:Action_MoveToLocation(shop_bot);
            end

            if ( npcBot:DistanceFromSecretShop() <= distanceBuyShop ) 
            then
                print("Will buy at secret shop : ",sNextItem," cost is:",
                    tostring(GetItemCost(sNextItem)));
                npcBot:ActionImmediate_PurchaseItem( sNextItem );
                table.remove( tableItemsToBuy, 1 );
                npcBot.secretShopMode = false;
            end
        else
            print("Money is enough,Will buy: ",sNextItem," cost is:",
                tostring(GetItemCost(sNextItem)));
            npcBot:ActionImmediate_PurchaseItem( sNextItem );
            table.remove( tableItemsToBuy, 1 );
        end
    end

end

-------------------------------------------------------------------------

需要注意的是不能买合成出的装备,需要自己按配方一个个配置。

配好后难道要等AI自己打出那么多钱来测试么?当然不,通过指令

dota_bot_give_gold 1000

来给所以AI加钱,直接就能看到结果。为了调试可以先把出门用的吃喝注释掉,防止占格子位置。

另外这套AI还有些瑕疵。我发现当角色不在神秘商店附近时是不可以买东西的,所以我写了个逻辑:如果需要买神秘商店的装备,就先将角色移动过去,然后再买。逻辑是这样的没错,不过角色移动的表现会比较傻缺。不管不顾的直接走也就罢了,有时候还会摩擦摩擦。搞了一天又累又饿,既然都能用,就先这样吧,以后有时间再优化,或者有大神路过帮忙看看也好。

总结

最后上个效果图


技术分享

技术分享

关注我的微信公众号,获取更多优质内容

Dota2 AI 开发 (二)定制AI阵容 配置英雄出装