Skip to main content

Unit KeyValues

This document covers every keyvalue of the npc_units_custom file

img

General

Most unit names start with "npc_" but this isn't necessary. A basic unit definition looks like this:

https://pastebin.com/KB7EsSLF

The definition of the default dota units can be found in npc_units.txt

Base Classes

There are a lot of classes for units, the complete list can be found in here, but as we don't have much control over their properties, only a few are really useful for custom units in general:

  • npc_dota_creature

    The most useful baseclass, it doesn't have any critical hardcoded property so it's the go-to unit type for most units. It also allows the usage of the "Creature" block, which will is reviewed in the next section. It's linked to the "DOTA_UNIT_TARGET_BASIC" target type in abilities.

    There is however one simple property imposed to this unit type, which for the most part it's useful but it's good to keep in mind, and it's that abilities are automatically skilled up to the MaxLevel if possible (limited by the Level*2 of the creature, meaning a Level 1 creature will autolearn its abilities upto the 2nd rank). This can be of course modified through Lua SetLevel on each ability.

  • npc_dota_building

    Linked to "DOTA_UNIT_TARGET_BUILDING", this baseclass can prove useful in many situations.

    It has the following properties imposed to it, which we have no control over them:

    • Invulnerable by default. Very annoying, it can be removed through Lua with building_handle:RemoveModifierByName("modifier_invulnerable")
    • Visible through fog. This is troublesome, and forces any game that wants to have building strategies to use npc_dota_creature and define custom building damage, with some other downsides.
    • No visual turning, even if internally the unit is actually changing its forward vector. Usually a good thing, the creature equivalent behavior for this is the stunned state.
      Worth mentioning `npc_dota_tower` is a subclass of building, and is coded to trigger stuff like the announcers, team gold sharing and aggro AI. Use npc_dota_building with attack to make towers that aren't forced to use those mechanics.
  • npc_dota_thinker

    For dummy units. More on this later


For the rest of this guide, we'll be assuming a `"BaseClass" "npc_dota_creature"`

Level

"Level"                        "32"

img

This level can be accessed and modified with Lua though various creature functions.

Model and Scale

"Model"                        "models/heroes/dragon_knight/dragon_knight.vmdl"
"ModelScale" "0.8"

Self explanatory, get the models through the asset browser and set its size (it will use "1" by omission).

Creatures using models that are broken down for cosmetic equipment will be 'naked' unless we attach them wearables. More on this later.

Minimap Icons

"MinimapIcon"               "minimap_candybucket"
"MinimapIconSize" "1000"

Produces: img

Unit Label

"UnitLabel"                    "healing_ward"

This can be any name, its only useful purpose is to use with Lua GetUnitLabel() which can work as an easy method of tagging units.

Boolean Values and Flags

"HasInventory"                "1"

Associated Lua functions: HasInventory() and SetHasInventory(bool)

Note: SetHasInventory(true) won't work on units that didn't have "HasInventory" "1" previously defined.

"IsSummoned"                "1"
"CanBeDominated" "0"

Self explanatory, the default values are 0 for summoned (so the lua IsSummoned will always return false unless you set this), and 1 for dominated creaturesl


``` "ConsideredHero" "1" ```

"DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO" datadriven flag. Gives the unit a hero styled health bar:

img


``` "IsAncient" "1" ``` Associated Lua function: `IsAncient()`
`"DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS"` datadriven flag.
``` "IsNeutralUnitType" "1" ```

Associated Lua function: IsNeutralUnitType()


``` "CanBeDominated" "0" ```

Helm of the Dominator specific. No associated Lua function, but it's easy to make one to read from this value if you wish.


``` "AutoAttacksByDefault" "0" ```

Ignores Auto Attack Behavior setting, forces to not autoattack. Used on Visage Familiars.


``` "ShouldDoFlyHeightVisual" "0" ```

img

Seems broken, no noticeable difference.


``` "WakesNeutrals" "1" ```

