Разработка своей кастомной карты

Участник
Участник
Статус
Оффлайн
Регистрация
28 Июл 2018
Сообщения
577
Реакции
583
Доброго времени суток господа, решил я значится, дублировать на этот форум полезные материалы для мододелов, глядишь откроют ветку для таких как я и сюда подтянутся людишки
В общем то, чего томить, я буду добавлять в теме свои наработки

"Я учусь и вас научу, чо нам пацанам то, просто мало инфы для ру комьюнити"

Сегодня я покажу в примере, как создать свой простой/универсальный предмет сделать ему модельку когда он лежит на земле (аля рапира, ботинки и прочее), поменять предмету текстуру и как ему накинуть иконку в панели предметов, чтож начнем.

Система дропов предметов / спавна предметов позаимствована у "
Пожалуйста, авторизуйтесь для просмотра ссылки.
"

Идем по пути: ********\steam\steamapps\common\dota 2 beta\game\dota_addons\********\scripts\vscripts\ (вместо * ваш путь), создаем тут файлик "item_drop.lua"
code_language.lua:
Expand Collapse Copy
if ItemDrop == nil then

    _G.ItemDrop = class({})

end



-- items - список предметов, которые могут выпасть

-- chance - шанс выпадения (если не определен, то равен 100%) список юнитов из которых могут выпасть предметы ( если не определен, то выпадает с любого юнита)

-- duration - длительность жизни предмета на полу( если не определен, то предмет лежит бесконечно)

-- limit - лимит предметов - количество предметов, которые могут выпасть( если не определен, то количество не ограничено)

-- units - список юнитов, из которых падает предмет



ItemDrop.item_drop = {

--        {items = {"item_branches"}, chance = 5, duration = 5, limit = 3, units = {"npc_name"} },

        {items = {"item_swen_sword"}, units = {"Wooden_box1"}}, --100% шанс дропа из сундука

        {items = {"item_flask"}, chance = 5, duration = 5},-- глобальный дроп в 5% фласки

        {items = {"item_tango_single"}, chance = 15, duration = 3},-- глобальный дроп в 15% кусок тангуса

        {items = {"item_enchanted_mango"}, chance = 8, duration = 5},-- глобальный дроп в 8% манго

}



-- point_name - название таргета

-- item_name - название предмета



ItemDrop.secret_items = {

--    ["point_name"] = "item_name",

    ["item_spawner_swen_sword"] = "item_swen_sword",



}

function ItemDrop:InitGameMode()

    ListenToGameEvent('entity_killed', Dynamic_Wrap(self, 'OnEntityKilled'), self)

    ListenToGameEvent('game_rules_state_change', Dynamic_Wrap(self, 'OnGameRulesStateChange'), self)

end



function ItemDrop:OnGameRulesStateChange()

    local newState = GameRules:State_Get()



    if newState == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then

        ItemDrop:SpawnItems()

    end

end



function ItemDrop:SpawnItems()

    local items = self.secret_items

    for point_name,item_name in pairs(items) do

        local point = Entities:FindByName(nil, point_name)

        if point then

            point = point:GetAbsOrigin()

            local newItem = CreateItem( item_name, nil, nil )

            local drop = CreateItemOnPositionSync( point, newItem )

        else

            print("point with name "..point_name.." dont exist !")

        end

    end

end



function ItemDrop:OnEntityKilled( keys )

    local killedUnit = EntIndexToHScript( keys.entindex_killed )

    local name = killedUnit:GetUnitName()

    local team = killedUnit:GetTeam()



    if team ~= DOTA_TEAM_GOODGUYS and name ~= "npc_dota_thinker" then

        ItemDrop:RollItemDrop(killedUnit)

    end



end



function ItemDrop:RollItemDrop(unit)

    local unit_name = unit:GetUnitName()



    for _,drop in ipairs(self.item_drop) do

        local items = drop.items or nil

        local items_num = #items

        local units = drop.units or nil -- если юниты не были определены, то срабатывает для любого

        local chance = drop.chance or 100 -- если шанс не был определен, то он равен 100

        local loot_duration = drop.duration or nil -- длительность жизни предмета на земле

        local limit = drop.limit or nil -- лимит предметов

        local item_name = items[1] -- название предмета

        local roll_chance = RandomFloat(0, 100)

 

        if units then

            for _,current_name in pairs(units) do

                if current_name == unit_name then

                    units = nil

                    break

                end

            end

        end



        if units == nil and (limit == nil or limit > 0) and roll_chance < chance then

            if limit then

                drop.limit = drop.limit - 1

            end



            if items_num > 1 then

                item_name = items[RandomInt(1, #items)]

            end



            local spawnPoint = unit:GetAbsOrigin()

            local newItem = CreateItem( item_name, nil, nil )

            local drop = CreateItemOnPositionForLaunch( spawnPoint, newItem )

            local dropRadius = RandomFloat( 50, 100 )



            newItem:LaunchLootInitialHeight( false, 0, 150, 0.5, spawnPoint + RandomVector( dropRadius ) )

            if loot_duration then

                newItem:SetContextThink( "KillLoot",

                    function()

                        if drop:IsNull() then

                            return

                        end



                        local nFXIndex = ParticleManager:CreateParticle( "particles/items2_fx/veil_of_discord.vpcf", PATTACH_CUSTOMORIGIN, drop )

                        ParticleManager:SetParticleControl( nFXIndex, 0, drop:GetOrigin() )

                        ParticleManager:SetParticleControl( nFXIndex, 1, Vector( 35, 35, 25 ) )

                        ParticleManager:ReleaseParticleIndex( nFXIndex )

                    --    EmitGlobalSound("Item.PickUpWorld")



                        UTIL_Remove( item )

                        UTIL_Remove( drop )

                    end, loot_duration )

            end

        end

    end

end



function KillLoot( item, drop )



    if drop:IsNull() then

        return

    end



    local nFXIndex = ParticleManager:CreateParticle( "particles/items2_fx/veil_of_discord.vpcf", PATTACH_CUSTOMORIGIN, drop )

    ParticleManager:SetParticleControl( nFXIndex, 0, drop:GetOrigin() )

    ParticleManager:SetParticleControl( nFXIndex, 1, Vector( 35, 35, 25 ) )

    ParticleManager:ReleaseParticleIndex( nFXIndex )

--    EmitGlobalSound("Item.PickUpWorld")



    UTIL_Remove( item )

    UTIL_Remove( drop )

end



ItemDrop:InitGameMode()



В этой же папке откройте ваш "addon_game_mode.lua" и добавьте строчку: require ("item_drop") - она подключит созданный вами ранее LUA скрипт
Теперь приступим непосредственно к созданию модели и все что с ней связано вплоть до текстуры
1) Открываем любой Ваш проект через "Dota 2 tools"
2) Открываем в нём "Hammer"
3) Создаем новую пустую карту (можете её даже не сохранять, она нужна чтобы отцентрировать бедующую модель)
4) Переносите понравившуюся модель в центр сетки
2022-01-01-033016.png
если не отображается просто нажми на него
- Я добавил ландшафт, чтобы понимать, как будет смотреться предмет когда выпадет, как лут (это не обязательно - лишь наглядная демонстрация)
5) Выберите Вашу модель
2022-01-01-033134.png
если не отображается просто нажми на него
6) Нажмите в контекстном меню кнопку: File -> Export Selected
7) Введите название для Вашей модели и сохраните её по пути: \steam\steamapps\common\dota 2 beta\content\dota_addons\*\models (вместо * ваш путь)
8) Откройте в правом верхнем почти углу Tools -> Model editor
2022-01-01-033222.png
если не отображается просто нажми на него
9) В появившемся
2022-01-01-033254.png
если не отображается просто нажми на него
жмем: New VMDL From Mesh File или же сочетание клавиш "Ctrl+M" -> выбираем сохраненную ранее модель в формате "DMX" -> Появится диалоговое окно уточнения пути сохранения будущей модели -> Нажимаем OK
10) Нас встречает окно с Вашей моделью сохраненной ранее, положение модели в котором вы его экспортировали будучи на 6м шаге!
2022-01-01-033325.png
если не отображается просто нажми на него
11) Скачиваем
Пожалуйста, авторизуйтесь для просмотра ссылки.
<- (click) - простая анимация пустоты - с помощью неё мы добавим кость
12) После скачивания помещаем её по пути :\steam\steamapps\common\dota 2 beta\content\dota_addons\***\models\ (Вместо * ваш путь)
13) Возвращаемся в наше окно с моделью, на строке контекстного меню находим кнопку: Animation -> Add Animation -> box.fbx (Выбираем наш ранее скачанный файлик с анимацией пустоты дающий нам косточку) (P.s. Управление такое же как и в Hammer: WASD + ПКМ для поворота камеры)
14) После предыдущего шага должна появиться строка Skeleton и Animations в древе файла слева
15) Нажимаем в контекстном меню кнопку: Model -> Hitboxes -> Add Hitbox -> соглашаемся с названиями либо переименовываем по желанию
16) Теперь настроим хитбокс у модели, выбираем в левом древе: Hitboxes -> HitboxSetList_X -> default -> X (X - название)
17) Для отображения хитбоксов необходимо включить визуалы на контекстном меню: Display -> Show all -> По желанию можно включить куб предмета (по нажатию на Show all они не отображаются, в дисплее оранжевый / фиолетовый / желтые кружки + физика зеленый)
18) После того как нажали на Show all у нас должен появиться зеленый квадратик - наш Хитбокс растягиваем его под модель: он нужен для того, что бы в игре модель можно было трогать как предметы, а не пустые модельки которые нельзя выбрать
19) Как только подогнали хитбокс
2022-01-01-033427.png
если не отображается просто нажми на него
- для более точной настройки используйте значения Bounds в правой колонке
20) Сохраняем нашу готовую модель в контекстном меню нажимаем: File -> Save (ctrl+s)
20.1) Работа с моделью закончена - это то что будет выпадать на землю
20.2) Не спешите закрывать окно, оно щас пригодится чтобы сделать иконку и получить быстро материал для модели (чтоб не бегать по 100 раз в Asset Browser)



