Difference between revisions of "Dota 2 Workshop Tools/Scripting/Abilities Data Driven"

From Valve Developer Community
Jump to: navigation, search
m (A Simple Example)
(Added the DestroyTrees k/v)
Line 127: Line 127:
 
  "RemoveAbility"
 
  "RemoveAbility"
 
     "Target", "AbilityName"
 
     "Target", "AbilityName"
 +
"DestroyTrees"
 +
    "Target"
 
</source>
 
</source>
  

Revision as of 15:33, 13 August 2014

Most abilities in Dota 2 are defined by C++ code. When looking at these abilities, the npc_abilities.txt keyvalues file contains some ability metadata and exposes some tuning knobs, these are mostly metadata with all the actual behavior defined in code. The data driven ability system is a method to create custom abilities for Dota 2 and assign special properties and events to occur when they're used.

A Simple Example

Here is a very simple example ability. It's a passive that applies a visual effect to the unit with that ability.

"fx_test_ability"
{
 // General
 //-------------------------------------------------------------------------------------------------------------
 "BaseClass"			"ability_datadriven"
 "AbilityBehavior"		"DOTA_ABILITY_BEHAVIOR_PASSIVE"
 "AbilityTextureName"		"axe_battle_hunger"
 // Modifiers
 //-------------------------------------------------------------------------------------------------------------
 "Modifiers"
 {
  "fx_test_modifier"
  {
   "Passive" "1"
   "OnCreated"
   {
    "AttachEffect"
    {
     "Target" "CASTER"
     "EffectName" "generic_buff_1"
     "EffectAttachType" "follow_overhead"
     "EffectLifeDurationScale" "1"
     "EffectColorA" "255 255 0"
    }
   }
  }
 }
}


The "BaseClass", "AbilityBehavior" and "AbilityTextureName" keys are common to all abilities:

"BaseClass" - Normally DOTA chooses the C++ class to connect to an ability by looking at the ability name (in this case "fx_test_ability"). If you'd like to force DOTA to use a different C++ class, the "BaseClass" key will do that - in this example we're using the ability_datadriven class to connect to the data driven ability system. It's possible to use this key to connect to any other existing ability code to make a new variant of an old ability, with different settings for whatever that ability exposes to keyvalues.

"ID" - ID is a unique number for stats tracking. This is not used for data driven abilities.

"AbilityBehavior" is a set of flags describing some properties of the ability. You can put flags in here separated by spaces and | for example "DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NO_TARGET" - the spaces are important!

