如今Dota2分为两种技能制作方式,Data Driven(数据驱动)和Lua Ability两种方式, 所谓的数据驱动是V社的一种文件格式,叫KeyValue格式,如果你知道JSON那么第一眼看起来会有点像JSON, 就算是Lua Ability也要通过数据驱动进行定义才能使用,数据驱动是基础,所以对数据驱动的理解必不可少。
数据驱动是V社设计好的,我们根据提供的功能来实现技能效果,涉及很少的逻辑代码,当然可以混合Lua加入逻辑代码, 数据驱动在游戏执行后会翻译成底层的C++对象,所以数据驱动的技能执行效率也要好一些, 不过这里有一点需要提醒:数据驱动发生错误可能会直接导致客户端崩溃, 基本没有错误信息,好在数据驱动没什么复杂逻辑,通过去掉代码等手段可以排查出来,熟悉之后更是可以很快定位, 建议新手先通过数据驱动制作技能,后面熟悉之后再尝试Lua Ability。
这是一种很自由的制作方式,可以实现很多复杂的技能,V社已经很多年没有更新数据驱动了,也没加入什么新功能, 自从推出Lua Ability,在Lua Ability方面的API倒是会更新一下,这可以认为是一种纯Lua的制作方式, 所以需要你有Lua的基础功底,涉及的知识也会很多,不推荐新手一上来就使用。
🔸后面开始介绍以数据驱动为主的技能制作,Lua Ability放到后面的高级篇讲解
文件入口 game/dota_addons/<你的项目>/scripts/npc/npc_abilities_custom.txt
💡 基础定义
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
}
}
💡 被动技能
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_PASSIVE"
}
}
很简单~一般也不需要其他辅助行为,这三种必须有。
AbilityBehavior
表示技能的行为,也是技能施放方式。
💡 无目标主动技能
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_NO_TARGET"
"AbilityCastPoint" "0.5"
"AbilityCastAnimation" "ACT_DOTA_CAST_ABILITY_1"
}
}
把PASSIVE
改成POINT
就是无目标技能了,在做完前摇动作后才会施放。
AbilityCastPoint
表示前摇时长,以秒为单位。AbilityCastAnimation
表示前摇动作,参考官方WiKi-GameActivity_t💡 点目标技能
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT"
"AbilityCastRange" "500"
}
}
在施放的时候单位会先转身面向目标点,然后做前摇动作,前摇结束才施放;
AbilityCastRange
表示施法距离,如果没有定义这个距离默认无限距离;
接下来我们加点辅助效果
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_IGNORE_TURN"
}
}
这里多了DOTA_ABILITY_BEHAVIOR_IMMEDIATE
和DOTA_ABILITY_BEHAVIOR_IGNORE_TURN
,并且它们使用|
隔开(注意在写的时候竖线两边要有空格),这表示合并效果,从代码方面讲这跟c/c++的异或差不多是一个意思的
IMMEDIATE
表示该技能立即施放,也就是没有前摇IGNORE_TURN
表示忽略转身更多技能行为常量参考:官方WiKi-DOTA_ABILITY_BEHAVIOR
💡 单位目标技能
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_UNIT_TARGET"
"AbilityUnitTargetType" "DOTA_UNIT_TARGET_BASIC | DOTA_UNIT_TARGET_HERO"
"AbilityUnitTargetTeam" "DOTA_UNIT_TARGET_TEAM_ENEMY"
"AbilityUnitTargetFlags" "DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES"
}
}
单位目标稍微麻烦些,多了三种常量,这三种常量定义了该技能对哪些单位有用;
AbilityUnitTargetType
表示单位类型,比如普通单位、英雄、建筑等,参考官方WiKi-DOTA_UNIT_TARGET_TYPEAbilityUnitTargetTeam
表示作用的队伍,DOTA_UNIT_TARGET_TEAM_ENEMY
表示敌人,参考官方WiKi-DOTA_UNIT_TARGET_TEAMAbilityUnitTargetFlags
表示筛选单位的一些特征,比如魔法免疫的单位(一般技能无法对魔法免疫单位施放),远古单位,近战或远程单位等,参考官方WiKi-DOTA_UNIT_TARGET_FLAGS💡 开关类技能
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_TOGGLE"
}
}
此类技能具有开关状态,具体事件下篇再讲
💡 自动施法
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_AUTOCAST"
"AbilityCastRange" "500"
}
}
前面的施法类型中可以搭配自动施法,也就是当你右键技能,这个技能就会出现一个转圈圈的特效表示会自动施法, 但是我实验的时候这个自动施法的AI要自己写,正常情况下不会自己施放。
💡 吟唱/蓄力/引导/持续 施法
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_CHANNELLED"
"AbilityCastRange" "500"
"AbilityChannelTime" "3.0"
}
}
这种技能在施法的时候会变成一种读条的形式,AbilityChannelTime
就是读条的时间,你可以当做施法前的吟唱,
也可以当做持续施法期间不断下冰雹这种技能,和上面的自动施法一样可以跟前面的施法类型搭配在一起。
💡 带有AOE范围指示的施法
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_AOE"
"AbilityCastRange" "1000"
"AOERadius" "300"
}
}
点击此技能后鼠标就会同时出现一个范围指示圈,AOERadius
表示这个范围。
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT"
"MaxLevel" "4"
"RequiredLevel" "5"
"LevelsBetweenUpgrades" "0"
"FightRecapLevel" "0"
"AbilityCooldown" "3.0"
"AbilitySharedCooldown" "common"
"AbilityManaCost" "10"
"AbilityTextureName" "xxx"
}
}
MaxLevel
表示技能最大等级RequiredLevel
表示?LevelsBetweenUpgrades
表示学习技能的等级要求FightRecapLevel
表示跳级?AbilityCooldown
表示技能冷却时间AbilitySharedCooldown
表示共享冷却时间的字段,相同字段的技能在其中一个使用后其它技能都会一起进入CDAbilityManaCost
表示使用技能所需的魔法值AbilityTextureName
表示技能图标的文件名,后面再细讲"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT"
"MaxLevel" "4"
"AbilityCastRange" "500 700"
"AbilityCooldown" "3.5"
"AbilityManaCost" "10 15 20 30"
"AbilityDamage" "100 200 300 400"
}
}
在技能中不同等级使用不同的数值是很常见的,上面定义该技能等级为4,则可以定义4个等级的数值(如AbilityManaCost),每个等级的数值用空格隔开,从左到右依次是从1级到4级的数值。
💡 自定义字段
"DOTAAbilities"
{
"custom_ability"
{
"ID" "5000"
"BaseClass" "ability_datadriven"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT"
"MaxLevel" "4"
"AbilitySpecial"
{
"01"
{
"var_type" "FIELD_FLOAT"
"damage" "20 30 40 50"
}
"02"
{
"var_type" "FIELD_INTEGER"
"radius" "500"
}
}
}
}
AbilitySpecial
用于自定义字段,其下面是字段列表,上面范例中的01,02不必是顺序的,只是用于保证唯一;
在往里是var_type
用于指定数值的类型,目前有两种:FIELD_FLOAT
和FIELD_INTEGER
,这里说明一下,
对于我们来说这并无区别,因为Lua只有number类型,所以我们获取到的数值都是number,而C++作为强类型的语言是有类型区分的;
在是var_type
下面就是需要自定义的字段,上面的范例我们自定义了damage
和radius
字段,数值表示的方式跟前面一样;AbilitySpecial
可以理解为定义变量的地方。
下一篇开始讲如何技能的事件和动作
📅 创建于2020-10-10