Unit won't aggro units on the Neutral team within their acquisition range.

Selection properties

"SelectionGroup"               "string"              
"SelectOnSpawn" "1"
"IgnoreAddSummonedToSelection" "1"
  • SelectionGroup will make it so that all the units of this type are in a group which can be accessed through tab.

img I pressed tab once and all these units got selected after defining them in the same control group

  • SelectOnSpawn forces the unit into the selection of the hero, even if the "Auto Select Summoned Units" setting is turned off. It's used on Visage Familiars.

  • IgnoreAddSummonedToSelection if set to 1, makes the "Auto Select Summoned Units" ignore this unit when it spawns. It's used on Brewmaster Primal Split units.

Sounds

"SoundSet"                     "Hero_DragonKnight"
"GameSoundsFile" "soundevents/game_sounds_heroes/game_sounds_dragon_knight.vsndevts"
"IdleSoundLoop" "Hero_DragonKnight.Tutorial_Intro"
  • SoundSet with the correct GameSoundsFile associated takes care of sounds like attacks and walking footsteps. The SoundSet string should be the first part of each of the hero sounds, which can be easily seen through the Dota 2 Sound Editor. Example

  • IdleSoundLoop will be played constantly after the unit spawns. Some heroes don't have a loop sound defined, but as in the example above it's possible to use this as an Spawn sound for the unit if you add the string of a non-loopable sound.

Abilities

"AbilityLayout"               "4"
"Ability1" "" // Ability 1.
//"Ability2" ... up to "Ability16"

The unit can hold up to 16 abilities at any time being.

"AbilityLayout" is used for the built-in Flash UI to change how many abilities it can display, and currently its limited to 4, 5 and 6 (anything else will malfunction)

Stats

Because of :valve: - reasons , unit stats aren't hover-able, but they are there.

Physical and Magical protection

"ArmorPhysical"                "0"
"MagicalResistance" "0"

Attack Capabilities

"AttackCapabilities"         "DOTA_UNIT_CAP_NO_ATTACK"

List of Attack Capabilities:

  • DOTA_UNIT_CAP_NO_ATTACK
  • DOTA_UNIT_CAP_MELEE_ATTACK
  • DOTA_UNIT_CAP_RANGED_ATTACK

Other Attack Stats:

"AttackDamageMin"            "50"       // Damage range min.
"AttackDamageMax" "40" // Damage range max.
"AttackRate" "1.7" // Speed of attack.
"AttackAnimationPoint" "0.75" // Normalized time in animation cycle to attack.
"AttackAcquisitionRange" "800" // Range within a target can be acquired.
"AttackRange" "600" // Range within a target can be attacked.
"AttackRangeBuffer" "250" // Extra range the target can move without canceling the attack

Ranged Attack Projectiles

"ProjectileModel"            "particles/units/heroes/hero_lina/lina_base_attack.vpcf"
"ProjectileSpeed" "900"

Find hero/unit attack particles with the asset browser, filtering for the hero name + "attack vpcf"

If you have any "Melee to Ranged" mechanic, the unit definition should have a projectile speed, else it will default to 0, effectively making them never reach its target.

The things we could do...

"AttackDamageType"           "DAMAGE_TYPE_ArmorPhysical"

This is seen in every unit file, but worthless/unsupported. In the future, we could see it being used to easily define Air/Ground attacks, Magic Attacks, etc, which currently require scripted abilities to simulate those behaviors.

Attribute Stats

Attributes are ignored for anything that isn't a hero unit, but because anything used to define units can also be used for npc_heroes_custom, these are the keyvalues, all self explanatory:

"AttributePrimary"             "DOTA_ATTRIBUTE_STRENGTH"
"AttributeBaseStrength" "0" // Base strength
"AttributeStrengthGain" "0" // Strength bonus per level.
"AttributeBaseAgility" "0" // Base agility
"AttributeAgilityGain" "0" // Agility bonus per level.
"AttributeBaseIntelligence" "0" // Base intelligence
"AttributeIntelligenceGain" "0" // Intelligence bonus per level.

