Special abilities as items

How would I go about allowing items to trigger a special ability that the owner doesn't have? For instance, use an item to cast Pudge's meat hook. Do I need to create a dummy unit and give that ability to it before it's even castable (would that even work?), or is there some other easier way?

Originally I tried creating a custom item with the base class set to the original ability's baseclass but nothing happened when I went to use it. I knew that would be too good to be true!

Comments

  • Posts: 30

    Thanks to this tutorial, I think I figured it out. It requires a little more tweaking than I expected but much less than trying to use the SpellLibrary to duplicate Valve spells.

    Here's how you make Pudge's meat hook into an item usable by any player:

    npc_items_custom.txt

        "item_meat_hook_new"
        {
            "BaseClass"     "item_datadriven"
            "ItemKillable"      "1" 
            "ItemSellable"      "0"
            "ItemPurchasable"   "0"
            "ItemDroppable"     "1"
            "ItemShareability"  "ITEM_FULLY_SHAREABLE_STACKING"
            "ItemDisassembleRule" "DOTA_ITEM_DISASSEMBLE_NEVER"
            "ItemInitialCharges"  "8"
            "ItemDisplayCharges"  "1"
            "ItemRequiresCharges" "0"
            "ItemStackable"     "0"
            "ItemPermanent"     "0"
            // Modify these
            "ID"    "1004"
            "AbilityTextureName"    "item_hvh_meat_hook" // filename: hvh_meat_hook 
            "AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING"
            "AbilityCastRange"      "1300"
            "AbilityCastPoint"      "0.3"
            "AbilityCooldown"       "3"
            "OnSpellStart"
            {
                "RunScript"
                {
                    "ScriptFile"            "SpellLibrary/item_forcecast.lua"
                    "Function"              "ForceCast"
                    "abilityName"           "pudge_meat_hook"
                    "maxDuration"           "3.0"
                }
            }
        }
    

    item_forcecast.lua

    function ForceCast( keys )
        local caster = keys.caster
        local item = keys.ability
        local casterLocation = caster:GetAbsOrigin()
    
        local abilityName = keys.abilityName
        local maxDuration = keys.maxDuration
    
        caster:AddAbility(abilityName)
        local ability = caster:FindAbilityByName(abilityName)
        ability:SetHidden(true)
        ability:SetLevel(ability:GetMaxLevel())
        ability:EndCooldown()
        ability:OnSpellStart()
        Timers:CreateTimer(maxDuration, function()
            caster:RemoveAbility(abilityName)
        end)
    end
    

    Be careful, though. If you remove the ability before it's done casting, the game will behave unpredictably. I'm believe the game has to reference the ability while it's ongoing. For instance, removing Pudge's Meat Hook after 0.03 seconds (1 frame) results in a limp meat hook particle that doesn't connect or do damage. Removing Bane's Nightmare while I was currently under my own spell just flat-out crashed the Dota2 client.

    However, you can't just keep giving players abilities, because I think there's a maximum (16?), and I was having issues with multiple SetHidden(true) calls messing up the ability bar. Any other tips are appreciated.

    Also, this guide was helpful for creating custom ability and item icons.