1. 程式人生 > >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還有些瑕疵。我發現當角色不在神祕商店附近時是不可以買東西的,所以我寫了個邏輯:如果需要買神祕商店的裝備,就先將角色移動過去,然後再買。邏輯是這樣的沒錯,不過角色移動的表現會比較傻缺。不管不顧的直接走也就罷了,有時候還會摩擦摩擦。搞了一天又累又餓,既然都能用,就先這樣吧,以後有時間再優化,或者有大神路過幫忙看看也好。

總結

最後上個效果圖


松陽論道

關注我的微信公眾號,獲取更多優質內容