Переходим к созданию новой текстуры для предмета
По умолчанию, нельзя взять у готовой модели текстуру в формате TGA/PNG/PSD они все закомпилены, самый простой и быстрый способ это:
1) В том же окне нажимаем на контекстном меню кнопку: Asset -> Open related files -> *** Material Editor (* там много писать.. лень) -> .vmat ( - название материала по умолчанию в формате vmat)
2) Открылось
2022-01-01-033502.png
если не отображается просто нажми на него
, материал котого нельзя заменить, но я скажу хитрость, как оттуда взять эту самую текстуру
3) Жмем в правом окошке, где сфера, на полотно 3я кнопка и получаем нашу
2022-01-01-033538.png
если не отображается просто нажми на него
(она может быть статичной или динамичной)
3.1) Статичная - когда картинка не изменяется (показываю на этом примере)
3.2) Динамичная когда что-то переливается
4) Нехитрым способом WIN+SHIFT+S выделяем область нашей текстуры, открываем любой удобный нам редактор, я открою фотошоп
4.1) Создаю новый файл 1024х1024 - размер текстуры -
2022-01-01-033623.png
если не отображается просто нажми на него
4.2) Вставляю туда текстуру, перекрашиваю её
2022-01-01-033659.png
если не отображается просто нажми на него
4.3) Сохранив новую текстуру в формате PNG | TGA | PSD | TIF
4.4) Идем обратно в окно материалов в контекстном меню нажимаем: File -> New -> Он не даст редактировать пока не сохраним! -> File -> Save As.. -> любое название для материала
4.5) Если все сделано верно, то будут доступны функции для материалов и добавление материала, нажимаем на папку для выбора Color:
2022-01-01-033737.png
если не отображается просто нажми на него
4.6) В появившемся окне выбора текстуры вместо параметра: Images выбираем All Images и выбираем Вашу готовую текстуру
2022-01-01-033823.png
если не отображается просто нажми на него
4.7) Сохраняем Ваш материал в контекстном меню кнопка: File -> Save (ctrl+s)
4.8) Теперь нам доступен новый материал в "Asset Browser"
4.9) Идем в папку с Вашей моделью (куда Вы изначально сохранили МОДЕЛЬ.DMX)
4.10) Открываем Вашу модель.DMX редактором: Notepad ++ | Sublime text | Прочими редакторами
4.11) Ищем такую строку:
Код:
Expand Collapse Copy
"material" "DmeMaterial"

{

    "id" "elementid" "b96f1baf-98cf-4612-975d-0c8171d69a9a"

    "name" "string" "material"

    "mtlName" "string" "materials/models/items/sven/sven_ti7_immortal_sword/sven_ti7_immortal_sword.vmat"

}

materials/models/items/sven/sven_ti7_immortal_sword/sven_ti7_immortal_sword.vmat - является материалом по умолчанию у предмета
Заменяем эту строчку путем к Вашему материалу, я его беру из "ASSET BROWSER" нажав: ПКМ на материал -> Copy Asset Name
a.vmat - путь к моему файлу (он не находится в папке models или material, а просто валяется в папке карты)
4.12) Готово, Вы молодцы и сделали теперь уже лежащий предмет в игре с Вашей текстуркой
Переходим к созданию иконки
1) Открываем любой доступный фото/вектор редактор (желательно конечно же вектор - он не потеряет качество), но я по привычке открою фотошоп
2) Создаем размеры: 88х33 px dpi 300 (стандартно у меня всегда)
3) Заливаем туда картинку подготовленную заранее в хорошем разрешении для нашего предмета в фотошопе будет пиксельная война, для таких приколов лучше использовать CorelDraw
3.1) Покажу лайфхак как замутить со своей наложенной готовой текстурой иконку для предмета:
2022-01-01-033901.png
если не отображается просто нажми на него

Жмем все те же Win+Shift+S выделяем что надо заскринить, идем в редактор и вставляем это в нашу иконку - немного её редачим, фон там накидываем и так далее
Вот картинка без фона в более менее хорошем качестве
если не отображается просто нажми на него
Вот картинка как иконка с фоном
2022-01-01-034023.png
если не отображается просто нажми на него
- мелкие недочеты ретуши уже не видны, да и в падлу было красиво делать

ПУТЬ ДЛЯ СОХРАНЕНИЯ ИКОНОК:
ДИСК:\steam\steamapps\common\dota 2 beta\game\dota_addons\КАРТА\resource\flash3\images\items\ (можно создавать подпапки)

Перейдем теперь к добавлению нашего предмета / меча, в игру :
1) Открываем ДИСК:\steam\steamapps\common\dota 2 beta\game\dota_addons\КАРТА\scripts\npc\ ФАЙЛ "npc_items_custom.txt"
Пример исходного кода с одним кастомным предметом - мечем который я рассматривал в этом уроке:

