From 549fa2c90dec35ce6ec3b6ac48b946f6319b6e94 Mon Sep 17 00:00:00 2001 From: Michael Kryukov Date: Tue, 1 Apr 2025 00:40:40 +0300 Subject: [PATCH] fix: replace AbilitySpecial with AbilityValues --- _articles/abilities/ability-keyvalues.md | 2 +- .../abilities/abilityduration-tooltips.md | 17 +- .../datadriven/all-about-the-target.md | 21 +- .../datadriven/channeling-animations.md | 18 +- .../datadriven-ability-events-modifiers.md | 10 +- .../invisibility-ability-example.md | 183 ++++++++---------- .../point-channeling-aoe-ability-example.md | 83 +++----- _articles/abilities/item-keyvalues.md | 2 +- _articles/abilities/lua-item-tutorial.md | 89 ++------- ... passing-abilityvalues-values-into-lua.md} | 24 +-- .../reutilizing-built-in-modifiers.md | 79 +++----- ...the-importance-of-abilityspecial-values.md | 27 --- .../the-importance-of-abilityvalues-values.md | 24 +++ .../Typescript/typescript-ability.md | 41 +--- .../Typescript/typescript-modifier.md | 15 +- _articles/scripting/custom-mana-system.md | 39 ++-- .../units/creating-units-with-a-duration.md | 16 +- sidebars.json | 4 +- 18 files changed, 258 insertions(+), 436 deletions(-) rename _articles/abilities/{passing-abilityspecial-values-into-lua.md => passing-abilityvalues-values-into-lua.md} (66%) delete mode 100644 _articles/abilities/the-importance-of-abilityspecial-values.md create mode 100644 _articles/abilities/the-importance-of-abilityvalues-values.md diff --git a/_articles/abilities/ability-keyvalues.md b/_articles/abilities/ability-keyvalues.md index 05954a50..97fc2dd9 100644 --- a/_articles/abilities/ability-keyvalues.md +++ b/_articles/abilities/ability-keyvalues.md @@ -11,7 +11,7 @@ TODO: Some categories are missing: [![Cast Animation](https://i.imgur.com/ewEWcom.png)](##animation "Animation when the spell starts casting") [![General Stats](https://i.imgur.com/5mO6j4Z.png)](##stats "General numeric values") [![Others](https://i.imgur.com/z73NEKo.png)](##others "Other less common values") -[![Ability Special](https://i.imgur.com/3ynaE40.png)](##special "AbilitySpecial block, used for variables") +[![Ability Special](https://i.imgur.com/3ynaE40.png)](##special "AbilityValues block, used for variables") [![precache](https://i.imgur.com/qKW3Xs4.png)](##precache "Precache block, used to preload assets") [![Ability Events](https://i.imgur.com/6IFhMIu.png)](##abilityevents "Triggers on the ability to perform Actions") [![Modifiers](https://i.imgur.com/XEFsYCD.png)](##modifiers "Effects that can be applied on units") diff --git a/_articles/abilities/abilityduration-tooltips.md b/_articles/abilities/abilityduration-tooltips.md index 143c9b23..848a19b8 100644 --- a/_articles/abilities/abilityduration-tooltips.md +++ b/_articles/abilities/abilityduration-tooltips.md @@ -5,7 +5,7 @@ steamId: '76561198046984233' date: 15.12.2014 --- -**TL;DR:** AbilityDuration is a fairly useless keyvalue because whoever coded it forgot to make an automatic tooltip like with `AbilityDamage`. Use a "duration" AbilitySpecial and connect it with lua instead. +**TL;DR:** AbilityDuration is a fairly useless keyvalue because whoever coded it forgot to make an automatic tooltip like with `AbilityDamage`. Use a "duration" AbilityValue and connect it with lua instead. Imagine you want to have an ability apply a modifier for some seconds, duration changing with levels. @@ -19,24 +19,20 @@ And then have your modifier refer to %AbilityDuration in the "Duration" modifier But when when you want to indicate that your ability lasts for said duration, this AbilityDuration doesn't generate a **"DURATION:"** tooltip by itself, so you have 3 options: -**Option 1.** Write "Last 3 seconds at level 1 and then 2 at level 2 and 3" in the _Description. +**Option 1.** Write "Last 3 seconds at level 1 and then 2 at level 2 and 3" in the _Description. This is bad for the reasons explained before. -**Option 2*.** Have a "duration" AbilitySpecial in addition to the "AbilityDuration" and keep both values syncronized. +**Option 2*.** Have a "duration" AbilityValue in addition to the "AbilityDuration" and keep both values syncronized. Suboptimal but decent solution, as it allows you to use ability:GetAbilityDuration() which takes takes its value from AbilityDuration. -**Option 3.** Remove AbilityDuration, only keep the AbilitySpecial. Best way as far as I can tell. +**Option 3.** Remove AbilityDuration, only keep the AbilityValue. Best way as far as I can tell. ``` -"AbilitySpecial" +"AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "duration" "3 2 2" - } + "duration" "3 2 2" } ``` @@ -51,4 +47,3 @@ end ``` Has the same results and works for every scenario. - diff --git a/_articles/abilities/datadriven/all-about-the-target.md b/_articles/abilities/datadriven/all-about-the-target.md index c475caac..825cbbec 100644 --- a/_articles/abilities/datadriven/all-about-the-target.md +++ b/_articles/abilities/datadriven/all-about-the-target.md @@ -91,19 +91,19 @@ Event | Target --|-- OnCreated | CASTER, TARGET OnDestroy | CASTER, TARGET -OnIntervalThink | CASTER, TARGET +OnIntervalThink | CASTER, TARGET OnProjectileDodge | CASTER, TARGET ### Damage In these events we can send an extra parameter, referenced as %attack_damage -Note that this is not a value taken from an AbilitySpecial, instead it is generated by the system to be used in very particular events. +Note that this is not a value taken from an AbilityValues, instead it is generated by the system to be used in very particular events. Event | Target | %attack_damage value --|--|-- -OnTakeDamage | CASTER, UNIT, ATTACKER | post reduction -OnDealDamage | CASTER, UNIT, ATTACKER | post reduction +OnTakeDamage | CASTER, UNIT, ATTACKER | post reduction +OnDealDamage | CASTER, UNIT, ATTACKER | post reduction ### Attacks @@ -114,8 +114,8 @@ Event | Target | %attack_damage value OnAttack | CASTER, TARGET, ATTACKER | 0 OnAttackStart | CASTER, TARGET, ATTACKER | 0 OnAttackAllied | CASTER, TARGET, ATTACKER | 0 -OnAttacked | CASTER, TARGET, ATTACKER | post reduction -OnAttackLanded | CASTER, TARGET, ATTACKER | **before** reduction, the real attack value +OnAttacked | CASTER, TARGET, ATTACKER | post reduction +OnAttackLanded | CASTER, TARGET, ATTACKER | **before** reduction, the real attack value OnAttackFailed | CASTER, TARGET, ATTACKER | **before** reduction, the real attack value ### Killing @@ -123,7 +123,7 @@ OnAttackFailed | CASTER, TARGET, ATTACKER | **before** reduction, the real attac Event | Target --|-- OnDeath | CASTER, UNIT, ATTACKER -OnKill | CASTER, UNIT, ATTACKER +OnKill | CASTER, UNIT, ATTACKER OnHeroKilled | CASTER, TARGET, ATTACKER ### Caster-Unit @@ -132,18 +132,17 @@ Event | Target | Extra --|--|-- OnAbilityEndChannel | CASTER, UNIT | TARGET if the ability isn't NO_TARGET OnAbilityExecuted | CASTER, UNIT | TARGET if the ability isn't NO_TARGET -OnOrder | CASTER, UNIT | TARGET if the Order is an ability with target +OnOrder | CASTER, UNIT | TARGET if the Order is an ability with target OnRespawn | CASTER, UNIT | needs "Attributes" "PERMANENT" on its modifier OnManaGained | CASTER, UNIT | OnSpentMana | CASTER, UNIT | -OnStateChanged | CASTER, UNIT | +OnStateChanged | CASTER, UNIT | OnTeleporting | CASTER, UNIT | OnTeleported | CASTER, UNIT | OnUnitMoved | CASTER, UNIT | OnHealReceived | CASTER, UNIT | OnHealthGained | CASTER, UNIT | - ### Never Triggered OnAbilityStart - Broken? @@ -154,6 +153,6 @@ Please report if you find any inconsistencies.
-On the next post you'll find the random rambling analyzed to get the results. +On the next post you'll find the random rambling analyzed to get the results. Then we'll move to Multiple Targets, acting over different entities, Flags, etc. diff --git a/_articles/abilities/datadriven/channeling-animations.md b/_articles/abilities/datadriven/channeling-animations.md index a8682817..47c8dcc6 100644 --- a/_articles/abilities/datadriven/channeling-animations.md +++ b/_articles/abilities/datadriven/channeling-animations.md @@ -5,7 +5,7 @@ steamId: '76561198046984233' date: 18.01.2015 --- -### Short Version: +### Short Version: ApplyModifier with short duration in a OnThinkInterval, channeling modifier has an OverrideAnimation with a ACT_ from the [Action List](https://developer.valvesoftware.com/wiki/Dota_2_Workshop_Tools/Actions_List) or with the method explained later. @@ -26,7 +26,7 @@ ApplyModifier with short duration in a OnThinkInterval, channeling modifier has } } } - + "channelling_animation" { "IsHidden" "1" @@ -78,14 +78,10 @@ After this, you can select any animation and it will animate the white blocks at "particle" "particles/units/heroes/hero_pugna/pugna_life_drain.vpcf" "soundfile" "soundevents/game_sounds_heroes/game_sounds_pugna.vsndevts" } - - "AbilitySpecial" + + "AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "hp_drain_per_second" "25 40 55" - } + "hp_drain_per_second" "25 40 55" } "OnSpellStart" @@ -130,7 +126,7 @@ After this, you can select any animation and it will animate the white blocks at "CASTER" "attach_hitloc" "TARGET" "attach_hitloc" } - + } } @@ -141,7 +137,7 @@ After this, you can select any animation and it will animate the white blocks at "Damage" { "Type" "DAMAGE_TYPE_MAGICAL" - "Target" "TARGET" + "Target" "TARGET" "Damage" "%hp_drain_per_second" } diff --git a/_articles/abilities/datadriven/datadriven-ability-events-modifiers.md b/_articles/abilities/datadriven/datadriven-ability-events-modifiers.md index 0aaca288..38c5204e 100644 --- a/_articles/abilities/datadriven/datadriven-ability-events-modifiers.md +++ b/_articles/abilities/datadriven/datadriven-ability-events-modifiers.md @@ -40,16 +40,16 @@ There's a complete (for the most part) [list of Events in the Workshop Tools Wik In the process I'm also going to make use of different [Actions](https://developer.valvesoftware.com/wiki/Dota_2_Workshop_Tools/Scripting/Abilities_Data_Driven#Actions), inside the Events, some are self explanatory and some require some in-depth explanation on how to use them. -There are 2 types, **Ability Events** and **Modifier Events**. +There are 2 types, **Ability Events** and **Modifier Events**. Ability Events go on the "first level" of the ability. Modifier Events need to be inside a modifier block. Basic Skeleton looks like this: -``` +``` "ability_custom" { // AbilityBehavior and General values - // AbilitySpecial block + // AbilityValues block // precache block // Ability Events @@ -58,7 +58,7 @@ Basic Skeleton looks like this: "Modifiers" { - "modifier_custom" + "modifier_custom" { // Modifier Events "OnCreated" @@ -80,7 +80,7 @@ To test if your Event is actually happening when you expect, you can add the fol } ``` -`RunScript` is one of the most common and potent Actions you'll use for creating complex abilities. For it to work, you need to have a Script File, in this case *utilities.lua*, inside the vscripts folder. +`RunScript` is one of the most common and potent Actions you'll use for creating complex abilities. For it to work, you need to have a Script File, in this case *utilities.lua*, inside the vscripts folder. The Function called can have this: diff --git a/_articles/abilities/datadriven/invisibility-ability-example.md b/_articles/abilities/datadriven/invisibility-ability-example.md index 0cfadcf8..a86e8937 100644 --- a/_articles/abilities/datadriven/invisibility-ability-example.md +++ b/_articles/abilities/datadriven/invisibility-ability-example.md @@ -14,132 +14,115 @@ This is a datadriven + lua ability that will apply the invis state and texture, **KV:** ``` - "assassin_walk_the_shadows" - { +"assassin_walk_the_shadows" +{ // General //-------------------------------------------------------------------------------------------------- "BaseClass" "ability_datadriven" - "AbilityTextureName" "assassin_skill1" + "AbilityTextureName" "assassin_skill1" "MaxLevel" "7" - "AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE" - + "AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE" + // Stats //-------------------------------------------------------------------------------------------------- - "AbilityCastPoint" "0" - "AbilityCooldown" "5" - "AbilityManaCost" "6 8 11 14 18 22 26 30" - - // Damage. - //----------------------------------------------------------------------------------------------- - "AbilityDamage" "25 150 300 600 1100 2000 3300 5000" - "AbilityUnitDamageType" "DAMAGE_TYPE_PHYSICAL" - - // Special - "AbilitySpecial" - { - "01" - { - "var_type" "FIELD_INTEGER" - "duration" "25" - } - "02" - { - "var_type" "FIELD_INTEGER" - "bonus_movespeed" "35" - } - "03" - { - "var_type" "FIELD_INTEGER" - "bonus_damage" "150 300 525 840 1260 1900 3000 4500" - } - "04" - { - "var_type" "FIELD_FLOAT" - "stun_duration" "3.25" - } - } + "AbilityCastPoint" "0" + "AbilityCooldown" "5" + "AbilityManaCost" "6 8 11 14 18 22 26 30" + + // Damage. + //----------------------------------------------------------------------------------------------- + "AbilityDamage" "25 150 300 600 1100 2000 3300 5000" + "AbilityUnitDamageType" "DAMAGE_TYPE_PHYSICAL" + + // Special + "AbilityValues" + { + "duration" "25" + "bonus_movespeed" "35" + "bonus_damage" "150 300 525 840 1260 1900 3000 4500" + "stun_duration" "3.25" + } - "precache" - { - "particle" "particles/units/heroes/hero_templar_assassin/templar_assassin_meld.vpcf" - "soundfile" "soundevents/game_sounds_heroes/game_sounds_templar_assassin.vsndevts" - } + "precache" + { + "particle" "particles/units/heroes/hero_templar_assassin/templar_assassin_meld.vpcf" + "soundfile" "soundevents/game_sounds_heroes/game_sounds_templar_assassin.vsndevts" + } - //---------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------- "OnSpellStart" { - "FireSound" - { - "EffectName" "Hero_TemplarAssassin.Meld" - "Target" "CASTER" - } - "RunScript" - { - "ScriptFile" "abilities/assassin.lua" - "Function" "walk_the_shadows_cast" - } + "FireSound" + { + "EffectName" "Hero_TemplarAssassin.Meld" + "Target" "CASTER" + } + "RunScript" + { + "ScriptFile" "abilities/assassin.lua" + "Function" "walk_the_shadows_cast" + } } + "Modifiers" - { - "assassin_walk_the_shadows_buff" - { - "IsBuff" "1" - "Duration" "%duration" - "EffectName" "particles/units/heroes/hero_templar_assassin/templar_assassin_meld.vpcf" - "EffectAttachType" "follow_origin" - "OnCreated" + { + "assassin_walk_the_shadows_buff" { - "FireEffect" - { - "EffectName" "particles/units/heroes/hero_bounty_hunter/bounty_hunter_windwalk_smoke.vpcf" + "IsBuff" "1" + "Duration" "%duration" + "EffectName" "particles/units/heroes/hero_templar_assassin/templar_assassin_meld.vpcf" "EffectAttachType" "follow_origin" - "Target" "CASTER" - } - } - "Properties" - { - "MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE" "%bonus_movespeed" - } - "States" - { - "MODIFIER_STATE_INVISIBLE" "MODIFIER_STATE_VALUE_ENABLED" - "MODIFIER_STATE_NO_UNIT_COLLISION" "MODIFIER_STATE_VALUE_ENABLED" - } - "OnAttackLanded" - { - "RunScript" + "OnCreated" + { + "FireEffect" + { + "EffectName" "particles/units/heroes/hero_bounty_hunter/bounty_hunter_windwalk_smoke.vpcf" + "EffectAttachType" "follow_origin" + "Target" "CASTER" + } + } + "Properties" { - "ScriptFile" "abilities/assassin.lua" - "Function" "walk_the_shadows_attack" + "MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE" "%bonus_movespeed" } - "Stun" + "States" { - "Target" "TARGET" - "Duration" "%stun_duration" + "MODIFIER_STATE_INVISIBLE" "MODIFIER_STATE_VALUE_ENABLED" + "MODIFIER_STATE_NO_UNIT_COLLISION" "MODIFIER_STATE_VALUE_ENABLED" } - } - "OnAbilityExecuted" - { - "RunScript" + "OnAttackLanded" { - "ScriptFile" "abilities/assassin.lua" - "Function" "walk_the_shadows_interrupt" + "RunScript" + { + "ScriptFile" "abilities/assassin.lua" + "Function" "walk_the_shadows_attack" + } + "Stun" + { + "Target" "TARGET" + "Duration" "%stun_duration" + } + } + "OnAbilityExecuted" + { + "RunScript" + { + "ScriptFile" "abilities/assassin.lua" + "Function" "walk_the_shadows_interrupt" + } } - } } - } - - } + } +} ``` - **Lua Scripts:** ```lua function walk_the_shadows_cast( event ) event.ability:ApplyDataDrivenModifier(event.caster, event.caster, "assassin_walk_the_shadows_buff", nil) - event.caster:AddNewModifier(event.caster, event.ability, "modifier_invisible", {duration = 25}) - + event.caster:AddNewModifier(event.caster, event.ability, "modifier_invisible", {duration = 25}) + end function walk_the_shadows_interrupt( event ) @@ -148,9 +131,9 @@ function walk_the_shadows_interrupt( event ) end function walk_the_shadows_attack( event ) - + event.caster:RemoveModifierByName("assassin_walk_the_shadows_buff") - + ApplyDamage({ victim = event.target, attacker = event.caster, damage = event.ability:GetAbilityDamage(), damage_type = event.ability:GetAbilityDamageType(), ability = event.ability }) end diff --git a/_articles/abilities/datadriven/point-channeling-aoe-ability-example.md b/_articles/abilities/datadriven/point-channeling-aoe-ability-example.md index 91c1588e..249de0de 100644 --- a/_articles/abilities/datadriven/point-channeling-aoe-ability-example.md +++ b/_articles/abilities/datadriven/point-channeling-aoe-ability-example.md @@ -40,41 +40,22 @@ We will review each important section of the code with comments on it, including Target Team/Type and DamageType are just there to show the tooltips. -`"AbilityChannelTime"` is a must have that will determine how much time the spell can be maintained. +`"AbilityChannelTime"` is a must have that will determine how much time the spell can be maintained. -Note the `"AOERadius"` which accepts a `"%radius"` from AbilitySpecial in its value. "AOERadius" needs `"DOTA_ABILITY_BEHAVIOR_AOE"` to display the AoE Circle. +Note the `"AOERadius"` which accepts a `"%radius"` from AbilityValues in its value. "AOERadius" needs `"DOTA_ABILITY_BEHAVIOR_AOE"` to display the AoE Circle. --- -### Ability Special block: -``` -"AbilitySpecial" +### Ability Special block + +``` +"AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "duration" "25" - } - "02" - { - "var_type" "FIELD_INTEGER" - "building_damage_per_sec" "50" - } - "03" - { - "var_type" "FIELD_INTEGER" - "radius" "250" - } - "04" - { - "var_type" "FIELD_INTEGER" - "movement_speed_slow_pct" "-75" - } - "05" - { - "var_type" "FIELD_FLOAT" - "wave_interval" "1.0" - } + "duration" "25.0" + "building_damage_per_sec" "50" + "radius" "250" + "movement_speed_slow_pct" "-75" + "wave_interval" "1.0" } ``` @@ -82,10 +63,10 @@ Nothing interesting except remarking that `"%duration"` **cannot** be used as a --- -### Precache block: -``` +### Precache block -"precache" +``` +"precache" { "particle" "particles/units/heroes/hero_leshrac/leshrac_split_earth.vpcf" "particle" "particles/units/heroes/hero_warlock/warlock_rain_of_chaos_explosion.vpcf" @@ -97,7 +78,7 @@ Nothing interesting except remarking that `"%duration"` **cannot** be used as a } ``` -Has all the particles used and leshrac soundfile loaded. +Has all the particles used and leshrac soundfile loaded. Paths were copied directly from the asset browser, unmodified particles. I'll explain each of its attachments when we get to them. @@ -119,7 +100,7 @@ When the cast point is complete, perform the following actions: //... ``` -This calls a very simple Lua script which creates a dummy unit to apply a thinker modifier which does the "waves". +This calls a very simple Lua script which creates a dummy unit to apply a thinker modifier which does the "waves". When using an `"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT"`, you can pass the POINT targeted as an extra parameter to the function (it won't be passed automatically, like CASTER or TARGET). This can be accessed as the **target_points[1]** on the event. @@ -145,7 +126,7 @@ Back to the dummy unit, this is its definition: { "BaseClass" "npc_dota_creature" "AttackCapabilities" "DOTA_UNIT_CAP_NO_ATTACK" - "VisionDaytimeRange" "0" + "VisionDaytimeRange" "0" "VisionNighttimeRange" "0" "UnitRelationshipClass" "DOTA_NPC_UNIT_RELATIONSHIP_TYPE_WARD" "MovementCapabilities" "DOTA_UNIT_CAP_MOVE_NONE" @@ -174,7 +155,7 @@ And the passive ability: "MODIFIER_STATE_MAGIC_IMMUNE" "MODIFIER_STATE_VALUE_ENABLED" "MODIFIER_STATE_NOT_ON_MINIMAP" "MODIFIER_STATE_VALUE_ENABLED" "MODIFIER_STATE_UNSELECTABLE" "MODIFIER_STATE_VALUE_ENABLED" - "MODIFIER_STATE_NO_HEALTH_BAR" "MODIFIER_STATE_VALUE_ENABLED" + "MODIFIER_STATE_NO_HEALTH_BAR" "MODIFIER_STATE_VALUE_ENABLED" } } } @@ -199,7 +180,7 @@ Back to the OnSpellStart, 2 more actions: "DelayedAction" { "Delay" "0.5" - "Action" + "Action" { "ApplyModifier" { @@ -207,7 +188,7 @@ Back to the OnSpellStart, 2 more actions: "Target" "CASTER" } } - } + } } ``` @@ -227,13 +208,13 @@ When the ability finishes channeling either because the channel time has finishe { "ScriptFile" "heroes/far_seer/earthquake.lua" "Function" "EarthquakeEnd" - } + } "RemoveModifier" { "ModifierName" "modifier_earthquake_channelling" "Target" "CASTER" - } + } } ``` @@ -268,7 +249,7 @@ Now lets move to the the Modifiers block, the first couple handles the animation "ModifierName" "modifier_channeling" "Target" "CASTER" "Duration" "0.9" - } + } } } @@ -290,7 +271,7 @@ Now lets move to the the Modifiers block, the first couple handles the animation "Aura" "modifier_eartquake_slow" "Aura_Radius" "%radius" "Aura_Teams" "DOTA_UNIT_TARGET_TEAM_ENEMY" - "Aura_Types" "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_BASIC" + "Aura_Types" "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_BASIC" //... ``` @@ -303,8 +284,8 @@ This constantly applies another modifier effect to all units around a radius of "IsDebuff" "1" "Properties" { - "MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE" "%movement_speed_slow_pct" - } + "MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE" "%movement_speed_slow_pct" + } } ``` @@ -353,7 +334,7 @@ Back to the "modifier_earthquake_thinker", we have to have actions on 2 instance I used one extra particle that needs to have the Control Point 1 attached to the target, else it will show on the middle of the map. ``` - "AttachEffect" + "AttachEffect" { "Target" "TARGET" "EffectAttachType" "follow_origin" @@ -370,7 +351,7 @@ I used one extra particle that needs to have the Control Point 1 attached to the To realize that the CP1 needs to be set else the particle will fail to display properly, this is the procedure: -1. Open the particle system on the Particle Editor, double clicking on it (needs **decompiled particles**!) +1. Open the particle system on the Particle Editor, double clicking on it (needs **decompiled particles**!) ![img](https://puu.sh/f61DF/2ed8e1c122.jpg) @@ -406,7 +387,7 @@ Still following this? Great, it's almost finished, only missing the `"OnInterval "Radius" "%radius" "Teams" "DOTA_UNIT_TARGET_TEAM_BOTH" "Types" "DOTA_UNIT_TARGET_BUILDING" - } + } "Type" "DAMAGE_TYPE_MAGICAL" "Damage" "%building_damage_per_sec" } @@ -429,7 +410,7 @@ Still following this? Great, it's almost finished, only missing the `"OnInterval "EffectName" "particles/units/heroes/hero_earthshaker/temp_eruption_dirt.vpcf" "EffectAttachType" "follow_origin" "Target" "TARGET" - } + } //... ``` @@ -447,7 +428,7 @@ To find what each control point does, follow the same method as with the espirit { "01" "%radius 50 50" } - } + } "AttachEffect" { @@ -468,7 +449,7 @@ To find what each control point does, follow the same method as with the espirit "ControlPoints" { "01" "1 0 0" - } + } } } ``` diff --git a/_articles/abilities/item-keyvalues.md b/_articles/abilities/item-keyvalues.md index dff68569..ed2cbbba 100644 --- a/_articles/abilities/item-keyvalues.md +++ b/_articles/abilities/item-keyvalues.md @@ -172,7 +172,7 @@ Apart from this values specially related to items, you can add ***everything*** "AbilityUnitTargetType" "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_BASIC" "AbilityCastAnimation" "ACT_DOTA_CAST_ABILITY_1" "AbilityManaCost" "100" -"AbilitySpecial" +"AbilityValues" { ... } ``` diff --git a/_articles/abilities/lua-item-tutorial.md b/_articles/abilities/lua-item-tutorial.md index bc4f0c39..0dab1048 100644 --- a/_articles/abilities/lua-item-tutorial.md +++ b/_articles/abilities/lua-item-tutorial.md @@ -397,29 +397,12 @@ end ``` Now to save time and sanity you might want to add 'Special' values to your script. These are values you can modify easily without opening the script and searching for them there. This is extremely helpful when you use those values in multiple places. It also lets you display the values in your item description.
First add following block to your item in 'npc_items_custom.txt' ``` - - "AbilitySpecial" + "AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "max_blink" "1200" - } - "02" - { - "var_type" "FIELD_INTEGER" - "blink_clamp" "960" - } - "03" - { - "var_type" "FIELD_INTEGER" - "help_range" "3000" - } - "04" - { - "var_type" "FIELD_FLOAT" - "help_duration" "5.0" - } + "max_blink" "1200" + "blink_clamp" "960" + "help_range" "3000" + "help_duration" "5.0" } ``` Now to use these values you use this function in your ability: @@ -699,54 +682,22 @@ Also you must give each item in npc_items_custom.txt unique ID. If you don't you "ItemShopTags" "blink;staff" "ItemQuality" "rare" "ItemAliases" "blink;staff" - // - "AbilitySpecial" + // + "AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "max_blink" "1200" - } - "02" - { - "var_type" "FIELD_INTEGER" - "blink_clamp" "960" - } - "03" - { - "var_type" "FIELD_INTEGER" - "help_range" "3000" - } - "04" - { - "var_type" "FIELD_FLOAT" - "help_duration" "5.0" - } - "05" - { - "var_type" "FIELD_FLOAT" - "hurt_cooldown" "3.0" - } - - // Stats from the recipe items - - "06" // Quarterstaff - { - "var_type" "FIELD_INTEGER" - "bonus_damage" "10" - } - - "07" // Quarterstaff - { - "var_type" "FIELD_INTEGER" - "bonus_attack_speed" "10" - } - - "08" // Robe Of Magi - { - "var_type" "FIELD_INTEGER" - "bonus_int" "6" - } + // Blink + "max_blink" "1200" + "blink_clamp" "960" + "help_range" "3000" + "help_duration" "5.0" + "hurt_cooldown" "3.0" + + // Quearterstaff + "bonus_damage" "10" + "bonus_attack_speed" "10" + + // Robe Of Magi + "bonus_int" "6" } } diff --git a/_articles/abilities/passing-abilityspecial-values-into-lua.md b/_articles/abilities/passing-abilityvalues-values-into-lua.md similarity index 66% rename from _articles/abilities/passing-abilityspecial-values-into-lua.md rename to _articles/abilities/passing-abilityvalues-values-into-lua.md index 3fa05464..64e82070 100644 --- a/_articles/abilities/passing-abilityspecial-values-into-lua.md +++ b/_articles/abilities/passing-abilityvalues-values-into-lua.md @@ -1,25 +1,17 @@ --- -title: Passing AbilitySpecial values into Lua +title: Passing AbilityValues values into Lua author: Noya steamId: '76561198046984233' date: 12.12.2014 --- -Given this "AbilitySpecial" block in the ability: +Given this "AbilityValues" block in the ability: ``` -"AbilitySpecial" +"AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "radius" "300" - } - "02" - { - "var_type" "FIELD_INTEGER" - "mana_per_second" "5 10 15 20" - } + "radius" "300" + "mana_per_second" "5 10 15 20" } ``` @@ -27,7 +19,7 @@ There are 2 functions to connect these with: `GetSpecialValueFor` and `GetLevelS ```lua local ability = event.ability -local radius = ability:GetSpecialValueFor("radius") +local radius = ability:GetSpecialValueFor("radius") local mana_per_second = ability:GetLevelSpecialValueFor("mana_per_second", (ability:GetLevel() - 1)) ``` @@ -35,8 +27,6 @@ The first one will get the value for the **current level** of the ability. The second one will get the value for the **specified level** of the ability -The first one is the most common and should be **used every time**, unless you need the value for a specific level. +The first one is the most common and should be **used every time**, unless you need the value for a specific level. Note the use of `(ability:GetLevel() - 1)` as the second parameter (which tells the script which level to take). This is needed because ability levels are 1-indexed but `GetLevelSpecialValueFor` is 0-indexed. - - diff --git a/_articles/abilities/reutilizing-built-in-modifiers.md b/_articles/abilities/reutilizing-built-in-modifiers.md index 10ab1009..50cdd116 100644 --- a/_articles/abilities/reutilizing-built-in-modifiers.md +++ b/_articles/abilities/reutilizing-built-in-modifiers.md @@ -7,13 +7,13 @@ date: 18.01.2015 Here it will be explained how to reuse any Built-In modifier through the datadriven system. -This has many uses, as sometimes it's impossible to replicate some effects that are very hidden/hardcoded within the engine. +This has many uses, as sometimes it's impossible to replicate some effects that are very hidden/hardcoded within the engine. In a previous example, the [Illusion Ability Example](http://moddota.com/forums/discussion/62/illusion-ability-example) made use of the `"modifier_illusion modifier"` in Lua like this: ```lua -illusion:AddNewModifier(caster, ability, "modifier_illusion", { duration = duration, - outgoing_damage = outgoingDamage, +illusion:AddNewModifier(caster, ability, "modifier_illusion", { duration = duration, + outgoing_damage = outgoingDamage, incoming_damage = incomingDamage }) ``` @@ -25,7 +25,7 @@ The Full List of Built-In Modifiers can be found [on the the wiki](https://devel **Basic Example:** This will apply 1 frame of MODIFIER_STATE_NO_UNIT_COLLISION ``` -"ApplyModifier" +"ApplyModifier" { "ModifierName" "modifier_phased" "Target" "TARGET" @@ -37,7 +37,7 @@ However this isn't more than a shortcut to avoid creating a new modifier with th
-For example, in the `alchemist_chemical_rage` ability, Alchemist changes its attack/idle/run animation, model effect, attack sound and also gets the ability bonus. +For example, in the `alchemist_chemical_rage` ability, Alchemist changes its attack/idle/run animation, model effect, attack sound and also gets the ability bonus. If we wanted to get all the cosmetic properties but with different ability effects, we need to rewrite the skill from scratch, but sadly the autoattack sound and animations for attack/idle/run aren't easily changed, and we would need to find a wacky workaround for it. @@ -53,34 +53,19 @@ Go to the original ability that uses the modifier you want to reuse form the lis
-#### Step 2 - Setting the AbilitySpecial fields +#### Step 2 - Setting the AbilityValues fields -Copy the ability specials from the main ability into your datadriven AbilitySpecial block. If the custom ability doesn't have the field, the modifier will default to 0, so you can remove those that you want to ignore. +Copy the ability specials from the main ability into your datadriven AbilityValues block. If the custom ability doesn't have the field, the modifier will default to 0, so you can remove those that you want to ignore. + +**Example:** [alchemist_chemical_rage](https://github.com/Pizzalol/SpellLibrary/blob/SpellLibrary/game/dota_addons/spelllibrary/scripts/npc/abilities/alchemist_chemical_rage_datadriven.txt#L30) AbilityValues block, with 2 added values and most of its ability bonus removed. -**Example:** [alchemist_chemical_rage](https://github.com/Pizzalol/SpellLibrary/blob/SpellLibrary/game/dota_addons/spelllibrary/scripts/npc/abilities/alchemist_chemical_rage_datadriven.txt#L30) AbilitySpecial block, with 2 added values and most of its ability bonus removed. ``` -"AbilitySpecial" +"AbilityValues" { - "01" - { - "var_type" "FIELD_FLOAT" - "duration" "25.0" - } - "02" - { - "var_type" "FIELD_FLOAT" - "transformation_time" "0.35" - } - "03" - { - "var_type" "FIELD_INTEGER" - "bonus_movespeed_percent" "50" - } - "04" - { - "var_type" "FIELD_INTEGER" - "bonus_attack_speed" "322" - } + "duration" "25.0" + "transformation_time" "0.35" + "bonus_movespeed_percent" "50" + "bonus_attack_speed" "322" } ```
@@ -89,7 +74,7 @@ Copy the ability specials from the main ability into your datadriven AbilitySpec On the desired Ability or Modifier Event, add the ApplyModifier action: ``` -"ApplyModifier" +"ApplyModifier" { "ModifierName" "modifier_alchemist_chemical_rage_transform" "Target" "CASTER" @@ -105,7 +90,7 @@ On the desired Ability or Modifier Event, add the ApplyModifier action: ![img](https://puu.sh/eHc3N/2b62c46b84.jpg) -The modifier_alchemist_chemical_rage tooltip needs to be adjusted to ignore AbilitySpecials we don't need, and instead use our bonus_attack_speed and bonus_movespeed_percent . +The modifier_alchemist_chemical_rage tooltip needs to be adjusted to ignore AbilityValues we don't need, and instead use our `bonus_attack_speed` and `bonus_movespeed_percent`. 1. Go to dota_english.txt, which can be found in the main dota file or in [this repository link](https://raw.githubusercontent.com/dotabuff/d2vpk/master/dota/resource/dota_english.txt) @@ -120,7 +105,7 @@ After modifying the addon_english.txt: ![img](https://puu.sh/eHpXB/8fe79a1d57.jpg) -Note that you cannot refer to a new custom %dMODIFIER_PROPERTY_[CONSTANT_LIST](http://moddota.com/forums/discussion/14/datadriven-ability-breakdown-documentation##properties)% in the tooltip, because it doesn't have the custom values in its modifier. +Note that you cannot refer to a new custom %dMODIFIER_PROPERTY_[CONSTANT_LIST](http://moddota.com/forums/discussion/14/datadriven-ability-breakdown-documentation##properties)% in the tooltip, because it doesn't have the custom values in its modifier. Instead you can make those tooltips in the separate modifier, or directly add the numbers to the original modifier tooltip if they are static values (like in this cause I could've written 50 and 322). Sadly, you can't set the built-in modifier as hidden either. @@ -143,28 +128,12 @@ Instead you can make those tooltips in the separate modifier, or directly add th "AbilityManaCost" "25" - "AbilitySpecial" + "AbilityValues" { - "01" - { - "var_type" "FIELD_FLOAT" - "duration" "15.0" - } - "02" - { - "var_type" "FIELD_FLOAT" - "transformation_time" "0.35" - } - "03" - { - "var_type" "FIELD_FLOAT" - "bonus_movespeed_percent" "50" - } - "04" - { - "var_type" "FIELD_FLOAT" - "bonus_attack_speed" "25 75 125" - } + "duration" "15.0" + "transformation_time" "0.35" + "bonus_movespeed_percent" "50" + "bonus_attack_speed" "25 75 125" } "precache" @@ -189,7 +158,7 @@ Instead you can make those tooltips in the separate modifier, or directly add th "Duration" "%transformation_time" } - // Extra Modifier with what we need to add for the custom ability + // Extra Modifier with what we need to add for the custom ability "ApplyModifier" { "ModifierName" "modifier_chemical_rage_warcraft" @@ -199,7 +168,7 @@ Instead you can make those tooltips in the separate modifier, or directly add th "Modifiers" { - + "modifier_chemical_rage_warcraft" { "IsBuff" "1" diff --git a/_articles/abilities/the-importance-of-abilityspecial-values.md b/_articles/abilities/the-importance-of-abilityspecial-values.md deleted file mode 100644 index 927ff1d6..00000000 --- a/_articles/abilities/the-importance-of-abilityspecial-values.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: The importance of AbilitySpecial values -author: Noya -steamId: '76561198046984233' -date: 12.12.2014 ---- - -*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.* - -When coding abilities or items, **do not** fall into the trap of replacing the use of AbilitySpecial variables with a constant (i.e. writing `"Duration" "12"`, `"MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE" "-30"` or doing similar assignations in lua scripts), thinking it will only be used once. - -There's **2 problems** with doing this - -* Tooltips are hard - - If you don't use AbilitySpecial for each variable, when you get to making the tooltips, you'll find pretty much impossible to make quality dota-styled strings because your spell description needs to have direct copies of the values you've put in the ability. To make this worse, if you ever make a change to an static number in your datadriven ability, you will also need to update the addon_english.txt - -* Consistency between Lua & Key Values - - Changing a key value won't only affect the datadriven but also the scripts and its easy to make a change and forget to extend this change to the .lua file. Doing proper references to the Specials also eliminates this problem. - -
-**TL;DR**: Use as many AbilitySpecial values as possible, then modifying/balancing your abilities can be done just by changing these variables and it will extend to the rest of the game mode. - ---- - -**Related**: [How to get AbilitySpecial values into Lua](http://moddota.com/forums/discussion/17/how-to-get-abilityspecial-values-into-lua) diff --git a/_articles/abilities/the-importance-of-abilityvalues-values.md b/_articles/abilities/the-importance-of-abilityvalues-values.md new file mode 100644 index 00000000..048bd569 --- /dev/null +++ b/_articles/abilities/the-importance-of-abilityvalues-values.md @@ -0,0 +1,24 @@ +--- +title: The importance of AbilityValues values +author: Noya +steamId: '76561198046984233' +date: 12.12.2014 +--- + +*To specify numeric values, you can put in a number or you can use `%name` formatting to grab values out of the "AbilityValues" 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.* + +When coding abilities or items, **do not** fall into the trap of replacing the use of AbilityValues variables with a constant (i.e. writing `"Duration" "12"`, `"MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE" "-30"` or doing similar assignations in lua scripts), thinking it will only be used once. + +There's **2 problems** with doing this + +* Tooltips are hard + + If you don't use AbilityValues for each variable, when you get to making the tooltips, you'll find pretty much impossible to make quality dota-styled strings because your spell description needs to have direct copies of the values you've put in the ability. To make this worse, if you ever make a change to an static number in your datadriven ability, you will also need to update the addon_english.txt + +* Consistency between Lua & Key Values + + Changing a key value won't only affect the datadriven but also the scripts and its easy to make a change and forget to extend this change to the .lua file. Doing proper references to the Specials also eliminates this problem. + +
+ +**TL;DR**: Use as many AbilityValues values as possible, then modifying/balancing your abilities can be done just by changing these variables and it will extend to the rest of the game mode. diff --git a/_articles/scripting/Typescript/typescript-ability.md b/_articles/scripting/Typescript/typescript-ability.md index 3cd3f630..16735ed9 100644 --- a/_articles/scripting/Typescript/typescript-ability.md +++ b/_articles/scripting/Typescript/typescript-ability.md @@ -50,38 +50,17 @@ In the npc_abilities_custom.txt, which is located in `scripts/npc` folder, we'll // Special //------------------------------------------------------------------------------------------------------------- - "AbilitySpecial" + "AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "bolt_speed" "500" - } - - "02" - { - "var_type" "FIELD_INTEGER" - "bolt_vision" "325" - } - - "03" - { - "var_type" "FIELD_FLOAT" - "bolt_damage" "60 80 100 120" - } - - "04" - { - "var_type" "FIELD_FLOAT" - "int_multiplier" "1.6" - "CalculateSpellDamageTooltip" "1" - } - - "05" - { - "var_type" "FIELD_FLOAT" - "vision_duration" "3.34" - } + "bolt_speed" "500" + "bolt_vision" "325" + "bolt_damage" "60 80 100 120" + "int_multiplier" + { + "value" "1.6" + "CalculateSpellDamageTooltip" "1" + } + "vision_duration" "3.34" } "AbilityCastAnimation" "ACT_DOTA_CAST_ABILITY_1" } diff --git a/_articles/scripting/Typescript/typescript-modifier.md b/_articles/scripting/Typescript/typescript-modifier.md index b0fee3b8..7eceb470 100644 --- a/_articles/scripting/Typescript/typescript-modifier.md +++ b/_articles/scripting/Typescript/typescript-modifier.md @@ -51,19 +51,10 @@ We'll begin with the KV, which is straightforward. Open `/game/scripts/npc/npc_a // Special //------------------------------------------------------------------------------------------------------------- - "AbilitySpecial" + "AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "resist_debuff" "30 35 40 45" - } - - "02" - { - "var_type" "FIELD_FLOAT" - "seal_duration" "3.0 4.0 5.0 6.0" - } + "resist_debuff" "30 35 40 45" + "seal_duration" "3.0 4.0 5.0 6.0" } "AbilityCastAnimation" "ACT_DOTA_CAST_ABILITY_3" } diff --git a/_articles/scripting/custom-mana-system.md b/_articles/scripting/custom-mana-system.md index 07c4538f..2215810b 100644 --- a/_articles/scripting/custom-mana-system.md +++ b/_articles/scripting/custom-mana-system.md @@ -5,11 +5,11 @@ steamId: '76561198046984233' date: 01.12.2014 --- -This is a guide to make a simple custom mana system. A working barebones addon is assumed. +This is a guide to make a simple custom mana system. A working barebones addon is assumed. In this example we'll make a classic *Rage* system, meaning: 1. No normal mana regeneration, starting mana 0 -2. Gain mana after an attack, scaling with level +2. Gain mana after an attack, scaling with level 3. Gain mana after being attacked, scaling with level 4. Gain mana on particular spell cast 5. Decrease mana over time, scaling with level @@ -26,12 +26,12 @@ Hope this is enough for most systems, let me know if you have another concept th //KV code inside npc_heroes_custom.txt "AttributeBaseIntelligence" "0" // Base intelligence "AttributeIntelligenceGain" "0" // Intelligence bonus per level. - + "StatusMana" "50" // Initial Max Mana -"StatsManaRegen" "0" // Base Mana Regen (KV doesn't like negative numbers here) +"StatsManaRegen" "0" // Base Mana Regen (KV doesn't like negative numbers here) ``` -If you need to keep your Int stat but still have 0 natural mana regen, you'll need to apply modifiers for each Int point with negative mana regen to compensate. +If you need to keep your Int stat but still have 0 natural mana regen, you'll need to apply modifiers for each Int point with negative mana regen to compensate. I won't be following this process in this guide, but you can check the guide [on the wiki](https://developer.valvesoftware.com/wiki/Dota_2_Workshop_Tools/Scripting/Using_Bitfields_To_Adjust_Stat_Value_Bonuses) @@ -40,7 +40,7 @@ For your mana to start at 0, we'll begin by making the passive hidden ability wh ``` //KV code inside npc_abilities_custom.txt -"barbarian_rage" +"barbarian_rage" { "BaseClass" "ability_datadriven" "AbilityTextureName" "barbarian_rage" @@ -48,7 +48,7 @@ For your mana to start at 0, we'll begin by making the passive hidden ability wh "AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_HIDDEN" "Modifiers" - { + { "rage_modifier" { "Passive" "1" //Auto apply this modifier when the spell is learned @@ -74,7 +74,7 @@ The script is very simple: ```lua -- lua code inside barbarian.lua - function ZeroManaOnSpawn( event ) + function ZeroManaOnSpawn( event ) local hero = event.caster Timers:CreateTimer(.01, function() -- Set Mana to 0 on created @@ -104,7 +104,7 @@ end The if is not exactly neccessary but you'll need to filter your desired hero somehow. We'll use Beastmaster for our example -## Gain mana after an attack, scaling with level +## Gain mana after an attack, scaling with level Our rage_modifier block gains another modifier event: @@ -116,7 +116,7 @@ Our rage_modifier block gains another modifier event: "ScriptFile" "barbarian.lua" "Function" "ManaOnAttack" } -} +} ``` I'll use a basic formula for it, which gives a base mana per attack but also scales with levels slightly. @@ -162,10 +162,10 @@ end ## Gain mana on particular spell cast ``` -"OnSpellStart" +"OnSpellStart" { "RunScript" - { + { "ScriptFile" "barbarian.lua" "Function" "leap" } @@ -179,16 +179,12 @@ local manaGain = event.ability:GetSpecialValueFor("mana_gain") event.caster:GiveMana(manaGain) ``` -This will take your "mana_gain" from AbilitySpecial, in my leap example it would be: +This will take your "mana_gain" from AbilityValues, in my leap example it would be: ``` -"AbilitySpecial" +"AbilityValues" { - "01" - { - "var_type" "FIELD_INTEGER" - "mana_gain" "8 16 25 35 47 60 72 85" - } + "mana_gain" "8 16 25 35 47 60 72 85" } ``` @@ -201,8 +197,8 @@ Base Mana Regen will need to be updated when the hero spawns `OnHeroInGame`, and For this we create a local function somewhere inside our main addon lua file and call it whenever we need (at least once `OnHeroInGame`): ```lua -function AdjustWarriorClassMana( hero ) - Timers:CreateTimer(0.1,function() +function AdjustWarriorClassMana( hero ) + Timers:CreateTimer(0.1,function() local heroLevel = hero:GetLevel() -- Adjust the new mana regen hero:SetBaseManaRegen( -(0.01 * heroLevel) - 0.25) @@ -227,4 +223,3 @@ Check the original complete file scripts in TBR Github * [heroes_custom file](https://github.com/Aleteh/TBR3/blob/master/scripts/npc/npc_heroes_custom.txt) * [abilities file](https://github.com/Aleteh/TBR3/blob/master/scripts/npc/npc_abilities_custom.txt) - diff --git a/_articles/units/creating-units-with-a-duration.md b/_articles/units/creating-units-with-a-duration.md index 5d2d0e31..3c78cc2d 100644 --- a/_articles/units/creating-units-with-a-duration.md +++ b/_articles/units/creating-units-with-a-duration.md @@ -24,22 +24,18 @@ Here is an example of it in KV; one spider spawns without the `modifier_kill` an ``` "test_ability" { - // General + // General "BaseClass" "ability_datadriven" "AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE" "AbilityType" "DOTA_ABILITY_TYPE_BASIC" - // Time + // Time "AbilityCooldown" "0.0" - // Cost + // Cost "AbilityManaCost" "0" - // Special - "AbilitySpecial" + // Special + "AbilityValues" { - "01" - { - "var_type" "FIELD_FLOAT" - "duration" "10.0" - } + "duration" "10.0" } "OnSpellStart" { diff --git a/sidebars.json b/sidebars.json index 3556caa4..89203c95 100644 --- a/sidebars.json +++ b/sidebars.json @@ -20,8 +20,8 @@ "items": [ "abilities/ability-keyvalues", "abilities/item-keyvalues", - "abilities/the-importance-of-abilityspecial-values", - "abilities/passing-abilityspecial-values-into-lua", + "abilities/the-importance-of-abilityvalues-values", + "abilities/passing-abilityvalues-values-into-lua", "abilities/abilityduration-tooltips", "abilities/simple-custom-ability", "abilities/creating-innate-abilities",