The following shows several examples of creating units or illusions in DotA 2 modding. This is with regards to server sided modding (custom games in DotA 2). It uses Lua as a language and requires some prior understanding of DotA 2 modding and Lua.
With exception to creating illusions, the code below shows creation of units in a synchronous manner. Take a careful look at the differences. In particular, when creating units, you set both SetControllableByPlayer
and SetOwner
. However, when creating illusions of heroes, you only set SetControllableByPlayer
and SetPlayerID
. This is very important as using SetOwner
on a hero unit will cause some issues whereas non-hero entities does not have the method SetPlayerID
.
Illusions of heroes should be done in an asynchronous manner. This is because the copying of items and abilities takes a longer execution time. Else, you will face latency issues while playing DotA 2. If you want to, you can make creation of both illusions and units asynchronous too.
Creating a unit
local vTargetPosition = self:GetCursorPosition()
local hTreant = CreateUnitByName( "npc_dota_furion_treant", vTargetPosition, true, self:GetCaster(), self:GetCaster():GetPlayerOwner(), self:GetCaster():GetTeamNumber() )
if hTreant ~= nil then
hTreant:SetControllableByPlayer( self:GetCaster():GetPlayerID(), false )
hTreant:SetOwner( self:GetCaster() )
end
Creating a unit with timed lifespan of 5 seconds
modifier_furion_force_of_nature_lua = class({})
function modifier_furion_force_of_nature_lua:OnDestroy()
if IsServer() then
self:GetParent():ForceKill( false )
end
end
--------------------------------------------------------------------------------
function modifier_furion_force_of_nature_lua:DeclareFunctions()
local funcs = {
MODIFIER_PROPERTY_LIFETIME_FRACTION
}
return funcs
end
--------------------------------------------------------------------------------
function modifier_furion_force_of_nature_lua:GetUnitLifetimeFraction( params )
return ( ( self:GetDieTime() - GameRules:GetGameTime() ) / self:GetDuration() )
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local vTargetPosition = self:GetCursorPosition()
local hTreant = CreateUnitByName( "npc_dota_furion_treant", vTargetPosition, true, self:GetCaster(), self:GetCaster():GetPlayerOwner(), self:GetCaster():GetTeamNumber() )
if hTreant ~= nil then
hTreant:SetControllableByPlayer( self:GetCaster():GetPlayerID(), false )
hTreant:SetOwner( self:GetCaster() )
local kv = {
duration = 5 -- Unit will live for 5 seconds
}
hTreant:AddNewModifier( self:GetCaster(), self, "modifier_furion_force_of_nature_lua", kv )
end
Creating an illusion of a hero (asynchronous)
local caster = self:GetCaster()
local unit_name = caster:GetUnitName()
local origin = caster:GetAbsOrigin() + RandomVector(100)
local modifyIllusion = function ( illusion )
illusion:SetControllableByPlayer( caster:GetPlayerID(), false )
illusion:SetPlayerID( caster:GetPlayerID() )
-- Set the unit as an illusion
-- modifier_illusion controls many illusion properties like +Green damage not adding to the unit damage, not being able to cast spells and the team-only blue particle
illusion:AddNewModifier(caster, self:GetAbility(), "modifier_illusion", { duration = 5, outgoing_damage = 0, incoming_damage = 0 })
-- Without MakeIllusion the unit counts as a hero, e.g. if it dies to neutrals it says killed by neutrals, it respawns, etc.
illusion:MakeIllusion()
-- Level Up the unit to the casters level
local casterLevel = self:GetCaster():GetLevel()
for i = 2, casterLevel do
illusion:HeroLevelUp(false)
end
-- Set the skill points to 0 and learn the skills of the caster
illusion:SetAbilityPoints(0)
local maxAbilities = caster:GetAbilityCount() - 1
for ability_id = 0, maxAbilities do
local ability = caster:GetAbilityByIndex(ability_id)
if ability then
local abilityLevel = ability:GetLevel()
if abilityLevel ~= 0 then
local illusionAbility = illusion:GetAbilityByIndex(ability_id)
if illusionAbility then
illusionAbility:SetLevel(abilityLevel)
else
-- Add ability
local abilityName = ability:GetAbilityName()
local newAbility = illusion:AddAbility(abilityName)
newAbility:SetLevel(abilityLevel)
end
end
end
end
-- Recreate the items of the caster
for itemSlot=0,5 do
local item = caster:GetItemInSlot(itemSlot)
if item ~= nil then
local itemName = item:GetName()
local newItem = CreateItem(itemName, illusion, illusion)
illusion:AddItem(newItem)
end
end
end
-- Create unit
CreateUnitByNameAsync(
unit_name, -- szUnitName
origin, -- vLocation,
true, -- bFindClearSpace,
caster, -- hNPCOwner,
caster:GetPlayerOwner(), -- hUnitOwner,
caster:GetTeamNumber(), -- iTeamNumber
modifyIllusion
)