Код:
Expand Collapse Copy
"DOTAAbilities"
{

//=================================================================================================================

// SWEN SWORD - Меч Свена

//=================================================================================================================

"item_swen_sword" // название предмета

{

    "ID"                        "2122" // уникальный ID предмета (не должны повторяться)

    "AbilityBehavior"                "DOTA_ABILITY_BEHAVIOR_PASSIVE" // Что из себя представляет эффект от предмета (в данном случае пассивку)

    "BaseClass"                    "item_datadriven" // База предмета

    "Model"                        "models/swen_sword.vmdl"// Путь к модельке предмета

    "AbilityTextureName"                "Swen_sword" // Путь к текстурке иконки 88х33 в моём случае просто в папке items

    // Item Info

    //---------------------------------------------------------------------------------------------------------

    "ItemCost"                    "9999999999" // цена покупки

    "ItemSellable"                    "0" // возможность продать

    "ItemKillable"                    "0" // возможность сломать шмотку

    "ItemQuality"                    "epic" // где будет предмет в магазине

    "ItemShopTags"                    "damage" // тэг в поиске магазина

    "ItemAliases"                    "sword_life" // Алиас для магазина

    "ItemShareability"                "ITEM_NOT_SHAREABLE" // возможность стакать предмет - в этом случае уникальный (аля рапира)

    "ItemDeclarations"                "DECLARE_PURCHASES_TO_TEAMMATES | DECLARE_PURCHASES_TO_SPECTATORS | DECLARE_PURCHASES_IN_SPEECH" -- для шопа что-то

    "Modifiers" // модификатор

    {

        "modifier_sword_life" // название модификатора

        {

            "Passive"            "1" // тип модификатора

            "IsHidden"            "1" // видимость модификатора

            "Properties" // действие модификатора

            {

                "MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE"             "%bonus_damage" // дать носителю дамаг от абилки bonus_damage

            }

        }

    }

    //  Special    // специальные вставки

    //---------------------------------------------------------------------------------------------------------

   "AbilitySpecial" // абика

    {



        "01" // нумирация



        {



            "var_type"            "FIELD_INTEGER" // тип исчисления (целочисленное)



            "bonus_damage"            "150" // бонус от абилки дамаг +150



        }



    }



}

}

}
2) Возвращаемся в наш файл Item_drop.lua, начинаем добавлять предмет (в коде он уже добавлен как шанс дропа из ящика - но у вас не будет этого самого ящика по этому любой ваш юнит на карте) либо просто заспавните его на полу через "ItemDrop.secret_items", напишите название info_target и название предмета
ДИСК:\steam\steamapps\common\dota 2 beta\game\dota_addons\КАРТА\resource\ файл "addon_russian.txt"
code_language.lua:
Expand Collapse Copy
"lang"
{

    "Language"        "russian"

    "Tokens"

    {

        "addon_game_name"            "Название вашей кастомки"

        "DOTA_Tooltip_ability_item_swen_sword"                      "Легендарный меч Свена"

        "DOTA_Tooltip_ability_item_swen_sword_Lore"                    "По легенде этот мечь способен прорубать толпы врагов"

        "DOTA_Tooltip_ability_item_swen_sword_bonus_damage"            "+к урону"

    }

}
Возвращаемся в Hammer пробуем компилить и радуемся
2022-01-01-034055.png
если не отображается просто нажми на него
2022-01-01-034128.png
если не отображается просто нажми на него
2022-01-01-034202.png
если не отображается просто нажми на него
2022-01-01-034228.png
если не отображается просто нажми на него

Ссылка на первоисточник "
Пожалуйста, авторизуйтесь для просмотра ссылки.
"

Спасибо за внимание :з

Всех с новым 2022 годом, вот вам господа мододелы, исходничек Lua скрипта на ограничение подбора более одного уникального предмета

Благодарность за исходник: "
Пожалуйста, авторизуйтесь для просмотра ссылки.
"

Нам понадобиться:
Пример можно взять
Пожалуйста, авторизуйтесь для просмотра ссылки.
<- (click)
Путь к файлу:
*:\steam\steamapps\common\dota 2 beta\game\dota_addons\КАРТА\scripts\vscripts\
Название файла:
custom_sword.lua

code_language.lua:
Expand Collapse Copy
LinkLuaModifier("modifier_item_sword_life_lua", "custom_sword", LUA_MODIFIER_MOTION_NONE)
LinkLuaModifier("modifier_item_sword_water_lua", "custom_sword", LUA_MODIFIER_MOTION_NONE)
LinkLuaModifier("modifier_item_sword_death_lua", "custom_sword", LUA_MODIFIER_MOTION_NONE)
LinkLuaModifier("modifier_item_sword_insects_lua", "custom_sword", LUA_MODIFIER_MOTION_NONE)



item_sword_life_lua = class({})

function item_sword_life_lua:GetIntrinsicModifierName()
    return "modifier_item_sword_life_lua"
end

modifier_item_sword_life_lua = class({
    IsHidden                = function(self) return true end,
    IsPurgable              = function(self) return false end,
    IsDebuff                = function(self) return false end,
    IsBuff                  = function(self) return true end,
    RemoveOnDeath           = function(self) return false end,
    DeclareFunctions        = function(self) return
    {
        MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE,
    } end,

})


function modifier_item_sword_life_lua:OnCreated()
    local caster = self:GetCaster()
    local vLocation = caster:GetAbsOrigin()
    local item = self:GetAbility()

    if caster.sword == nil then
        caster.sword = self
    else
        Timers:CreateTimer(0, function()
            caster:DropItemAtPositionImmediate(item, vLocation)
            GameRules:SendCustomMessage("<font color='#FA8072'> Нельзя носить более одного уникального меча !</font>",0,0)
        end)
    end
    self.bonus_dmg = self:GetAbility():GetSpecialValueFor("bonus_dmg")
end

function modifier_item_sword_life_lua:OnDestroy()
    local caster = self:GetCaster()

    if caster.sword == self then
        caster.sword = nil
    end
end

function modifier_item_sword_life_lua:GetAttributes()
    return MODIFIER_ATTRIBUTE_MULTIPLE + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE
end

function modifier_item_sword_life_lua:GetModifierPreAttack_BonusDamage()
    return self.bonus_dmg
end



item_sword_water_lua = class({})

function item_sword_water_lua:GetIntrinsicModifierName()
    return "modifier_item_sword_water_lua"
end

modifier_item_sword_water_lua = class({
    IsHidden                = function(self) return true end,
    IsPurgable              = function(self) return false end,
    IsDebuff                = function(self) return false end,
    IsBuff                  = function(self) return true end,
    RemoveOnDeath           = function(self) return false end,
    DeclareFunctions        = function(self) return
    {
        MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE,
    } end,

})


function modifier_item_sword_water_lua:OnCreated()
    local caster = self:GetCaster()
    local vLocation = caster:GetAbsOrigin()
    local item = self:GetAbility()

    if caster.sword == nil then
        caster.sword = self
    else
        Timers:CreateTimer(0, function()
            caster:DropItemAtPositionImmediate(item, vLocation)
            GameRules:SendCustomMessage("<font color='#FA8072'> Нельзя носить более одного уникального меча !</font>",0,0)
        end)
    end
    self.bonus_dmg = self:GetAbility():GetSpecialValueFor("bonus_dmg")
end

function modifier_item_sword_water_lua:OnDestroy()
    local caster = self:GetCaster()

    if caster.sword == self then
        caster.sword = nil
    end
end

function modifier_item_sword_water_lua:GetAttributes()
    return MODIFIER_ATTRIBUTE_MULTIPLE + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE
end

function modifier_item_sword_water_lua:GetModifierPreAttack_BonusDamage()
    return self.bonus_dmg
end



item_sword_death_lua = class({})

function item_sword_death_lua:GetIntrinsicModifierName()
    return "modifier_item_sword_death_lua"
end

modifier_item_sword_death_lua = class({
    IsHidden                = function(self) return true end,
    IsPurgable              = function(self) return false end,
    IsDebuff                = function(self) return false end,
    IsBuff                  = function(self) return true end,
    RemoveOnDeath           = function(self) return false end,
    DeclareFunctions        = function(self) return
    {
        MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE,
    } end,

})