Bounty

If you want to make any complex rule for XP/Gold, for example, give less XP from this unit to heroes at a certain level, it's better to leave the values at 0 and grant it through lua.

"BountyXP"                    "0"            // Experience earn.
"BountyGoldMin" "0" // Gold earned min.
"BountyGoldMax" "0" // Gold earned max.

Bounds

This defines the unit collision with other units.

"BoundsHullName"            "DOTA_HULL_SIZE_HERO"

Bound Size Reference:

ValueRadius in Hammer units
DOTA_HULL_SIZE_SMALL8
DOTA_HULL_SIZE_REGULAR16
DOTA_HULL_SIZE_SIEGE16
DOTA_HULL_SIZE_HERO24
DOTA_HULL_SIZE_HUGE80
DOTA_HULL_SIZE_BUILDING81
DOTA_HULL_SIZE_FILLER96
DOTA_HULL_SIZE_BARRACKS144
DOTA_HULL_SIZE_TOWER144
  • Lua SetHullRadius(float) can change this to any value in between or even above 144.
"RingRadius"                "70"

The visible selection ring when the unit is selected

img

"HealthBarOffset"           "250"

The height from the ground at which the Health Bar should be placed. By default this value is set to "-1" to use the models default height. The bigger the Model and ModelScale, this should be adjusted to a higher number so it doesn't look weird.

img

Movement

"MovementCapabilities"        "DOTA_UNIT_CAP_MOVE_NONE"
"MovementSpeed" "300" // Speed
"MovementTurnRate" "0.5" // Turning rate.

List of Movement Capabilities

  • DOTA_UNIT_CAP_MOVE_NONE
  • DOTA_UNIT_CAP_MOVE_GROUND
  • DOTA_UNIT_CAP_MOVE_FLY
"HasAggressiveStance"         "0"

Plays alternate idle/run animation when near enemies, e.g. Abaddon model

"FollowRange"                 "100"

Distance to keep when following. Healing Ward/Sigil have it set at 250.

Health and Mana

"StatusHealth"                "150"       // Base health.
"StatusHealthRegen" "0" // Health regeneration rate.
"StatusMana" "0" // Base mana.
"StatusManaRegen" "0" // Mana regeneration rate.

Notes:

  • Negative Health/Mana Regen doesn't work.
  • Setting StatusMana on 0 will make it not have a mana bar.
  • There is currently no way of Setting MAX Mana in Lua! Unit mana pool modification has to be done with the Creature block and Levels.

Rarely used:

"StatusStartingMana"          "-1"

-1 means default to full mana, which is the default. It can be changed to any integer value so the units don't spawn with a filled pool.

Armor and Attack Types

The Table of Physical Attacks vs Armor Types can be found here in this link to the dota wiki

"CombatClassAttack"           "DOTA_COMBAT_CLASS_ATTACK_HERO"
"CombatClassDefend" "DOTA_COMBAT_CLASS_DEFEND_HERO"

Attack Types Table

NameDota Equivalent
NormalDOTA_COMBAT_CLASS_ATTACK_BASIC
PierceDOTA_COMBAT_CLASS_ATTACK_PIERCE
SiegeDOTA_COMBAT_CLASS_ATTACK_SIEGE
ChaosDOTA_COMBAT_CLASS_ATTACK_LIGHT
HeroDOTA_COMBAT_CLASS_ATTACK_HERO

Armor Types Table

NameDota Equivalent
UnarmoredDOTA_COMBAT_CLASS_DEFEND_SOFT
LightDOTA_COMBAT_CLASS_DEFEND_WEAK
MediumDOTA_COMBAT_CLASS_DEFEND_BASIC
HeavyDOTA_COMBAT_CLASS_DEFEND_STRONG
FortifiedDOTA_COMBAT_CLASS_DEFEND_STRUCTURE
HeroDOTA_COMBAT_CLASS_DEFEND_HERO