DOTA_ABILITY_BEHAVIOR_HIDDEN				= 1 << 0, //This ability can be owned by a unit but can't be casted and wont show up on the HUD.
DOTA_ABILITY_BEHAVIOR_PASSIVE				= 1 << 1, //Can't be casted like above but this one shows up on the ability HUD
DOTA_ABILITY_BEHAVIOR_NO_TARGET				= 1 << 2, //Doesn't need a target to be cast, ability fires off as soon as the button is pressed
DOTA_ABILITY_BEHAVIOR_UNIT_TARGET			= 1 << 3, //Ability needs a target to be casted on.
DOTA_ABILITY_BEHAVIOR_POINT					= 1 << 4, //Ability 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_AOE					= 1 << 5, //This ability draws a radius where the ability will have effect. Kinda like POINT but with a an area of effect display.
DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE			= 1 << 6, //This ability probably can be casted or have a casting scheme but cannot be learned (these are usually abilities that are temporary like techie's bomb detonate)
DOTA_ABILITY_BEHAVIOR_CHANNELLED			= 1 << 7, //This ability is channeled. If the user moves or is silenced the ability is interrupted.
DOTA_ABILITY_BEHAVIOR_ITEM					= 1 << 8, //This ability is tied up to an item.
DOTA_ABILITY_BEHAVIOR_TOGGLE				= 1 << 9, //This ability can be insta-toggled
DOTA_ABILITY_BEHAVIOR_DIRECTIONAL			= 1 << 10, //This ability has a direction from the hero, such as miranas arrow or pudge's hook
DOTA_ABILITY_BEHAVIOR_IMMEDIATE				= 1 << 11, //This ability can be used instantly without going into the action queue
DOTA_ABILITY_BEHAVIOR_AUTOCAST				= 1 << 12, //This ability can be casted automatically
DOTA_ABILITY_BEHAVIOR_NOASSIST				= 1 << 13, //This ability has no reticle assist
DOTA_ABILITY_BEHAVIOR_AURA					= 1 << 14, //This ability is an aura. We don't really use this other than to tag the ability as so
DOTA_ABILITY_BEHAVIOR_ATTACK				= 1 << 15, //This ability is an attack and cannot hit attack-immune targets
DOTA_ABILITY_BEHAVIOR_DONT_RESUME_MOVEMENT	= 1 << 16, //This ability should not resume movement when it completes. Only applicable to no-target, non-immediate abilities.
DOTA_ABILITY_BEHAVIOR_ROOT_DISABLES			= 1 << 17, //This ability cannot be used when rooted
DOTA_ABILITY_BEHAVIOR_UNRESTRICTED			= 1 << 18, //This ability is allowed when commands are restricted
DOTA_ABILITY_BEHAVIOR_IGNORE_PSEUDO_QUEUE	= 1 << 19, //This ability can be executed while stunned, casting, or force-attacking. Only applicable to toggled abilities.
DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL		= 1 << 20, //This ability can be executed without interrupting channels
DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_MOVEMENT  = 1 << 21, //This ability doesn't cause certain modifiers to end, used for courier and speed burst 
DOTA_ABILITY_BEHAVIOR_DONT_ALERT_TARGET		= 1 << 22, //This ability does not alert enemies when target-cast on them
DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK	= 1 << 23, //This 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	= 1 << 24, //This ability still uses its normal cast point when stolen.
DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING		= 1 << 25, //This ability ignores backswing psuedoqueue
DOTA_ABILITY_BEHAVIOR_RUNE_TARGET			= 1 << 26, //TArgets Runes


"AbilityTextureName" is the icon that should be used in the UI for this ability. You can use this to borrow the icon from another ability just by putting that ability name here.

"Modifiers" is unique to data-driven abilities. This block describes a set of modifiers (a.k.a. Buffs) that are unique to this ability. Each modifier is named by the name of the keyvalues block that defines the modifier.

"Passive" in a modifier flags the modifier as a passive modifier that should automatically be applied to the ability owner.

"OnCreated" is an action block that is triggered when the ability is first attached to the owner. In this example, we attach a visual effect to the ability caster.

Ability Events and Actions

Abilities have various in-game events which can trigger behaviour. The events that can trigger actions on an ability are:

"OnToggleOn"
"OnToggleOff"
"OnSpellStart"
"OnOwnerDied"
"OnOwnerSpawned"
"OnProjectileHit"
"OnChannelSucceeded"
"OnChannelFinish"
"OnChannelInterrupted"


Each of these keys is a block that contains one or more action descriptions. The actions you can use are:

 "ApplyModifier"
    "Target" and "ModifierName".
 "AttachEffect"
    "EffectName", "EffectAttachType" and control point data.
 "Blink"
    "Target" (position to blink to)
 "Random"
    "Chance", "PseudoRandom", "OnSuccess" and "OnFailure"
 "CreateThinker"
    "Target" and "ModifierName"
 "Damage"
    "Target", "Type" and "MinDamage"/"MaxDamage" or "Damage"
 "FireEffect"
    "EffectName", "EffectAttachType" and control point data.
 "FireSound"
    "EffectName"
 "Lifesteal"
    "Target" and "LifestealPercent"
 "RemoveModifier"
    "Target" and "ModifierName"
 "LinearProjectile"
    "EffectName", "MoveSpeed", "StartRadius", "EndRadius", "TargetTeams", "TargetTypes", "TargetFlags", "HasFrontalCone".
 "TrackingProjectile"
    "EffectName", "Dodgeable", "ProvidesVision", "VisionRadius", "MoveSpeed", "SourceAttachment"
 "SpawnUnit"
    "UnitName", "UnitCount", "SpawnRadius"
 "AddAbility"
    "Target", "AbilityName"
 "RemoveAbility"
    "Target", "AbilityName"
 "DestroyTrees"
    "Target"