function modifier_item_sword_death_lua:OnCreated()
    local caster = self:GetCaster()
    local vLocation = caster:GetAbsOrigin()
    local item = self:GetAbility()

    if caster.sword == nil then
        caster.sword = self
    else
        Timers:CreateTimer(0, function()
            caster:DropItemAtPositionImmediate(item, vLocation)
            GameRules:SendCustomMessage("<font color='#FA8072'> Нельзя носить более одного уникального меча !</font>",0,0)
        end)
    end
    self.bonus_dmg = self:GetAbility():GetSpecialValueFor("bonus_dmg")
end

function modifier_item_sword_death_lua:OnDestroy()
    local caster = self:GetCaster()

    if caster.sword == self then
        caster.sword = nil
    end
end

function modifier_item_sword_death_lua:GetAttributes()
    return MODIFIER_ATTRIBUTE_MULTIPLE + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE
end

function modifier_item_sword_death_lua:GetModifierPreAttack_BonusDamage()
    return self.bonus_dmg
end



item_sword_insects_lua = class({})

function item_sword_insects_lua:GetIntrinsicModifierName()
    return "modifier_item_sword_insects_lua"
end

modifier_item_sword_insects_lua = class({
    IsHidden                = function(self) return true end,
    IsPurgable              = function(self) return false end,
    IsDebuff                = function(self) return false end,
    IsBuff                  = function(self) return true end,
    RemoveOnDeath           = function(self) return false end,
    DeclareFunctions        = function(self) return
    {
        MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE,
    } end,

})


function modifier_item_sword_insects_lua:OnCreated()
    local caster = self:GetCaster()
    local vLocation = caster:GetAbsOrigin()
    local item = self:GetAbility()

    if caster.sword == nil then
        caster.sword = self
    else
        Timers:CreateTimer(0, function()
            caster:DropItemAtPositionImmediate(item, vLocation)
            GameRules:SendCustomMessage("<font color='#FA8072'> Нельзя носить более одного уникального меча !</font>",0,0)
        end)
    end
    self.bonus_dmg = self:GetAbility():GetSpecialValueFor("bonus_dmg")
end

function modifier_item_sword_insects_lua:OnDestroy()
    local caster = self:GetCaster()

    if caster.sword == self then
        caster.sword = nil
    end
end

function modifier_item_sword_insects_lua:GetAttributes()
    return MODIFIER_ATTRIBUTE_MULTIPLE + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE
end

function modifier_item_sword_insects_lua:GetModifierPreAttack_BonusDamage()
    return self.bonus_dmg
end
Путь к файлу:
*:\steam\steamapps\common\dota 2 beta\game\dota_addons\КАРТА\scripts\npc\
Название файла:
npc_items_custom.txt
Код:
Expand Collapse Copy
"DOTAAbilities"
{

     "item_sword_insects_lua"
        {
            "BaseClass"                     "item_lua"
            "ScriptFile"                    "custom_sword"
            "AbilityBehavior"                "DOTA_ABILITY_BEHAVIOR_PASSIVE"
               "Model"                        "models/sword_insects.vmdl"
                   "AbilityTextureName"                "sword_insects"

            "AbilitySpecial"
            {
                "01"
                {
                    "var_type"            "FIELD_INTEGER"
                    "bonus_dmg"            "150"
                }
            }
        }

    "item_sword_death_lua"
        {
            "BaseClass"                     "item_lua"
            "ScriptFile"                    "custom_sword"
            "AbilityBehavior"                "DOTA_ABILITY_BEHAVIOR_PASSIVE"
              "Model"                        "models/sword_death.vmdl"
                  "AbilityTextureName"                "sword_death"

            "AbilitySpecial"
            {
                "01"
                {
                    "var_type"            "FIELD_INTEGER"
                    "bonus_dmg"            "150"
                }
            }
        }

   "item_sword_water_lua"
       {
           "BaseClass"                     "item_lua"
           "ScriptFile"                    "custom_sword"
           "AbilityBehavior"                "DOTA_ABILITY_BEHAVIOR_PASSIVE"
           "Model"                        "models/sword_water.vmdl"
                   "AbilityTextureName"                "sword_water"

           "AbilitySpecial"
           {
               "01"
               {
                   "var_type"            "FIELD_INTEGER"
                   "bonus_dmg"            "150"
               }
           }
       }

  "item_sword_life_lua"
    {
        "BaseClass"                     "item_lua"
        "ScriptFile"                    "custom_sword"
        "AbilityBehavior"                "DOTA_ABILITY_BEHAVIOR_PASSIVE"
        "Model"                            "models/sword_life.vmdl"
        "AbilityTextureName"            "sword_life"
        "RingRadius"                "99"
        "HealthBarOffset"            "300"
        "AbilitySpecial"
        {
            "01"
            {
                "var_type"            "FIELD_INTEGER"
                "bonus_dmg"            "150"
            }
        }
    }
}
Закиньте файл с любым названием - содержание:
code_language.lua:
Expand Collapse Copy
--[[
  -- A timer running every second that starts immediately on the next frame, respects pauses
  Timers:CreateTimer(function()
      print ("Hello. I'm running immediately and then every second thereafter.")
      return 1.0
    end
  )
  -- A timer running every second that starts 5 seconds in the future, respects pauses
  Timers:CreateTimer(5, function()
      print ("Hello. I'm running 5 seconds after you called me and then every second thereafter.")
      return 1.0
    end
  )
  -- 10 second delayed, run once using gametime (respect pauses)
  Timers:CreateTimer({
    endTime = 10, -- when this timer should first execute, you can omit this if you want it to run first on the next frame
    callback = function()
      print ("Hello. I'm running 10 seconds after when I was started.")
    end
  })
  -- 10 second delayed, run once regardless of pauses
  Timers:CreateTimer({
    useGameTime = false,
    endTime = 10, -- when this timer should first execute, you can omit this if you want it to run first on the next frame
    callback = function()
      print ("Hello. I'm running 10 seconds after I was started even if someone paused the game.")
    end
  })
  -- A timer running every second that starts after 2 minutes regardless of pauses
  Timers:CreateTimer("uniqueTimerString3", {
    useGameTime = false,
    endTime = 120,
    callback = function()
      print ("Hello. I'm running after 2 minutes and then every second thereafter.")
      return 1
    end
  })
  -- A timer using the old style to repeat every second starting 5 seconds ahead
  Timers:CreateTimer("uniqueTimerString3", {
    useOldStyle = true,
    endTime = GameRules:GetGameTime() + 5,
    callback = function()
      print ("Hello. I'm running after 5 seconds and then every second thereafter.")
      return GameRules:GetGameTime() + 1
    end
  })
]]

TIMERS_THINK = 0.01

if Timers == nil then
    print ( '[Timers] creating Timers' )
    Timers = {}
    Timers.__index = Timers
end

function Timers:new( o )
    o = o or {}
    setmetatable( o, Timers )
    return o
end

function Timers:start()
    Timers = self
    self.timers = {}

    local ent = Entities:CreateByClassname("info_target") -- Entities:FindByClassname(nil, 'CWorld')
    ent:SetThink("Think", self, "timers", TIMERS_THINK)
end

