Dota2 AI 简易开发教程(一)——选择阵容及技能使用

本文是Dota2 AI开发教程的第一部分,主要讲解如何为AI选择阵容和技能使用。内容包括:根据hero_selection.lua文件选择阵容,编写UpdateLaneAssignments()函数分路,以及在ability_item_usage_generic.lua中实现AbilityUsageThink()函数来控制技能加点和使用。示例以宙斯为例,详细解释了如何让AI智能选择英雄、分配分路并合理使用技能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一篇教程中,我们主要介绍了Dota2 AI的基本情况,在这篇文章中,我们将介绍如何为AI选择阵容和技能使用(以宙斯为例)。

选择阵容

官方开发者维基中有着这样的说明:

如果你想控制英雄选择和分路,你可以在文件名为hero_selection.lua的文件中实现如下函数:
Think() - 每帧被调用。负责机器人选择英雄。
UpdateLaneAssignments() - 在游戏开始前的每一帧被调用。返回玩家ID-分路的值对。
GetBotNames() - 调用一次,返回一个包含玩家名称的表。

dota 2 beta\game\dota\scripts\vscripts\bots_exampleV社的示例文件中,我们可以找到hero_selection.lua文件,这就是为AI选择阵容的脚本文件。

如果我们要开始制作自己的AI,那么首先需要创建dota 2 beta\game\dota\scripts\vscripts\bots文件夹,之后建立hero_selection.lua文件,在其中编写选择阵容的部分,这样的话AI就会选择自定义阵容了。

打开这个文件,我们可以看到如下内容

    function Think()
        if ( GetTeam() == TEAM_RADIANT )                    --处于天辉方时
        then
            print( "selecting radiant" );                    --在控制台输出调试信息
            SelectHero( 0, "npc_dota_hero_antimage" );        --为0号玩家选择敌法师
            SelectHero( 1, "npc_dota_hero_axe" );
            SelectHero( 2, "npc_dota_hero_bane" );
            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

其中Think()是主函数,游戏选择阵容时就会调用这个函数,然后判断是天辉方还是夜魇方,之后分别选择各自的阵容。那么我们如何找到英雄对应的名字呢?在这里便可找到英雄的实际名称。

例如宙斯的实际名称是"npc_dota_hero_zuus",那么我们将夜魇方的SelectHero( 5, "npc_dota_hero_drow_ranger" );替换为SelectHero( 5, "npc_dota_hero_zuus" );,那么AI便会选择在5号玩家的位置上选择宙斯。需要注意的是,玩家的ID是会随着人类玩家的加入而发生改变的,将玩家ID硬编码是一种不好的做法,比较好的方法是通过循环遍历出玩家的ID,这样无论人类玩家有多少,AI都能正常选择阵容。

下面便是能够自动适应玩家变化选择阵容的代码。

function Think()
        for i,id in pairs(GetTeamPlayers(GetTeam()))    --Lua语言自带的迭代器pairs,能够依次读取表中的值。
        do
            if(IsPlayerBot(id))                                     --判断该玩家是否为电脑
            then
                SelectHero( id, "npc_dota_hero_drow_ranger" );      --为id号玩家选择黑暗游侠
            end
        end
    end

如果我们要AI能够选择随机的阵容,而不是仅仅选择10个黑暗游侠,那该怎么办呢?很简单,通过Lua语言唯一的数据结构表(称作Table,可以用作数组)保存可以选择的英雄列表,然后随机出一个序号,选出表中的英雄。

