{"id":842,"date":"2019-12-08T01:33:42","date_gmt":"2019-12-07T17:33:42","guid":{"rendered":"https:\/\/woohuiren.me\/blog\/?p=842"},"modified":"2019-12-08T01:33:50","modified_gmt":"2019-12-07T17:33:50","slug":"creating-units-or-illusions-in-dota-2-lua-modding","status":"publish","type":"post","link":"https:\/\/woohuiren.me\/blog\/creating-units-or-illusions-in-dota-2-lua-modding\/","title":{"rendered":"Creating units or illusions in DotA 2 Lua Modding"},"content":{"rendered":"\n<p>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.<\/p>\n\n\n\n<p>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 <code>SetControllableByPlayer<\/code> and <code>SetOwner<\/code>. However, when creating illusions of heroes, you only set <code>SetControllableByPlayer<\/code> and <code>SetPlayerID<\/code>. This is very important as using <code>SetOwner<\/code> on a hero unit will cause some issues whereas non-hero entities does not have the method <code>SetPlayerID<\/code>.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating a unit<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>local vTargetPosition = self:GetCursorPosition()\nlocal hTreant = CreateUnitByName( \"npc_dota_furion_treant\", vTargetPosition, true, self:GetCaster(), self:GetCaster():GetPlayerOwner(), self:GetCaster():GetTeamNumber() )\nif hTreant ~= nil then\n\thTreant:SetControllableByPlayer( self:GetCaster():GetPlayerID(), false )\n\thTreant:SetOwner( self:GetCaster() )\nend<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Creating a unit with timed lifespan of 5 seconds<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>\nmodifier_furion_force_of_nature_lua = class({})\n\nfunction modifier_furion_force_of_nature_lua:OnDestroy()\n\tif IsServer() then\n\t\tself:GetParent():ForceKill( false )\n\tend\nend\n\n--------------------------------------------------------------------------------\n\nfunction modifier_furion_force_of_nature_lua:DeclareFunctions()\n\tlocal funcs = {\n\t\tMODIFIER_PROPERTY_LIFETIME_FRACTION\n\t}\n\n\treturn funcs\nend\n\n--------------------------------------------------------------------------------\n\nfunction modifier_furion_force_of_nature_lua:GetUnitLifetimeFraction( params )\n\treturn ( ( self:GetDieTime() - GameRules:GetGameTime() ) \/ self:GetDuration() )\nend\n\n--------------------------------------------------------------------------------\n--------------------------------------------------------------------------------\n\nlocal vTargetPosition = self:GetCursorPosition()\nlocal hTreant = CreateUnitByName( \"npc_dota_furion_treant\", vTargetPosition, true, self:GetCaster(), self:GetCaster():GetPlayerOwner(), self:GetCaster():GetTeamNumber() )\nif hTreant ~= nil then\n\thTreant:SetControllableByPlayer( self:GetCaster():GetPlayerID(), false )\n\thTreant:SetOwner( self:GetCaster() )\n    local kv = {\n\t\tduration = 5 -- Unit will live for 5 seconds\n\t}\n\n\thTreant:AddNewModifier( self:GetCaster(), self, \"modifier_furion_force_of_nature_lua\", kv )\nend<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Creating an illusion of a hero (asynchronous)<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>local caster = self:GetCaster()\nlocal unit_name = caster:GetUnitName()\nlocal origin = caster:GetAbsOrigin() + RandomVector(100)\nlocal modifyIllusion = function ( illusion )\n\tillusion:SetControllableByPlayer( caster:GetPlayerID(), false )\n\tillusion:SetPlayerID( caster:GetPlayerID() )\n\n\t-- Set the unit as an illusion\n\t-- 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\n\tillusion:AddNewModifier(caster, self:GetAbility(), \"modifier_illusion\", { duration = 5, outgoing_damage = 0, incoming_damage = 0 })\n\t-- Without MakeIllusion the unit counts as a hero, e.g. if it dies to neutrals it says killed by neutrals, it respawns, etc.\n\tillusion:MakeIllusion()\n\n\t-- Level Up the unit to the casters level\n\tlocal casterLevel = self:GetCaster():GetLevel()\n\tfor i = 2, casterLevel do\n\t\tillusion:HeroLevelUp(false)\n\tend\n\n\t-- Set the skill points to 0 and learn the skills of the caster\n\tillusion:SetAbilityPoints(0)\n\n\tlocal maxAbilities = caster:GetAbilityCount() - 1\n\n\tfor ability_id = 0, maxAbilities do\n\t\tlocal ability = caster:GetAbilityByIndex(ability_id)\n\t\tif ability then\n\t\t\tlocal abilityLevel = ability:GetLevel()\n\t\t\tif abilityLevel ~= 0 then\n\t\t\t\tlocal illusionAbility = illusion:GetAbilityByIndex(ability_id)\n\t\t\t\tif illusionAbility then\n\t\t\t\t\tillusionAbility:SetLevel(abilityLevel)\n\t\t\t\telse\n\t\t\t\t\t-- Add ability\n\t\t\t\t\tlocal abilityName = ability:GetAbilityName()\n\t\t\t\t\tlocal newAbility = illusion:AddAbility(abilityName)\n\t\t\t\t\tnewAbility:SetLevel(abilityLevel)\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\n\t-- Recreate the items of the caster\n\tfor itemSlot=0,5 do\n\t\tlocal item = caster:GetItemInSlot(itemSlot)\n\t\tif item ~= nil then\n\t\t\tlocal itemName = item:GetName()\n\t\t\tlocal newItem = CreateItem(itemName, illusion, illusion)\n\t\t\tillusion:AddItem(newItem)\n\t\tend\n\tend\nend\n\n-- Create unit\nCreateUnitByNameAsync(\n\tunit_name, -- szUnitName\n\torigin, -- vLocation,\n\ttrue, -- bFindClearSpace,\n\tcaster, -- hNPCOwner,\n\tcaster:GetPlayerOwner(), -- hUnitOwner,\n\tcaster:GetTeamNumber(), -- iTeamNumber\n\tmodifyIllusion\n)<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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 &hellip; <a href=\"https:\/\/woohuiren.me\/blog\/creating-units-or-illusions-in-dota-2-lua-modding\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Creating units or illusions in DotA 2 Lua Modding&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[2,5,29],"tags":[201,203,202],"class_list":["post-842","post","type-post","status-publish","format-standard","hentry","category-information-technology","category-programming","category-tutorials","tag-dota-2","tag-dota-2-modding","tag-lua"],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/posts\/842"}],"collection":[{"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/comments?post=842"}],"version-history":[{"count":1,"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/posts\/842\/revisions"}],"predecessor-version":[{"id":843,"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/posts\/842\/revisions\/843"}],"wp:attachment":[{"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/media?parent=842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/categories?post=842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/woohuiren.me\/blog\/wp-json\/wp\/v2\/tags?post=842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}