function Timers:Think()
    if GameRules:State_Get() >= DOTA_GAMERULES_STATE_POST_GAME then
        return
    end

    -- Track game time, since the dt passed in to think is actually wall-clock time not simulation time.
    local now = GameRules:GetGameTime()

    -- Process timers
    for k,v in pairs(Timers.timers) do
        local bUseGameTime = true
        if v.useGameTime ~= nil and v.useGameTime == false then
            bUseGameTime = false
        end
        local bOldStyle = false
        if v.useOldStyle ~= nil and v.useOldStyle == true then
            bOldStyle = true
        end

        local now = GameRules:GetGameTime()
        if not bUseGameTime then
            now = Time()
        end

        if v.endTime == nil then
            v.endTime = now
        end
        -- Check if the timer has finished
        if now >= v.endTime then
            -- Remove from timers list
            Timers.timers[k] = nil

            -- Run the callback
            local status, nextCall = pcall(v.callback, GameRules:GetGameModeEntity(), v)

            -- Make sure it worked
            if status then
                -- Check if it needs to loop
                if nextCall then
                    -- Change its end time

                    if bOldStyle then
                        v.endTime = v.endTime + nextCall - now
                    else
                        v.endTime = v.endTime + nextCall
                    end

                    Timers.timers[k] = v
                end

                -- Update timer data
                --self:UpdateTimerData()
            else
                -- Nope, handle the error
                Timers:HandleEventError('Timer', k, nextCall)
            end
        end
    end

    return TIMERS_THINK
end

function Timers:HandleEventError(name, event, err)
    print(err)

    -- Ensure we have data
    name = tostring(name or 'unknown')
    event = tostring(event or 'unknown')
    err = tostring(err or 'unknown')

    -- Tell everyone there was an error
    --Say(nil, name .. ' threw an error on event '..event, false)
    --Say(nil, err, false)

    -- Prevent loop arounds
    if not self.errorHandled then
        -- Store that we handled an error
        self.errorHandled = true
    end
end

function Timers:CreateTimer(name, args)
    if type(name) == "function" then
        args = {callback = name}
        name = DoUniqueString("timer")
    elseif type(name) == "table" then
        args = name
        name = DoUniqueString("timer")
    elseif type(name) == "number" then
        args = {endTime = name, callback = args}
        name = DoUniqueString("timer")
    end
    if not args.callback then
        print("Invalid timer created: "..name)
        return
    end


    local now = GameRules:GetGameTime()
    if args.useGameTime ~= nil and args.useGameTime == false then
        now = Time()
    end

    if args.endTime == nil then
        args.endTime = now
    elseif args.useOldStyle == nil or args.useOldStyle == false then
        args.endTime = now + args.endTime
    end

    Timers.timers[name] = args

    return name
end

function Timers:RemoveTimer(name)
    Timers.timers[name] = nil
end

function Timers:RemoveTimers(killAll)
    local timers = {}

    if not killAll then
        for k,v in pairs(Timers.timers) do
            if v.persist then
                timers[k] = v
            end
        end
    end

    Timers.timers = timers
end

Timers:start()
Это таймеры, если у вас вдруг их нет
И подключите файл через:
require ("Ваше название") //без формата: require ("timers")
В файле addon_game_mode.lua
Путь к файлу:
*:\steam\steamapps\common\dota 2 beta\game\dota_addons\КАРТА\resource\
Файл:
addon_russian.txt
Код:
Expand Collapse Copy
"lang"
{
    "Language"        "russian"
    "Tokens"
    {

        "DOTA_Tooltip_ability_item_sword_life_lua"                          "Меч повелителя теплокровных"
        "DOTA_Tooltip_ability_item_sword_life_lua_Lore"                        "По легенде этот меч способен покарить теплокровных существ"
        "DOTA_Tooltip_ability_item_sword_life_lua_bonus_dmg"                "+к урону по живым"

        "DOTA_Tooltip_ability_item_sword_water_lua"                          "Меч повелителя хладнокровных"
        "DOTA_Tooltip_ability_item_sword_water_lua_Lore"                     "По легенде этот меч способен покарить хлоднокровных существ"
        "DOTA_Tooltip_ability_item_sword_water_lua_bonus_dmg"             "+к урону по амфибиям"

        "DOTA_Tooltip_ability_item_sword_insects_lua"                        "Меч повелителя насекомых"
        "DOTA_Tooltip_ability_item_sword_insects_lua_Lore"                     "По легенде этот меч способен покарить членистоногих"
        "DOTA_Tooltip_ability_item_sword_insects_lua_bonus_dmg"             "+к урону по насекомым"

        "DOTA_Tooltip_ability_item_sword_death_lua"                          "Меч повелителя смерти"
        "DOTA_Tooltip_ability_item_sword_death_lua_Lore"                     "По легенде этот меч способен покарить всю нечисть"
        "DOTA_Tooltip_ability_item_sword_death_lua_bonus_dmg"             "+к урону по мертвым"
    }
}



as5c_tW2--A.jpg
7cr_tPQCy3I.jpg


Ссылка на первоисточник "
Пожалуйста, авторизуйтесь для просмотра ссылки.
"

Спасибо за внимание :3
 
Последнее редактирование:
Добрый день господа, мододелы, вот вам небольшой сборник пассивных способностей

У вас уже должна быть база (какой то начальный проект)

Установка в 3х пунктах:

Берем из спойлера - Абилку, которая вам понравилась

1.1] Идем по пути: :\steam\steamapps\common\dota 2 beta\game\dota_addons\***\npc\ в файлик: npc_abilities_custom.txt

1.2] Вставляем абилку между фигурных скобок

"DOTAAbilities"

{

}

1.3] Строки:

"ScriptFile" "heroes/passive/legion_Armor" - ПУТЬ К LUA файлу (P.S. Если вы оставили скрипт в корне VSCRIPTS => Путь будет: "Ваше название скрипта, без расширения *.lua")

"AbilityTextureName" "specal/armor" - ПУТЬ К Иконке 128х128 .png (Полный путь: :\steam\steamapps\common\dota 2 beta\game\dota_addons\**\resource\flash3\images\spellicons\specal\)

Берем из спойлера - LUA, которая вам понравилась

2.1] Идем по пути: :\steam\steamapps\common\dota 2 beta\game\dota_addons\***\scripts\vscripts\ (* - диск, **** - ваша карта) p.s. По желанию можно разделить папками ваши абилки

Пример из сборника пассивок: :\steam\steamapps\common\dota 2 beta\game\dota_addons\***\scripts\vscripts\hero\Passive (Добавилась 1 папка и подпапка)

2.2] Создаем файл с расширением *.lua и вставляем в него код

2.3] Если у вас другие папки/подпапки или вовсе вы создали *.lua в корне vscripts то редактируем путь в коде:

Находим строчку: LinkLuaModifier("modifier_legion_Armor", "heroes/Passive/legion_Armor", LUA_MODIFIER_MOTION_NONE)

Меняем в кавычках путь: "heroes/Passive/legion_Armor" => "Ваш путь к LUA, без расширения *.lua"

P.S. Если вы оставили скрипт в корне VSCRIPTS => Путь будет: "Ваше название скрипта, без расширения *.lua"

P.s. содержание строки зависит от пассивки/модификатора, главное это путь к скрипту!

Берем из спойлера - Ру локаль, от абилки которая вам понравилась

3.1]Идем по пути: :\steam\steamapps\common\dota 2 beta\game\dota_addons\***\resource\ (* - диск, **** - ваша карта)

3.2] Открываем / создаем файлик: addon_russian.txt

3.3] Вставляем строки между:

"lang"

{

"Language" "russian"

"Tokens"

{

"addon_game_name" "Название вашей карты на ру"

Вот сюда уже строки

}

}




Код:
Expand Collapse Copy
"passive_Legion_Armor"

   {

      "BaseClass"                "ability_lua"

      "ScriptFile"            "heroes/passive/legion_Armor"

      "AbilityTextureName"      "specal/armor"

      "MaxLevel"             "5"



      "AbilityType"           "DOTA_ABILITY_TYPE_BASIC"

      "AbilityBehavior"        "DOTA_ABILITY_BEHAVIOR_PASSIVE"



      "AbilitySpecial"

      {

         "01"

         {

            "var_type"       "FIELD_INTEGER"

            "bonus_armor"     "3 7 12 16 23"

         }

         "02"

         {

            "var_type"       "FIELD_INTEGER"

            "bonus_resist"    "4 8 12 16 20"

         }

      }

   }