hero_pool_my=
{
        'npc_dota_hero_zuus',
        'npc_dota_hero_skywrath_mage',
        'npc_dota_hero_ogre_magi',
        'npc_dota_hero_chaos_knight',
        'npc_dota_hero_viper',
        "npc_dota_hero_lina",
        "npc_dota_hero_kunkka",
        "npc_dota_hero_lich",
        "npc_dota_hero_shadow_shaman",
        "npc_dota_hero_centaur",
        'npc_dota_hero_crystal_maiden',
}
function Think()
    for i,id in pairs(GetTeamPlayers(GetTeam())) 
    do
        if(IsPlayerBot(id) and (GetSelectedHeroName(id)=="" or GetSelectedHeroName(id)==nil))
        then
            local num=hero_pool_my[RandomInt(1, #hero_pool_my)]     --取随机数
            SelectHero( id, num );          --在保存英雄名称的表中,随机选择出AI的英雄
            table.remove(hero_pool_my,num)      --移除这个英雄
        end
    end
end

以上代码会为两边的AI依次从hero_pool_my表中随机选出5个英雄。如果要让AI不选择重复的英雄,那么还需要进一步的修改。

选择分路

为AI分路的函数也是在hero_selection.lua中,如果我们想让AI遵循自定义的分路,那么需要在这个文件里新建一个UpdateLaneAssignments()函数。这个函数是用于游戏底层C++端调用,所以需要返回一个分路情况的表。

function UpdateLaneAssignments()
    local npcBot = GetBot()
    local lanes=
    {
        [1]=LANE_MID,
        [2]=LANE_BOT,
        [3]=LANE_TOP,
        [4]=LANE_BOT,
        [5]=LANE_TOP,
    }
    return lanes;
end

以上函数根据AI的位置分路,1楼中路,2楼下路,3楼上路,4楼下路,5楼上路。当然,如果要根据英雄的特性分路,那么需要加入更多判断。如果没有自己写好分路系统的话,可以暂时启用默认分路系统,即不编写这个函数。

技能加点

官方开发者维基中有着这样的说明:

如果你只想重写在技能和物品使用时的决策,你可以在文件名为ability_item_usage_generic.lua的文件中实现如下函数:
ItemUsageThink() - 每帧被调用。负责发出物品使用行为。
AbilityUsageThink() - 每帧被调用。负责发出技能使用行为。
CourierUsageThink() - 每帧被调用。负责发出信使的相关命令。
BuybackUsageThink() - 每帧被调用。负责发出买活指令。
AbilityLevelUpThink() - 每帧被调用。负责升级技英雄能。
这些函数中未被重写的,会自动采用默认的C++实现。
你也可以仅重写某个特定英雄对技能/物品使用的逻辑,比如火女(Lina),写在文件名为ability_item_usage_lina.lua的文件中。如果你想在特定英雄对技能/物品使用的逻辑重写时调用泛用的逻辑代码,请参考附件A的实现细节。

我们要实现的第一个英雄为宙斯,那么就可以新建一个ability_item_usage_zuus.lua的文件。首先要实现AI的加点,就要在此文件中编写AbilityLevelUpThink()函数。然后通过 npcBot:ActionImmediate_LevelAbility(abilityname);升级名称为abilityname的技能。那么怎样获取升级技能所需的技能名称呢?比较原始的方法是用一个表记录从1到25级所有的技能名称。其中的数据要在dota 2 beta\game\dota\scripts\npc\npc_heroes.txt中获取。
例如宙斯的技能为

    --以下为宙斯的技能名称
    "zuus_arc_lightning",
    "zuus_lightning_bolt",
    "zuus_static_field",
    "zuus_cloud",
    "zuus_thundergods_wrath",
    --以下为某个版本的天赋,请注意天赋名称会随着版本更新而变化,所以以下部分可能在当前版本中无效
    "special_bonus_mp_regen_2",
    "special_bonus_movement_speed_25",
    "special_bonus_armor_7",
    "special_bonus_magic_resistance_15",
    "special_bonus_unique_zeus_2",
    "special_bonus_unique_zeus_3",
    "special_bonus_cast_range_200",
    "special_bonus_unique_zeus",

如果通过原始方法记录,则需要排列组合以上的技能天赋。比较好的方法则是用两个表分别保存技能和天赋的名称,然后在一个统一的表中引用技能天赋名称,以存储加点顺序。

local Talents =
{
    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值