Note:AddAbility adds a new ability at level 0. RemoveAbility deletes the ability even if it has been leveled. More complex ability management should be done through script as opposed to the data driven system.

Action Targets

Target selection for actions exposes some choices. A "Target" key can have a value of "CASTER", "TARGET", "ATTACKER" or "UNIT" for simple single-target selection. These names mean different things in different events - experiment to discover exactly what in each case.

For selecting multiple targets in an area, make the "Target" key a block with the following subkeys:

"Center" - "CASTER", "TARGET", "ATTACKER", "UNIT"
"Radius" - The radius to search for target in.
"Teams" - Bit field or'ed of 
  DOTA_UNIT_TARGET_TEAM_FRIENDLY
  DOTA_UNIT_TARGET_TEAM_ENEMY
  DOTA_UNIT_TARGET_TEAM_CUSTOM
  DOTA_UNIT_TARGET_TEAM_BOTH
"Types" - Bit field or'ed of
  DOTA_UNIT_TARGET_HERO
  DOTA_UNIT_TARGET_CREEP
  DOTA_UNIT_TARGET_BUILDING
  DOTA_UNIT_TARGET_MECHANICAL
  DOTA_UNIT_TARGET_COURIER
  DOTA_UNIT_TARGET_OTHER
  DOTA_UNIT_TARGET_TREE
  DOTA_UNIT_TARGET_CUSTOM
  DOTA_UNIT_TARGET_BASIC
  DOTA_UNIT_TARGET_ALL
"ExcludeTypes" - As the above, but reject any of the flagged types.
"Flags" - Bit field or'ed of
  DOTA_UNIT_TARGET_FLAG_RANGED_ONLY
  DOTA_UNIT_TARGET_FLAG_MELEE_ONLY
  DOTA_UNIT_TARGET_FLAG_DEAD
  DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES
  DOTA_UNIT_TARGET_FLAG_NOT_MAGIC_IMMUNE_ALLIES
  DOTA_UNIT_TARGET_FLAG_INVULNERABLE
  DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE
  DOTA_UNIT_TARGET_FLAG_NO_INVIS
  DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS
  DOTA_UNIT_TARGET_FLAG_PLAYER_CONTROLLED
  DOTA_UNIT_TARGET_FLAG_NOT_DOMINATED
  DOTA_UNIT_TARGET_FLAG_NOT_SUMMONED
  DOTA_UNIT_TARGET_FLAG_NOT_ILLUSIONS
  DOTA_UNIT_TARGET_FLAG_NOT_ATTACK_IMMUNE
  DOTA_UNIT_TARGET_FLAG_MANA_ONLY
  DOTA_UNIT_TARGET_FLAG_CHECK_DISABLE_HELP
  DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO
  DOTA_UNIT_TARGET_FLAG_OUT_OF_WORLD
  DOTA_UNIT_TARGET_FLAG_NOT_NIGHTMARED
"ExcludeFlags" - As the above, but reject any of the flagged states.


Modifier Properties

Modifier properties are gameplay values a modifier can change on the unit it is applied to. Here's a simple example of a modifier that slows attacks and movement speed (this chunk is a block inside the "Modifiers" block of an ability). To specify numeric values, you can put in a number or you can use %name formatting to grab values out of the AbilitySpecial block of the Ability. The advantage to using the %name syntax is that the value can change as the ability levels up and the numeric value can be formatted into tooltips. In this example, the slow duration comes from an AbilitySpecial block, but the slow values are just numbers.

"creature_slithereen_crush_slow"
{
 "Duration"	"%slow_duration"
 "Properties"
 {
   "MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE" "-20"
   "MODIFIER_PROPERTY_ATTACKSPEED_BONUS_PERCENTAGE" "-20"
 }
}

Here is a list of the properties you can put in a modifier:

MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE
MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE
MODIFIER_PROPERTY_PERSISTENT_INVISIBILITY
MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT
MODIFIER_PROPERTY_MOVESPEED_BASE_OVERRIDE
MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE
MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE_UNIQUE
MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE
MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE
MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT
MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT_SECONDARY
MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT
MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE
MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION
MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE
MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE
MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_PERCENTAGE
MODIFIER_PROPERTY_INCOMING_SPELL_DAMAGE_CONSTANT
MODIFIER_PROPERTY_EVASION_CONSTANT
MODIFIER_PROPERTY_AVOID_DAMAGE
MODIFIER_PROPERTY_AVOID_SPELL
MODIFIER_PROPERTY_MISS_PERCENTAGE
MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS
MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_ILLUSIONS
MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE
MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE_ACTIVE
MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS
MODIFIER_PROPERTY_MAGICAL_RESISTANCE_ITEM_UNIQUE
MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DECREPIFY_UNIQUE
MODIFIER_PROPERTY_BASE_MANA_REGEN
MODIFIER_PROPERTY_MANA_REGEN_CONSTANT
MODIFIER_PROPERTY_MANA_REGEN_CONSTANT_UNIQUE
MODIFIER_PROPERTY_MANA_REGEN_PERCENTAGE
MODIFIER_PROPERTY_MANA_REGEN_TOTAL_PERCENTAGE
MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT
MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE
MODIFIER_PROPERTY_HEALTH_BONUS
MODIFIER_PROPERTY_MANA_BONUS
MODIFIER_PROPERTY_STATS_STRENGTH_BONUS
MODIFIER_PROPERTY_STATS_AGILITY_BONUS
MODIFIER_PROPERTY_STATS_INTELLECT_BONUS
MODIFIER_PROPERTY_ATTACK_RANGE_BONUS
MODIFIER_PROPERTY_RESPAWNTIME
MODIFIER_PROPERTY_DEATHGOLDCOST
MODIFIER_PROPERTY_PREATTACK_CRITICALSTRIKE
MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK
MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_UNAVOIDABLE_PRE_ARMOR
MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK
MODIFIER_PROPERTY_OVERRIDE_ANIMATION
MODIFIER_PROPERTY_OVERRIDE_ANIMATION_WEIGHT
MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE
MODIFIER_PROPERTY_DISABLE_AUTOATTACK
MODIFIER_PROPERTY_BONUS_DAY_VISION
MODIFIER_PROPERTY_BONUS_NIGHT_VISION
MODIFIER_PROPERTY_MIN_HEALTH
MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PHYSICAL
MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_MAGICAL
MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PURE
MODIFIER_PROPERTY_IS_ILLUSION
MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE
MODIFIER_PROPERTY_DISABLE_HEALING


Modifier States

States are very similar to properties, except they are tri-state values. A state can have the value "MODIFIER_STATE_VALUE_NO_ACTION", "MODIFIER_STATE_VALUE_ENABLED" or "MODIFIER_STATE_VALUE_DISABLED". This example modifier attaches a simple stunned effect, overrides the base unit's animation and forces the unit into the stunned state:

"creature_bash_ministun"
{
 "Duration" "%duration"
 "EffectName" "generic_stunned"
 "EffectAttachType" "follow_overhead"
 "Duration"  "%stun_duration"
 "OverrideAnimation" "ACT_DOTA_DISABLED"
 "States"
 {
   "MODIFIER_STATE_STUNNED" "MODIFIER_STATE_VALUE_ENABLED"
 }			
}


Here is a list of all the states available to a modifier:

MODIFIER_STATE_ROOTED
MODIFIER_STATE_SOFT_DISARMED
MODIFIER_STATE_DISARMED
MODIFIER_STATE_ATTACK_IMMUNE
MODIFIER_STATE_SILENCED
MODIFIER_STATE_MUTED
MODIFIER_STATE_STUNNED
MODIFIER_STATE_HEXED
MODIFIER_STATE_INVISIBLE
MODIFIER_STATE_INVULNERABLE
MODIFIER_STATE_MAGIC_IMMUNE
MODIFIER_STATE_PROVIDES_VISION
MODIFIER_STATE_NIGHTMARED
MODIFIER_STATE_BLOCK_DISABLED
MODIFIER_STATE_EVADE_DISABLED
MODIFIER_STATE_UNSELECTABLE
MODIFIER_STATE_CANNOT_MISS
MODIFIER_STATE_SPECIALLY_DENIABLE
MODIFIER_STATE_FROZEN
MODIFIER_STATE_COMMAND_RESTRICTED
MODIFIER_STATE_NOT_ON_MINIMAP
MODIFIER_STATE_NOT_ON_MINIMAP_FOR_ENEMIES
MODIFIER_STATE_LOW_ATTACK_PRIORITY
MODIFIER_STATE_NO_HEALTH_BAR
MODIFIER_STATE_FLYING
MODIFIER_STATE_NO_UNIT_COLLISION
MODIFIER_STATE_NO_TEAM_MOVE_TO
MODIFIER_STATE_NO_TEAM_SELECT
MODIFIER_STATE_PASSIVES_DISABLED
MODIFIER_STATE_DOMINATED
MODIFIER_STATE_BLIND
MODIFIER_STATE_OUT_OF_GAME


