Custom talents update tooltip but don't affect the spell

edited November 1 in Questions

I have a spell that adds cast range and attack range and two talents that increase one of the boni. When I skill the talent, it updates the number in the tooltip, but the bonus in-game stays on the same value. How can I fix that?

"air_watch_datadriven"
    {
        "BaseClass"                     "ability_datadriven"
        "AbilityBehavior"               "DOTA_ABILITY_BEHAVIOR_NO_TARGET"
        "FightRecapLevel"               "1"
        "AbilityTextureName"            "air_watch"
        "MaxLevel"                      "4"

        "AbilityCastPoint"              "0.0"

        "AbilityManaCost"               "80"
        "AbilityCooldown"               "22"

        "AbilitySpecial"
        {
            "01"
            {
                "var_type"          "FIELD_INTEGER"
                "attack_range_bonus"    "50 100 150 200"
                "LinkedSpecialBonus"    "airwatcher_bonus2"
            }
            "02"
            {
                "var_type"          "FIELD_INTEGER"
                "cast_range_bonus"      "50 100 150 200"
                "LinkedSpecialBonus"    "airwatcher_bonus3"
            }
            "03"
            {
                "var_type"          "FIELD_INTEGER"
                "duration"          "4 6 8 10"
            }
            "04"
            {
                "var_type"          "FIELD_INTEGER"
                "stun_duration"         "2"
            }
            "05"
            {
                "var_type"          "FIELD_INTEGER"
                "vision_range"      "850 1000 1150 1300"
            }
        }

        "OnSpellStart"
        {
            "ApplyModifier"
            {
                "ModifierName"  "modifier_air_watch"
                "Target"        "CASTER"
                "Duration"      "%duration"
            }
            "ApplyModifier"
            {
                "ModifierName"  "modifier_item_aether_lens"
                "Target"        "CASTER"
                "Duration"      "%duration"
            }


            "FireEffect"
            {
                "EffectName"        "particles/units/heroes/hero_winter_wyvern/wyvern_arctic_burn_buff_ground_dust.vpcf"
                "EffectAttachType"  "follow_origin"
                "Target"            "TARGET"
            }
        }

        "Modifiers"
        {
            "modifier_air_watch"
            {
                "Passive"           "0"
                "IsHidden"          "0"
                "IsDebuff"          "0"

                "EffectName"        "particles/units/heroes/hero_winter_wyvern/wyvern_arctic_burn_buff.vpcf"
                "EffectAttachType"  "follow_origin"

                "ThinkInterval"  "0.033333333"
                "OnIntervalThink"
                {
                    "RunScript"
                    {
                        "ScriptFile"    "air_watch.lua"
                        "Function"      "AirWatch"
                        "ModifierName"  "modifier_air_watch"
                    }                   
                }
                "OnDestroy"
                {
                    "DestroyTrees"
                    {
                        "Target"        "CASTER"
                        "Radius"        "250"
                    }
                }

                "Properties"
                {
                    "MODIFIER_PROPERTY_ATTACK_RANGE_BONUS" "%attack_range_bonus"
                }

                "States"
                {
                    "MODIFIER_STATE_FLYING"     "MODIFIER_STATE_VALUE_ENABLED"
                }
            }
        }

    } 
"airwatcher_bonus2"
    {
        "BaseClass"                     "special_bonus_undefined"
        "AbilityType"                   "DOTA_ABILITY_TYPE_ATTRIBUTES"
        "AbilityBehavior"               "DOTA_ABILITY_BEHAVIOR_PASSIVE"
        "AbilitySpecial"
        {
            "01"
            {
                "var_type"          "FIELD_INTEGER"
                "value"             "150"
            }
        }

    }

    "airwatcher_bonus3"
    {
        "BaseClass"                     "special_bonus_undefined"
        "AbilityType"                   "DOTA_ABILITY_TYPE_ATTRIBUTES"
        "AbilityBehavior"               "DOTA_ABILITY_BEHAVIOR_PASSIVE"
        "AbilitySpecial"
        {
            "01"
            {
                "var_type"          "FIELD_INTEGER"
                "value"             "300"
            }
        }

    }