code_language.lua:
Expand Collapse Copy
passive_Legion_Armor = class({})



LinkLuaModifier("modifier_passive_Legion_Armor", "heroes/passive/legion_Armor", LUA_MODIFIER_MOTION_NONE)



function passive_Legion_Armor:GetIntrinsicModifierName()

    return "modifier_passive_Legion_Armor"

end



modifier_passive_Legion_Armor = class({})



function modifier_passive_Legion_Armor:IsHidden() return true end

function modifier_passive_Legion_Armor:IsDebuff() return false end

function modifier_passive_Legion_Armor:IsPurgable() return false end

function modifier_passive_Legion_Armor:GetAttributes() return MODIFIER_ATTRIBUTE_PERMANENT + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE end



function modifier_passive_Legion_Armor:DeclareFunctions()

    local funcs = {

        MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS,

        MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING,

    }

    return funcs

end



function modifier_passive_Legion_Armor:GetModifierPhysicalArmorBonus()

    return self:GetAbility():GetSpecialValueFor("bonus_armor")

end



function modifier_passive_Legion_Armor:GetModifierStatusResistanceStacking()

    return self:GetAbility():GetSpecialValueFor("bonus_resist")

end


Код:
Expand Collapse Copy
        "DOTA_Tooltip_ability_Passive_Legion_Armor"                                    "Броня легиона"

        "DOTA_Tooltip_ability_Passive_Legion_Armor_Description"                        "Увеличивает броню на %bonus_armor% и сопротивление эффектам на %bonus_resist%%%."

        "DOTA_Tooltip_ability_Passive_Legion_Armor_lore"                            "Дарует вам броню Легендарного легиона, прошло уже более 1000 лет, а их сталь все ещё крепче любого металла!"

Код:
Expand Collapse Copy
    "passive_honed_mastery_of_weapons"

        {

            "BaseClass"                    "ability_lua"

            "ScriptFile"                "heroes/passive/mastery_of_weapons"

            "AbilityTextureName"        "specal/war"

            "MaxLevel"                    "5"



            "AbilityType"                "DOTA_ABILITY_TYPE_BASIC"

            "AbilityBehavior"            "DOTA_ABILITY_BEHAVIOR_PASSIVE"



            "AbilitySpecial"

            {

                "01"

                {

                    "var_type"            "FIELD_INTEGER"

                    "bonus_dmg"            "3 10 23 28 30"

                }

            }

        }

code_language.lua:
Expand Collapse Copy
passive_honed_mastery_of_weapons = class({})



LinkLuaModifier("modifier_passive_honed_mastery_of_weapons", "heroes/passive/mastery_of_weapons", LUA_MODIFIER_MOTION_NONE)



function passive_honed_mastery_of_weapons:GetIntrinsicModifierName()

    return "modifier_passive_honed_mastery_of_weapons"

end











modifier_passive_honed_mastery_of_weapons = class({})



function modifier_passive_honed_mastery_of_weapons:IsHidden() return true end

function modifier_passive_honed_mastery_of_weapons:IsDebuff() return false end

function modifier_passive_honed_mastery_of_weapons:IsPurgable() return false end

function modifier_passive_honed_mastery_of_weapons:GetAttributes() return MODIFIER_ATTRIBUTE_PERMANENT + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE end



function modifier_passive_honed_mastery_of_weapons:DeclareFunctions()

    local funcs = {

        MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE

    }

    return funcs

end



function modifier_passive_honed_mastery_of_weapons:GetModifierDamageOutgoing_Percentage()

    return self:GetAbility():GetSpecialValueFor("bonus_dmg")

end



function modifier_passive_honed_mastery_of_weapons:CheckState()

    return {

        [MODIFIER_STATE_CANNOT_MISS] = true,

    }

end

Код:
Expand Collapse Copy
        "DOTA_Tooltip_ability_passive_honed_mastery_of_weapons"                                    "Мастерство владения оружием"

        "DOTA_Tooltip_ability_passive_honed_mastery_of_weapons_Description"                        "Дарует <font color='#B694FF'> <b>атаки без промахов</b> </font> и %bonus_dmg%%% дополнительного урона."

        "DOTA_Tooltip_ability_passive_honed_mastery_of_weapons_lore"                                "Непрерывная тренировка оттачивает оружие воина в его собственное продолжение."

Код:
Expand Collapse Copy
"passive_influx_of_life"

        {

            "BaseClass"                    "ability_lua"

            "ScriptFile"                "heroes/passive/influx_of_life"

            "AbilityTextureName"        "specal/heal"

            "MaxLevel"                    "5"



            "AbilityType"                "DOTA_ABILITY_TYPE_BASIC"

            "AbilityBehavior"            "DOTA_ABILITY_BEHAVIOR_PASSIVE"



            "AbilitySpecial"

            {

                "01"

                {

                    "var_type"            "FIELD_INTEGER"

                    "bonus_heal"        "3 6 9 12 16"

                }

                "02"

                {

                    "var_type"            "FIELD_INTEGER"

                    "percent_heal"        "1"

                }

            }

        }

code_language.lua:
Expand Collapse Copy
passive_influx_of_life = class({})



LinkLuaModifier("modifier_passive_influx_of_life", "heroes/passive/influx_of_life", LUA_MODIFIER_MOTION_NONE)



function passive_influx_of_life:GetIntrinsicModifierName()

    return "modifier_passive_influx_of_life"

end



modifier_passive_influx_of_life = class({})



function modifier_passive_influx_of_life:IsHidden() return true end

function modifier_passive_influx_of_life:IsDebuff() return false end

function modifier_passive_influx_of_life:IsPurgable() return false end

function modifier_passive_influx_of_life:GetAttributes() return MODIFIER_ATTRIBUTE_PERMANENT + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE end



function modifier_passive_influx_of_life:OnCreated()

    self:OnRefresh()

end



function modifier_passive_influx_of_life:OnRefresh()

    self.bonus_heal = self:GetAbility():GetSpecialValueFor("bonus_heal")

    self.percent_heal = self:GetAbility():GetSpecialValueFor("percent_heal")

end



function modifier_passive_influx_of_life:DeclareFunctions()

    return {

        MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE,

        MODIFIER_PROPERTY_HP_REGEN_AMPLIFY_PERCENTAGE,

        MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE

    }

end



function modifier_passive_influx_of_life:GetModifierHealAmplify_PercentageSource()

    return self.bonus_heal or 0

end



function modifier_passive_influx_of_life:GetModifierHPRegenAmplify_Percentage()

    return self.bonus_heal or 0

end



function modifier_passive_influx_of_life:GetModifierHealthRegenPercentage()

    return self.percent_heal or 0

end

Код:
Expand Collapse Copy
        "DOTA_Tooltip_ability_passive_influx_of_life"                                    "Приток жизни"

        "DOTA_Tooltip_ability_passive_influx_of_life_Description"                        "Увеличивает исходящее лечение и восстановление здоровья на %bonus_heal%%%."

        "DOTA_Tooltip_ability_passive_influx_of_life_lore"                                "Годы медитаций позволили вам восстанавливаться гораздо быстрее чем обычный человек"

Код:
Expand Collapse Copy
"passive_magical_exhaustion"

        {

            "BaseClass"                    "ability_lua"

            "ScriptFile"                "heroes/passive/magical_exhaustion"

            "AbilityTextureName"        "specal/mag_debaf"

            "MaxLevel"                    "5"



            "AbilityType"                "DOTA_ABILITY_TYPE_BASIC"

            "AbilityBehavior"            "DOTA_ABILITY_BEHAVIOR_PASSIVE"



            "AbilitySpecial"

            {

                "01"

                {

                    "var_type"            "FIELD_INTEGER"

                    "magic_resist"        "8 14 17 22 25"

                }

                "02"

                {

                    "var_type"            "FIELD_INTEGER"

                    "status_resist"        "8 14 17 22 25"

                }

            }

        }

