A DataDriven ability is a collection KeyValues. KeyValues are simple, tree-based structures used for storing nested sections containing key/value pairs.
DataDriven abilities are defined inside scripts/npc/npc_abilities_custom.txt under a game addon folder.
This skeleton contains many keyvalues which will be expanded upon in this documentation.
BaseClass can be any default dota ability name or "ability_datadriven", which allows the use of the entire data driven ability system.
Using a dota ability as the BaseClass can be done either as an override of the ability (goes in npc_abilities_override.txt) or just as a new ability in npc_abilities.custom.txt which inherits the exposed variables. This however doesn't let us change/add its internal structure, as that code is locked in C++ code.
Here we'll focus on everything that concerns writing custom abilities from scratch, using the
This describes how the ability works, the general behavior to perform when it is executed.
You can use different behaviors together, separated by spaces and | pipes.
List of every possible AbilityBehavior
|DOTA_ABILITY_BEHAVIOR_NO_TARGET||Doesn't need a target to be cast. |
Ability fires off as soon as the button is pressed.
|DOTA_ABILITY_BEHAVIOR_UNIT_TARGET||Needs a target to be cast on. |
|DOTA_ABILITY_BEHAVIOR_POINT||Can be cast anywhere the mouse cursor is. |
If a unit is clicked, it will just be cast where the unit was standing.
|DOTA_ABILITY_BEHAVIOR_PASSIVE||Cannot be cast.|
If the user moves, or is silenced/stunned, the ability is interrupted.
|DOTA_ABILITY_BEHAVIOR_TOGGLE||Can be toggled On/Off.|
|DOTA_ABILITY_BEHAVIOR_AURA||Ability is an aura.|
Not really used other than to tag the ability as such.
|DOTA_ABILITY_BEHAVIOR_AUTOCAST||Can be cast automatically.|
Usually doesn't work by itself in anything that is not an ATTACK ability.
|DOTA_ABILITY_BEHAVIOR_HIDDEN||Can't be cast, and won't show up on the HUD.|
|DOTA_ABILITY_BEHAVIOR_AOE||Can draw a radius where the ability will have effect.|
Like POINT, but with an area of effect display.
Makes use of
|DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE||CAnnot be learned by clicking on the HUD.|
Example: Invoker's abilities.
|DOTA_ABILITY_BEHAVIOR_ITEM||Ability is tied to an item. There is no need to use this, the game will internally assign this behavior to any |
|DOTA_ABILITY_BEHAVIOR_DIRECTIONAL||Has a direction from the hero.|
Examples: Mirana's Arrow, or Pudge's Hook.
|DOTA_ABILITY_BEHAVIOR_IMMEDIATE||Can be used instantly, without going into the action queue.|
|DOTA_ABILITY_BEHAVIOR_NOASSIST||Ability has no reticle assist. (?)|
|DOTA_ABILITY_BEHAVIOR_ATTACK||Is an attack, and cannot hit attack-immune targets.|
|DOTA_ABILITY_BEHAVIOR_ROOT_DISABLES||Cannot be used when rooted.|
|DOTA_ABILITY_BEHAVIOR_UNRESTRICTED||Ability is allowed when commands are restricted.|
Example: Lifestealer's Consume.
|DOTA_ABILITY_BEHAVIOR_DONT_ALERT_TARGET||Does not alert enemies when target-cast on them.|
Example: Spirit Breaker's Charge.
|DOTA_ABILITY_BEHAVIOR_DONT_RESUME_MOVEMENT||Should not resume movement when it completes.|
Only applicable ot no-target, non-immediate abilities.
|DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK||Ability should not resume command-attacking the previous target when it completes.|
Only applicable to no-target, non-immediate abilities and unit-target abilities.
|DOTA_ABILITY_BEHAVIOR_NORMAL_WHEN_STOLEN||Ability still uses its normal cast point when stolen.|
Examples: Meepo's Poof, Furion's Teleport.
|DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING||Ability ignores backswing pseudoqueue.|
|DOTA_ABILITY_BEHAVIOR_IGNORE_PSEUDO_QUEUE||Can be executed while stunned, casting, or force-attacking. Only applicable to toggled abilities.|
Example: Morphling's Attribute Shift.
|DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL||Doesn't cancel abilities with |
|DOTA_ABILITY_BEHAVIOR_OPTIONAL_UNIT_TARGET||Bottle and Wards.|
The following behaviors will generate a line in the ability tooltip. You want at least one of 1 behavior of this list. The rest of the ability behaviors don't have any UI support yet.
The UI can only show one behavior tooltip, but internally it will behave as expected, as long two contradicting keys are not used together (like NO_TARGET with UNIT_TARGET).
|AbilityBehavior||ABILITY: Tooltip||Takes precdence over:|
|DOTA_ABILITY_BEHAVIOR_CHANNELLED||Channeled||POINT and UNIT|
|DOTA_ABILITY_BEHAVIOR_TOGGLE||Toggle||POINT and UNIT|
For example, an ability with
will be shown like this:
Omitting this will default to DOTA_ABILITY_TYPE_BASIC.
|DOTA_ABILITY_TYPE_BASIC||Normal ability, learnable at level 1 and upgradeable every 2 levels.|
|DOTA_ABILITY_TYPE_ULTIMATE||5 levels between upgrades, and requires level 6 to spend the first point on it.|
Also tags the ability as ultimate for the HUD.
|DOTA_ABILITY_TYPE_ATTRIBUTES||Used for attribute_bonus.|
Additionally, ability level intervals and limits can be directly changed with these keyvalues inside the ability block:
The UI currently supports the following ability level displays: 1, 3, 4, and 7.
You can still use any integer value as MaxLevel, and it will assign the proper level values internally, but it will use a combination of these UI display numbers, then "start again" to another UI.
At which level the ability can first be learned. This takes negative values, to enable for skills to be skilled at any point, because the next value sets the levels between ranks of the ability, including the first one.
How many levels to wait to be able to learnt he next rank.
Results in an ability that can be first skilled at levels 3/10/17/24/31/38/45.
Max level of the heroes can be changed using the Lua
SetCustomHeroMaxLevel(MAX_LEVEL) API function.
The icon file name that should be used in the UI for this ability. You can reutilize the icon from another just by putting that ability name here if desired. The internal name of every default dota ability can be found in: Built-In Ability Names.
To use your own icons, place them in
resources/flash3/images/spellicons in you game addon folder, and just directly refer to the image name without the path or the extension.
Format: 128x128 PNG
Added in Reborn:
Cast While Hidden
Added in Reborn:
|DOTA_UNIT_TARGET_TEAM_NONE||Default value by omission.|
|DOTA_UNIT_TARGET_ALL||Everything, including hidden entities.|
|DOTA_UNIT_TARGET_BASIC||Basic units, including summons.|
Examples: Tangos, Quelling Blade.
Same as BASIC, but might not include things like some summons.
Examples: Death Pact, Devour.
|DOTA_UNIT_TARGET_OTHER||Everything not included in the previous types.|
Examples: Replicate, Sunder, Demonic Conversion, Tether, Infest...
Flags allow targeting units that are ignored by default (for example, magic immune enemies,) or to ignore specific types of units that will otherwise be targetable (like Ancients, or magic immune allies.)
|AbilityUnitTargetFlags||Targets / Ignores|
|DOTA_UNIT_TARGET_FLAG_NONE||Default value by omission.|
|DOTA_UNIT_TARGET_FLAG_DEAD||Dead units, which are otherwise ignored.|
|DOTA_UNIT_TARGET_FLAG_MELEE_ONLY||Units with AttackCapabilities DOTA_UNIT_CAP_MELEE_ATTACK.|
|DOTA_UNIT_TARGET_FLAG_RANGED_ONLY||Units with AttackCapabilities DOTA_UNIT_CAP_RANGED_ATTACK.|
|DOTA_UNIT_TARGET_FLAG_MANA_ONLY||Units with mana, without |
|DOTA_UNIT_TARGET_FLAG_CHECK_DISABLE_HELP||Units with Disable Help on.|
Not sure how to make a DataDriven ability use it?
|DOTA_UNIT_TARGET_FLAG_NO_INVIS||Ignores invisible units (with MODIFIER_STATE_INVISIBLE.)|
|DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES||Targets ENEMY units with |
Examples: Ensnare, Culling Blade, Primal Roar...
|DOTA_UNIT_TARGET_FLAG_NOT_MAGIC_IMMUNE_ALLIES||Ignores FRIENDLY units with |
Example: Bane's Nightmare.
|DOTA_UNIT_TARGET_FLAG_NOT_ATTACK_IMMUNE||Ignores units with |
|DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE||Breaks when the unit goes into the fog of war.|
Examples: Mana Drain, Life Drain.
|DOTA_UNIT_TARGET_FLAG_INVULNERABLE||Units with |
Examples: Assassinate, Recall, Boulder Smash...
|DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS||Ignores units with |
Example: Hand of Midas.
|DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO||Ignores units with |
Examples: Astral Imprisonment, Disruption, Sunder.
|DOTA_UNIT_TARGET_FLAG_NOT_DOMINATED||Ignores units with |
|DOTA_UNIT_TARGET_FLAG_NOT_ILLUSIONS||Ignores untis with |
|DOTA_UNIT_TARGET_FLAG_NOT_NIGHTMARED||Ignores units with |
|DOTA_UNIT_TARGET_FLAG_NOT_SUMMONED||Ignores units created through the |
|DOTA_UNIT_TARGET_FLAG_OUT_OF_WORLD||Units with |
|DOTA_UNIT_TARGET_FLAG_PLAYER_CONTROLLED||Units controllable by a player, accesible with Lua's |
|DOTA_UNIT_TARGET_FLAG_PREFER_ENEMIES||Prioritizes units over trees when both are selectable.|
Fun with Flags
Flags were seen as AbilityUnitTargetFlags completions, but this is not their sole application.
The same applies to Team and Types.
"Target"block gives control over how to target units to apply actions on them later:
"LinearProjectile"action allows a
LinearProjectileto ignore units that would otherwise be included by default in the Team+Type values, for example those with
"Aura_Flags"in a modifier with the other
"Aura"keys can be used, for example, to make an aura modifier only affect ranged units by adding
The same applies for Teams and Types.
Example: Targets all friendly units in a radius of the caster, including couriers, buildings, and siege units. Excludes heroes, summons, and other player controlled units.
Example: Mirana's Arrow projectile rewrite that only hits heroes, including those that are magic immune:
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, and with
Other keyvalues of the Action Target block
To target units in a line between the caster and the targeted point.
Instead of the
"Radius" keyvalue, which only takes one parameter,
Thickness integer values in a block like this:
Limiting the amount of targets
MaxTargets takes an integer value to limit the amount of targets the Target block will select.
Random also takes an integer to be as "take up to this number of units randomly."
(For more complex targeting, Lua scripting is the answer.)
Its use is very rare, normally when the targeting is complex we would just use
RunScript lua and do all the acitons inside the script.
A more in-depth explanation is needed to explain the complete usage of the Target block, as understanding the scope of the "Target" "TARGET" keyvalue is one of the most difficult things of the datadriven system.
- Constants wiki
- Abilities Data Driven wiki
- Extracted npc_abilities.txt file
- holdout_example keyvalues
- random github datamining
- brute-forcing everything for countless hours!
If you have any content to expand or improve this documentation, please let me know.