Silencer and omniknight Dota 2 tower defender [Tutorial] Building towers, displaying build area and blocking stacked buildings | Dota 2 Workshop Tool

This tutorial will assume you know about the *.txt files used to create custom units and abilities, and the basics like that.

So, to create a tower creating ability, we need a few things:
  • An overriden hero to place the ability on
  • A custom ability that is attached to said hero
  • A lua script that deals with logic beyond the scope of the ability itself
  • A custom building to place - we could use a preset one, but that is boring.



I will detail the code required for each of these four things, and above each line, I will comment why that line is needed.

Custom Hero

In npc_heroes_custom.txt:

"npc_dota_hero_storm_bro"
{
    "override_hero"     "npc_dota_hero_storm_spirit"
    "Ability1"      "place_tower"
}

Custom Abilities

In npc_abilities_custom.txt:

"place_tower"
    {
        // All abilites require a base class, and since this class is not simply over-riding an old skill, it must be "data_driven"
        "BaseClass" "ability_datadriven"
        // We require blah_POINT to gain the "Target" parameter for the lua functions, and blah_AOE to display the aoe when placing the tower
        "AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_AOE" 
        // These aren't important, but make testing a tad easier
        "AbilityTextureName" "axe_battle_hunger"
        "Ability Cast Range" "0"
        "Ability Cast Point" "0"

        // This is important. This allows us to see the area the tower will be placed on. You ned to make this the same as PLACED_BUILDING_RADIUS in the lua script for consistency.
        "AOERadius" "45"

        // When we start the spell (ie, after we have clicked the location we want)
        "OnSpellStart"
        {
            // We want to run a lua script
            "RunScript"
            {
                // The script file we call
                "ScriptFile"        "scripts/vscripts/custom_abilities.lua"
                // The specific function we want
                "Function"          "placeBuilding"
                // Extra info we want passed to the lua file
                "Target" "POINT"
            }       
        }
    }

And with that, the ability is made!

The lua script


-- Constant placed up here so its easy to see
PLACED_BUILDING_RADIUS = 45.0;
function placeBuilding(keys)
    -- We need a few variables. They should be self-explanatory
    blocking_counter = 0
    attempt_place_location = keys.target_points[1]
    -- Hoooooly complicated! Basically, this line finds all entities within PLACED_BUILDING_RADIUS of where we want to put the tower
    -- The for loop then counts them
    for _,thing in pairs(Entities:FindAllInSphere(GetGroundPosition(attempt_place_location, nil), PLACED_BUILDING_RADIUS) )  do
        -- is this a valid blocker?
        if thing:GetClassname() == "npc_dota_creature" then
            blocking_counter = blocking_counter + 1
            print("blocking creature")
        end
    end
    print(blocking_counter .. " blockers")

    -- If there are any entities to block us placing the tower, don't place it, otherwise: do!
    if( blocking_counter < 1) then
        tower = CreateUnitByName("npc_dota_building_homebase", keys.target_points[1], false, nil, nil,keys.caster:GetPlayerOwner():GetTeam() ) 
        -- Rotate it as we want
        tower:SetAngles(90.0,90.0,90.0)
    end
end 

The custom building

In npc_units_custom.txt

"npc_dota_building_homebase"
{
    // What will it look like
    "Model" "models/buildings/building_plain_reference.vmdl"
    // Its extending creature so we can place it using CreateUnitByName
    "BaseClass" "npc_dota_creature"
    // How big is it. Related to PLACED_BUILDING_RADIUS
    "BoundsHullName" "DOTA_HULL_SIZE_HUGE"
} 

And there you have it! You can now place buildings down as a skill, and the radius indicator of the skill will show you whether the placed building is going to overlap on-top of something when you place it.

The sad thing is, it is impossible to do more than that for placing the tower, as far as I currently know. We do not get access to the mouse cursor at any point apart from when we fire a targeted skill, so we can't draw stuff on it to indicate allowed positions or grids or stuff like that.

Hope this is helpful, Let me know if I made any mistakes or something isn't clear! I prefer to put explanations as code comments, so the code is still understandable when you copy it. If this is a pain, I can reformat.

Tutotials by kotarou_c

Post a Comment

Powered by Blogger.