Comments

  • I do not know if it's the best way, but the way I found it to do this is by passing the parameters inside the .lua file of the skill (I do not know how to do this in datadriven) as in the code below

    function dk_pull_skill(event)
        local target = event.target
        local caster = event.caster
        local ability = event.ability
        local talent = caster:FindAbilityByName("special_bonus_unique_dk_1")
        local max_damage = ability:GetLevelSpecialValueFor( "damage_max", ability:GetLevel() - 1 )
    
        if talent:GetLevel() > 0 then
            damage = max_damage + talent:GetSpecialValueFor("value")
        else
            damage = max_damage
        end
    
        local min_damage = ability:GetLevelSpecialValueFor( "damage_min", ability:GetLevel() - 1 )
        local totaldamage = (damage / 700)*target:GetRangeToUnit(caster)
        if target:GetRangeToUnit(caster) > 700 then
            local finaldamage = {
                            victim = target,
                            attacker = caster,
                            damage = damage,
                            damage_type = DAMAGE_TYPE_MAGICAL,
                            ability = ability
                        }
            ApplyDamage(finaldamage)
        elseif target:GetRangeToUnit(caster) <= 700 and totaldamage > min_damage then
            local finaldamage = {
                            victim = target,
                            attacker = caster,
                            damage = totaldamage,
                            damage_type = DAMAGE_TYPE_MAGICAL,
                            ability = ability
                        }
            ApplyDamage(finaldamage)
        elseif totaldamage <= min_damage then
            local finaldamagemin = {
                            victim = target,
                            attacker = caster,
                            damage = min_damage,
                            damage_type = DAMAGE_TYPE_MAGICAL,
                            ability = ability
                        }
            ApplyDamage(finaldamagemin)
        end
    end
    

    At the beginning of the code, I declare the talent and then check if it has a level greater than 1, if it is, the damage (or anything else you want) is applied with the previous damage plus the bonus damage of the talent, in this part specifically

    local talent = caster:FindAbilityByName("special_bonus_unique_dk_1")
        local max_damage = ability:GetLevelSpecialValueFor( "damage_max", ability:GetLevel() - 1 )
    
        if talent:GetLevel() > 0 then
            damage = max_damage + talent:GetSpecialValueFor("value")
        else
            damage = max_damage
        end
    

    For datadriven, the way I found it was to create a new skill with a thinker checking if the talent is level up, and when it is, it changes the skill with the values I want, as I did with a hidden modifier

    "Modifiers"
        {
            "modifier_desintegrate_talent"
            {
                "Passive"           "1"
                "IsHidden"          "1"
                "IsDebuff"          "0"
                "IsPurgable"        "0"
                "ThinkInterval"     "0.1"
                "OnIntervalThink"
                {
                    "RunScript"
                    {
                        "ScriptFile"    "lua_abilities/legion_desintegrate_talent.lua"
                        "Function"      "CheckTalent"
                    }
                }
            }
        }
    
    function CheckTalent(keys)
        local caster = keys.caster
        local ability = keys.ability
        local ability2 = caster:FindAbilityByName("legion_desintegrate_talent")
        local talent = caster:FindAbilityByName("special_bonus_unique_legion_1")
        if talent:GetLevel() > 0 then
            if ability:IsHidden() == false then
                caster:SwapAbilities("legion_desintegrate", "legion_desintegrate_talent", false, true)
                local cooldown = ability:GetCooldownTimeRemaining()
                ability2:StartCooldown(cooldown)
                local level = ability:GetLevel()
                ability2:SetLevel(level)
                caster:RemoveModifierByName("modifier_desintegrate_talent")
            else
                local level = ability:GetLevel()
                ability2:SetLevel(level)
                caster:RemoveModifierByName("modifier_desintegrate_talent")
            end
        end
    end
    

    I'm sure there is a simpler way to do this with datadriven, but as I do not know, I think the best way to do this is pass the skill on a .lua file as the first example. Hope I had helped you!

  • Posts: 151

    there is no way to do it in datadriven for most cases. doing it in a lua script is correct.

  • edited November 6 Posts: 7

    Thank you. So I have remade the ability to apply the modifiers through lua and take the talents into account. Yet I can't seem to pass the updated values to the modifiers, how should I do that?

  • Posts: 7

    @Caelumest Your replacement solution solution doesn't seem to be working for me. Is there perhaps a part of it you failed to mention? I copied it exactly, only changing the strings, so I am not making the mistake. Can you help?

  • edited November 11 Posts: 151
    local normal_value = ability:GetSpecialValueFor("bonus_something")
    local talent = caster:FindModifierByName("talent_name")
    if talent and talent:GetLevel() > 0 then
        normal_value = normal_value + talent:GetSpecialValueFor("value") -- needs to be "value"
    end
    
  • Posts: 7

    @DankBud I understood that and did it that way - but I don't know how to pass the updated value to the ApplyDataDrivenModifier modifier-table. It works for my other abilities, as they deal more damage or other things, but my main problem here is the application of the modifier. Can't do it directly and can't get the SwapAbility solution to work either. And because I am forced to use the Aether Lens modifier, because PROPERTY_CAST_RANGE_BONUS and PROPERTY_CAST_RANGE_BONUS_STACKING don't work, I can't rewrite it as a lua modifier.

  • edited November 11 Posts: 7

    With modifiers things complicate a bit, note that in this code the talent is serving only to change the tooltip, and to change the actual value of the talent I use an int of 5 adding inside the modifier_dragon_blood_talent. This one...

    function modifier_dragon_blood_talent:GetModifierSpellAmplify_Percentage()
        local total = (5 + spell_amp) * self:GetStackCount()
        return total
    end
    

    I tried to use the same method of checking if the talent has a level greater than 0 inside the modifier with millions of different methods, but for some reason it never worked, so I had to make this "mess". The codes and links below are all of the same skill with the modifier being passed in .lua (they all work together)

    "dk_dragon_blood"
    {
        // General
        //----------------------------------------------------------------------------------
        "BaseClass"                     "ability_datadriven"
        "AbilityBehavior"               "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_HIDDEN"
        "AbilityTextureName"            "dragon_knight_dragon_blood"
    
        // Special
        //----------------------------------------------------------------------------------
        "AbilitySpecial"
        {
            "01"
            {
                "var_type"                      "FIELD_FLOAT"
                "spell_amp_per_stack"           "2.5 3 3.5 5"
                "LinkedSpecialBonus"            "special_bonus_unique_dk_2"
            }
            "02"
            {
                "var_type"                      "FIELD_FLOAT"
                "mana_regen_per_stack"          "0.3 0.4 0.5 0.7"
            }
            "03"
            {
                "var_type"                      "FIELD_FLOAT"
                "hurt_health_ceiling"           "0.87"
            }
            "04"
            {
                "var_type"                      "FIELD_FLOAT"
                "hurt_health_floor"             "0.03"
            }
            "05"
            {
                "var_type"                      "FIELD_FLOAT"
                "hurt_health_step"              "0.07"
            }
        }
    
        // Precache
        //----------------------------------------------------------------------------------
    
        //Datadriven
        //----------------------------------------------------------------------------------
        "OnUpgrade"
        {
            "RunScript"
            {
                "ScriptFile"    "lua_abilities/dragon_blood_talent.lua"
                "Function"      "ApplyLuaModifier"
            }
        }
        "Modifiers"
        {
            "modifier_check_talent"
            {
                "Passive"           "1"
                "IsHidden"          "1"
                "IsDebuff"          "0"
                "IsPurgable"        "0"
                "ThinkInterval"     "0.1"
                "OnIntervalThink"
                {
                    "RunScript"
                    {
                        "ModifierName"  "modifier_dragon_blood"
                        "ScriptFile"    "lua_abilities/dragon_blood.lua"
                        "Function"      "ApplyLuaModifier"
                    }
                }
            }
        }
    }
    
    "special_bonus_unique_dk_2"
    {
        // General
        //----------------------------------------------------------------------------------
        "BaseClass"                     "special_bonus_undefined"
        "AbilityType"                   "DOTA_ABILITY_TYPE_ATTRIBUTES"
        "AbilityBehavior"               "DOTA_ABILITY_BEHAVIOR_PASSIVE"
        "MaxLevel"                      "1"
    
        // Special
        //----------------------------------------------------------------------------------
        "AbilitySpecial"
        {
            "01"
            {
                "var_type"                  "FIELD_FLOAT"
                "value"                     "5"
            }
        }
    }
    

    modifier_dragon_blood_talent(works with the talent)

    modifier_dragon_blood(works without the talent)

    dragon_blood.lua(add the modifier)

    dragon_blood_talent.lua(resets the modifier when you upgrade the ability)

    [Edit] Use this code. The code above (dragon_blood.lua) will only work in my mod with my custom skill.

    dragon_blood = class({})
    LinkLuaModifier("modifier_dragon_blood_talent", LUA_MODIFIER_MOTION_NONE)
    LinkLuaModifier("modifier_dragon_blood", LUA_MODIFIER_MOTION_NONE)
    
    function ApplyLuaModifier(keys)
        local caster = keys.caster
        local ability = keys.ability
        local modifiername = keys.ModifierName
        local talent = caster:FindAbilityByName("special_bonus_unique_dk_2")
        if talent:GetLevel() == 0 then
            caster:AddNewModifier(caster, ability, "modifier_dragon_blood", {})
        else
            caster:RemoveModifierByName("modifier_dragon_blood")
            caster:AddNewModifier(caster, ability, "modifier_dragon_blood_talent", {})
        end
    end
    
  • @DankBud With lua modifier is different, and as I said above, I tried several ways to pass the talent inside it but it never worked. If you know any other way, I'd like to know too.

  • edited November 11 Posts: 151

    @Caelumest what exactly do you mean by

    I tried several ways to pass the talent inside it but it never worked.

    @pujok i know MODIFIER_PROPERTY_CAST_RANGE_BONUS does work in a lua modifier, but i do not know if it can be used in a datadriven modifier

    and as for your talent issue, in your modifier_air_watch modifier you have this:

     "MODIFIER_PROPERTY_ATTACK_RANGE_BONUS" "%attack_range_bonus"
    

    you can make your modifier use the talent value if you instead apply the modifier from a lua script and use:

    "MODIFIER_PROPERTY_ATTACK_RANGE_BONUS" "1"
    

    and set the stack count of the modifier to the bonus you want.

    local value = ability:GetSpecialValueFor("attack_range_bonus")
    
    local talent = caster:FindAbilityByName("airwatcher_bonus2")
    if talent and talent:GetLevel() > 0 then
        value = value + talent:GetSpecialValueFor("value")
    end
    
    local modifier = ability:ApplyDataDrivenModifier(caster, target, "modifier_air_watch", {duration = ability:GetSpecialValueFor("duration")})
    modifier:SetStackCount(value)
    

    edit: and if you dont want the stack count displayed on the modifier you can make the modifier hidden and make a new dummy modifier just for showing on the hud. or rewrite it as a lua modifier.