Modifier Events

Modifiers can also describe actions that should happen on various in-game events. Each of these keys is a block that describes actions - the action description system is documented elsewhere on this page. The events that are supported are:

OnCreated - The modifier has been created.
OnAttacked - The unit this modifier is attached to has been attacked.
OnAttackLanded - The unit this modifier is attached to has landed an attack on a target.
OnDestroy - The modifier has been removed.

A More Complex Example

Here is an ability that waits for the owner to die. On death, a thinker is created with an acid pool visual effect and an aura modifier which reduces armor and applies a damage over time effect.

//=================================================================================================================
// Creature: Acid Spray
//=================================================================================================================
"creature_acid_spray"
{
 // General
 //-------------------------------------------------------------------------------------------------------------
 "BaseClass" 					"ability_datadriven"
 "AbilityBehavior"				"DOTA_ABILITY_BEHAVIOR_AOE"
 "AbilityUnitDamageType"			"DAMAGE_TYPE_COMPOSITE"
 "AbilityTextureName"			"alchemist_acid_spray"
 // Casting
 //-------------------------------------------------------------------------------------------------------------
 "AbilityCastPoint"				"0.2"
 "AbilityCastRange"				"900"
 "OnOwnerDied"
 {
   "CreateThinker"
   {
    "ModifierName" "creature_acid_spray_thinker"
    "Target" "CASTER"
   }
 }
 "Modifiers"
 {
  "creature_acid_spray_thinker"
  {
   "Aura" "create_acid_spray_armor_reduction_aura"
   "Aura_Radius" "%radius"
   "Aura_Teams" "DOTA_UNIT_TARGET_TEAM_ENEMY"
   "Aura_Types" "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_CREEP | DOTA_UNIT_TARGET_MECHANICAL"
   "Aura_Flags" "DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES"
   "Duration" "%duration"
   "OnCreated"
   {
    "AttachEffect"
    {
      "EffectName" "alchemist_acid_spray"
      "EffectAttachType" "follow_origin"
      "Target" "TARGET"
      "ControlPoints"
      {
       "00" "0 0 0"
       "01" "%radius 1 1"
      }
     }
    }
   }
   "create_acid_spray_armor_reduction_aura"
   {
    "IsDebuff" "1"
    "IsPurgable" "0"
    "EffectName" "alchemist_acid_spray_debuff"				
    "ThinkInterval" "%tick_rate"
    "OnIntervalThink"
    {
      "Damage"
      {
       "Type" "DAMAGE_TYPE_COMPOSITE"
       "Damage" "%damage"
       "Target" "TARGET"
      }
     }
     "Properties"
     {
       "MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS" "%armor_reduction"
     }
    }
   }
 // Special	
 //-------------------------------------------------------------------------------------------------------------
 "AbilitySpecial"
 {
  "01"
  {
   "var_type"				"FIELD_INTEGER"
   "radius"				"250"
  }
  "02"
  {
   "var_type"				"FIELD_FLOAT"
   "duration"				"16.0"
  }
  "03"
  {
   "var_type"				"FIELD_INTEGER"
   "damage"				"118 128 138 158"
  }
  "04"
  {
   "var_type"				"FIELD_INTEGER"
   "armor_reduction"		        "-3 -4 -5 -6"
  }
  "05"
  {
   "var_type"				"FIELD_FLOAT"
   "tick_rate"				"1.0"
  }
 }
}