Vision

"VisionDaytimeRange"        "1200"        // Range of vision during day light.
"VisionNighttimeRange" "1800" // Range of vision at night time.

Vision on any unit can't exceed 1800, any value above that will just default to 1800.


## Unit Relationship Class

This doesn't seem to make any difference, might be deprecated or just used for tagging stuff internally.

"UnitRelationshipClass"       "DOTA_NPC_UNIT_RELATIONSHIP_TYPE_DEFAULT"

List:

  • DOTA_NPC_UNIT_RELATIONSHIP_TYPE_BARRACKS
  • DOTA_NPC_UNIT_RELATIONSHIP_TYPE_BUILDING
  • DOTA_NPC_UNIT_RELATIONSHIP_TYPE_COURIER
  • DOTA_NPC_UNIT_RELATIONSHIP_TYPE_DEFAULT
  • DOTA_NPC_UNIT_RELATIONSHIP_TYPE_HERO
  • DOTA_NPC_UNIT_RELATIONSHIP_TYPE_SIEGE
  • DOTA_NPC_UNIT_RELATIONSHIP_TYPE_WARD

Lua VScript AI

"vscripts"                    "path_to_ai_script.lua"

This will load a lua script file as soon as the unit is spawned. With a Spawn ( entityKeyValues ) function one can initiate a thinker to do any sort of logic, this is a very simple example for a unit that goes through a series of waypoints while casting spells anytime its possible: ai_tank_miniboss.lua.

Neutral Behavior

When you add a creep to the map and set it to the neutral team, the default is to turn it to a neutral. If you wan't to use a custom behavior, turn it off:

"UseNeutralCreepBehavior"   "0"

Creature Block

The creature block allows for a variety of features to be applied from KV like basic AI, stat bonuses based on creature level, and wearables. All these settings can and should be put inside one creature block, but they will be separated by category in this guide

Stats Settings and Items

"Creature"
{
"CanRespawn" "0"

//Pathing Setting
"DisableClumpingBehavior" "1"

//Level Up Parameters
"HPGain" "10"
"DamageGain" "20"
"ArmorGain" "0.25"
"MagicResistGain" "0"
"MoveSpeedGain" "1"
"BountyGain" "3"
"XPGain" "15"

"DisableResistance" "80.0"

//Starting Items | Note: requires "HasInventory" "1" outside of creature block
"EquippedItems"
{
"Maelstrom" { "Item" "item_maelstrom" }
"Treads" { "Item" "item_power_treads" }
"SnY" { "Item" "item_sange_and_yasha" }
}
}

Wearables

See this guide for more info.

"Creature"
{
"AttachWearables"
{
"Wearable1" { "ItemDef" "101" }
"Wearable2" { "ItemDef" "102" }
"Wearable3" { "ItemDef" "103" }
}
}

Creature AI

I highly recommend using Lua for AI instead, but will leave some information here anyway.

"Creature"
{
// ?
"PermanentDesire" "1"

"DefaultState" "Invade"

"States"
{
"Invade"
{
"Name" "Invade"
"Aggression" "100.0"
"Avoidance" "0.0"
"Support" "0.0"
"RoamDistance" "2000.0"
}
}

"OffensiveAbilities"
{
"Ability1"
{
"Name" "broodmother_spawn_spiderlings"
}
"Ability2"
{
"Name" "centaur_hoof_stomp"

//Targeting Parameters
"Radius" "275"
"MinimumTargets" "2"
"UseAtHealthPercent" "50"
"UseSelfishly" "1"

//Ability Descriptors
"AOE" "1"
"Debuff" "1"
"Buff" "1"
"Stun" "1"
"Damage" "1"
"Heal" "1"
}
}
"DefensiveAbilities"
{
"Ability1"
{
"Name" "undying_tombstone"
"AOE" "1"
"Radius" "1000"
"MinimumTargets" "1"
}
}
}