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