code_language.lua:
Expand Collapse Copy
passive_magical_exhaustion = class({})



LinkLuaModifier("modifier_passive_magical_exhaustion", "heroes/passive/magical_exhaustion", LUA_MODIFIER_MOTION_NONE)

LinkLuaModifier("modifier_passive_magical_exhaustion_aura", "heroes/passive/magical_exhaustion", LUA_MODIFIER_MOTION_NONE)



function passive_magical_exhaustion:GetIntrinsicModifierName()

    return "modifier_passive_magical_exhaustion"

end



modifier_passive_magical_exhaustion = class({})



function modifier_passive_magical_exhaustion:IsHidden() return true end

function modifier_passive_magical_exhaustion:IsDebuff() return false end

function modifier_passive_magical_exhaustion:IsPurgable() return false end

function modifier_passive_magical_exhaustion:GetAttributes() return MODIFIER_ATTRIBUTE_PERMANENT + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE end





function modifier_passive_magical_exhaustion:IsAura() return true end

function modifier_passive_magical_exhaustion:GetAuraRadius() return 1200 end

function modifier_passive_magical_exhaustion:GetAuraSearchTeam() return DOTA_UNIT_TARGET_TEAM_ENEMY end

function modifier_passive_magical_exhaustion:GetAuraSearchType() return DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC end

function modifier_passive_magical_exhaustion:GetModifierAura() return "modifier_passive_magical_exhaustion_aura" end







modifier_passive_magical_exhaustion_aura = class({})



function modifier_passive_magical_exhaustion:IsDebuff() return false end

function modifier_passive_magical_exhaustion:IsPurgable() return false end



function modifier_passive_magical_exhaustion_aura:DeclareFunctions()

    return {

        MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS,

        MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING

    }

end



function modifier_passive_magical_exhaustion_aura:OnCreated()

    local ability = self:GetAbility()

    if (not ability) or ability:IsNull() then return end



    self.magic_resist = (-1) * ability:GetSpecialValueFor("magic_resist")

    self.status_resist = (-1) * ability:GetSpecialValueFor("status_resist")

end



function modifier_passive_magical_exhaustion_aura:GetModifierMagicalResistanceBonus()

    return self.magic_resist or 0

end



function modifier_passive_magical_exhaustion_aura:GetModifierStatusResistanceStacking()

    return self.status_resist or 0

end



function modifier_passive_magical_exhaustion_aura:GetEffectName()

    return "particles/dev/library/base_item_attachment_magic.vpcf"

end



function modifier_passive_magical_exhaustion_aura:GetEffectAttachType()

    return PATTACH_OVERHEAD_FOLLOW

end



function modifier_passive_magical_exhaustion_aura:ShouldUseOverheadOffset()

    return false

end

Код:
Expand Collapse Copy
        "DOTA_Tooltip_ability_passive_magical_exhaustion"                                "Магическое подавление"

        "DOTA_Tooltip_ability_passive_magical_exhaustion_Description"                    "Вы уменьшаете у ближайших врагов магическое сопротивление на %magic_resist%%% и сопротивление эффектам на %status_resist%%%."

        "DOTA_Tooltip_ability_passive_magical_exhaustion_lore"                            "Отсутствие вашей души нервирует всех ближайших живых существ, снижая их естественную защиту от магии и странностей в целом."

        "DOTA_Tooltip_modifier_passive_magical_exhaustion_aura"                                "Магическое подавление"

        "DOTA_Tooltip_modifier_passive_magical_exhaustion_aura_Description"                            "Ваше магическое сопротивление и сопротивление эффектам снижено"

Код:
Expand Collapse Copy
"passive_attack_speed"

        {

            "BaseClass"                    "ability_lua"

            "ScriptFile"                "heroes/passive/attack_speed"

            "AbilityTextureName"        "specal/add_speed_damage"

            "MaxLevel"                    "1"



            "AbilityType"                "DOTA_ABILITY_TYPE_BASIC"

            "AbilityBehavior"            "DOTA_ABILITY_BEHAVIOR_PASSIVE"



            "AbilitySpecial"

            {

                "01"

                {

                    "var_type"                    "FIELD_INTEGER"

                    "bonus_attack_speed"        "15"

                }

            }

        }

code_language.lua:
Expand Collapse Copy
passive_attack_speed = class({})



LinkLuaModifier("modifier_passive_attack_speed", "heroes/passive/attack_speed", LUA_MODIFIER_MOTION_NONE)



function passive_attack_speed:GetIntrinsicModifierName()

    return "modifier_passive_attack_speed"

end



modifier_passive_attack_speed = class({})



function modifier_passive_attack_speed:IsHidden() return true end

function modifier_passive_attack_speed:IsDebuff() return false end

function modifier_passive_attack_speed:IsPurgable() return false end

function modifier_passive_attack_speed:GetAttributes() return MODIFIER_ATTRIBUTE_PERMANENT + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE end



function modifier_passive_attack_speed:DeclareFunctions()

    local funcs = {

        MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT,

    }

    return funcs

end



function modifier_passive_attack_speed:OnCreated()

    self.multiplier = self:GetAbility():GetLevelSpecialValueFor("bonus_attack_speed", 1)

    self.attack_speed_bonus = self:GetParent():GetAttackSpeed() * self.multiplier

    self:StartIntervalThink(1)

end



function modifier_passive_attack_speed:OnIntervalThink()

    self.attack_speed_bonus = (self:GetParent():GetAttackSpeed() - self.attack_speed_bonus * 0.01) * self.multiplier

end



function modifier_passive_attack_speed:GetModifierAttackSpeedBonus_Constant()

    return self.attack_speed_bonus

end

Код:
Expand Collapse Copy
        "DOTA_Tooltip_ability_passive_attack_speed"                                    "Ускорение атак"

        "DOTA_Tooltip_ability_passive_attack_speed_Description"                        "Увеличивает скорость атаки на %bonus_attack_speed%%%."

        "DOTA_Tooltip_ability_passive_attack_speed_lore"                            "Когда вы тренируетесь вы оттачиваете мастерство скорости, что позволило вам быстрее производить атаки"

Код:
Expand Collapse Copy
 "passive_fatal_wound"

        {

            "BaseClass"                    "ability_lua"

            "ScriptFile"                "heroes/passive/fatal_wound"

            "AbilityTextureName"        "specal/crit_hit"

            "MaxLevel"                    "5"



            "AbilityType"                "DOTA_ABILITY_TYPE_BASIC"

            "AbilityBehavior"            "DOTA_ABILITY_BEHAVIOR_PASSIVE"



            "AbilitySpecial"

            {

                "01"

                {

                    "var_type"                    "FIELD_FLOAT"

                    "pct_health_threshold"        "95.0"

                }

                "02"

                {

                    "var_type"                    "FIELD_FLOAT"

                    "damage_multiplier"            "100.0 200.0 300.0 400.0 500.0"

                }

            }

        }

code_language.lua:
Expand Collapse Copy
passive_fatal_wound = class({})



LinkLuaModifier("modifier_passive_fatal_wound", "heroes/passive/fatal_wound", LUA_MODIFIER_MOTION_NONE)



function passive_fatal_wound:GetIntrinsicModifierName()

    return "modifier_passive_fatal_wound"

end











modifier_passive_fatal_wound = class({})



function modifier_passive_fatal_wound:IsHidden() return true end

function modifier_passive_fatal_wound:IsDebuff() return false end

function modifier_passive_fatal_wound:IsPurgable() return false end

function modifier_passive_fatal_wound:GetAttributes() return MODIFIER_ATTRIBUTE_PERMANENT + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE end



function modifier_passive_fatal_wound:GetMultiplier(victim)

    local ability = self:GetAbility()

    local damage_multiplier = 1



    if (ability and victim:GetTeam() == ability:GetTeam()) then

        return damage_multiplier

    end



    if ability and (not ability:IsNull()) and victim:GetHealthPercent() >= ability:GetSpecialValueFor("pct_health_threshold") then

        damage_multiplier = 0.01 * ability:GetSpecialValueFor("damage_multiplier")



        local blitz_pfx = ParticleManager:CreateParticle("particles/econ/items/void_spirit/void_spirit_immortal_2021/void_spirit_immortal_2021_astral_step_dmg_blood.vpcf", PATTACH_ABSORIGIN_FOLLOW, victim)

        ParticleManager:SetParticleControl(blitz_pfx, 0, victim:GetAbsOrigin())

        ParticleManager:ReleaseParticleIndex(blitz_pfx)

    end



    return damage_multiplier

end





function modifier_passive_fatal_wound:DeclareFunctions()

    return {

        MODIFIER_PROPERTY_TOTALDAMAGEOUTGOING_PERCENTAGE,

    }

end



function modifier_passive_fatal_wound:GetModifierTotalDamageOutgoing_Percentage(params)

    local multiplier = self:GetMultiplier(params.target)

    if multiplier > 1 then

        SendOverheadEventMessage(nil, OVERHEAD_ALERT_CRITICAL, params.target, params.original_damage * multiplier, nil)

    end

    return (multiplier - 1) * 100

end

Код:
Expand Collapse Copy
        "DOTA_Tooltip_ability_passive_fatal_wound"                                "Смертельный удар"

        "DOTA_Tooltip_ability_passive_fatal_wound_Description"                    "Любой урон нанесённый врагам с высоким уровнем больше %pct_health_threshold%%% здоровья, является автоматическим %damage_multiplier%%% критом."

        "DOTA_Tooltip_ability_passive_fatal_wound_lore"                            "Оттачивая своё мастерство вы уже наперед знаете и видите все слабые места противника"

Код:
Expand Collapse Copy
"passive_armor_destroyer"

            {

                "BaseClass"                    "ability_lua"

                "ScriptFile"                "heroes/passive/armor_destroyer"

                "AbilityTextureName"        "specal/armorDebaf"

                "MaxLevel"                    "5"



                "AbilityType"                "DOTA_ABILITY_TYPE_BASIC"

                "AbilityBehavior"            "DOTA_ABILITY_BEHAVIOR_PASSIVE"



                "AbilitySpecial"

                {

                    "01"

                    {

                        "var_type"            "FIELD_FLOAT"

                        "armor_tear"        "0.2 0.5 0.8 1.0 1.3"

                    }

                }

            }

code_language.lua:
Expand Collapse Copy
passive_armor_destroyer = class({})



LinkLuaModifier("modifier_passive_armor_destroyer", "heroes/passive/armor_destroyer", LUA_MODIFIER_MOTION_NONE)

LinkLuaModifier("modifier_passive_armor_destroyer_tear", "heroes/passive/armor_destroyer", LUA_MODIFIER_MOTION_NONE)



function passive_armor_destroyer:GetIntrinsicModifierName()

    return "modifier_passive_armor_destroyer"

end





modifier_passive_armor_destroyer = class({})



function modifier_passive_armor_destroyer:IsHidden() return true end

function modifier_passive_armor_destroyer:IsDebuff() return false end

function modifier_passive_armor_destroyer:IsPurgable() return false end

function modifier_passive_armor_destroyer:GetAttributes() return MODIFIER_ATTRIBUTE_PERMANENT + MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE end



function modifier_passive_armor_destroyer:DeclareFunctions()

    if IsServer() then return { MODIFIER_PROPERTY_PROCATTACK_FEEDBACK } end

end



function modifier_passive_armor_destroyer:OnCreated()

    if IsClient() then return end



    self:GetParent():SetRangedProjectileName("particles/items_fx/desolator_projectile.vpcf")

  

end



function modifier_passive_armor_destroyer:GetModifierProcAttack_Feedback(keys)

    if keys.target:GetTeamNumber() == keys.attacker:GetTeamNumber() then return end



    keys.target:EmitSound("Item_Desolator.Target")



    local modifier_rend = keys.target:AddNewModifier(keys.attacker, self:GetAbility(), "modifier_passive_armor_destroyer_tear", {})

    if modifier_rend and not modifier_rend:IsNull() then modifier_rend:IncrementStackCount() end

end







modifier_passive_armor_destroyer_tear = class({})



function modifier_passive_armor_destroyer_tear:IsHidden() return false end

function modifier_passive_armor_destroyer_tear:IsDebuff() return true end

function modifier_passive_armor_destroyer_tear:IsPurgable() return false end

function modifier_passive_armor_destroyer_tear:GetTexture() return "specal/armorDebaf" end



function modifier_passive_armor_destroyer_tear:DeclareFunctions()

    return {

        MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS

    }

end



function modifier_passive_armor_destroyer_tear:OnCreated()

    self.armor_tear = (-1) * self:GetAbility():GetSpecialValueFor("armor_tear")



    if IsClient() then return end



    self.rend_pfx = ParticleManager:CreateParticle("particles/units/heroes/hero_monkey_king/monkey_king_jump_armor_debuff_model.vpcf", PATTACH_OVERHEAD_FOLLOW, self:GetParent())

    ParticleManager:SetParticleControlEnt(self.rend_pfx, 0, self:GetParent(), PATTACH_OVERHEAD_FOLLOW, "follow_overhead", self:GetParent():GetAbsOrigin(), false)

    ParticleManager:SetParticleControl(self.rend_pfx, 2, Vector(1,0,0))

end



function modifier_passive_armor_destroyer_tear:OnStackCountChanged()

    if self.rend_pfx then

        ParticleManager:SetParticleControl(self.rend_pfx, 2, Vector(self:GetStackCount(), 0, 0))

    end

end



function modifier_passive_armor_destroyer_tear:OnDestroy()

    if self.rend_pfx then

        ParticleManager:DestroyParticle(self.rend_pfx, false)

        ParticleManager:ReleaseParticleIndex(self.rend_pfx)

    end

end



function modifier_passive_armor_destroyer_tear:GetModifierPhysicalArmorBonus()

    return self.armor_tear * self:GetStackCount()

end



function modifier_passive_armor_destroyer_tear:OnRoundEndForTeam(keys)

    self:OnPvpEndedForDuelists(keys)

end



function modifier_passive_armor_destroyer_tear:OnPvpEndedForDuelists(keys)

    if IsClient() then return end



    self:Destroy()

end

Код:
Expand Collapse Copy
        "DOTA_Tooltip_ability_passive_armor_destroyer"                                        "Разрушитель брони"

        "DOTA_Tooltip_ability_passive_armor_destroyer_Description"                            "Ваши атаки уменьшают броню врага на %armor_tear% до конца его жизни.<br><br>Складывается бесконечно."

        "DOTA_Tooltip_ability_passive_armor_destroyer_lore"                                    "Рвать и метать... До самого конца!"

        "DOTA_Tooltip_modifier_passive_armor_destroyer_tear"                                "Броня сломана"

        "DOTA_Tooltip_modifier_passive_armor_destroyer_tear_Description"                    "Ваша броня поломана, без шанса на восстановление"
 
Взял из заброшенного RPG проекта! Убрал только лишнее в xml, js не трогал
P.S. Изменил оригинал под более простой пример/исходник через css / xml (добавлял пару Label)
изображение_2022-01-11_012757.png
Исходник прикреплен
034uLsYfPmA.jpg
 

Вложения

Назад
Сверху Снизу