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

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

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

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

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

Идем по пути: ********\steam\steamapps\common\dota 2 beta\game\dota_addons\********\scripts\vscripts\ (вместо * ваш путь), создаем тут файлик "item_drop.lua"
code_language.lua:
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) Переносите понравившуюся модель в центр сетки
если не отображается просто нажми на него
- Я добавил ландшафт, чтобы понимать, как будет смотреться предмет когда выпадет, как лут (это не обязательно - лишь наглядная демонстрация)
5) Выберите Вашу модель
если не отображается просто нажми на него
6) Нажмите в контекстном меню кнопку: File -> Export Selected
7) Введите название для Вашей модели и сохраните её по пути: \steam\steamapps\common\dota 2 beta\content\dota_addons\*\models (вместо * ваш путь)
8) Откройте в правом верхнем почти углу Tools -> Model editor
если не отображается просто нажми на него
9) В появившемся
если не отображается просто нажми на него
жмем: New VMDL From Mesh File или же сочетание клавиш "Ctrl+M" -> выбираем сохраненную ранее модель в формате "DMX" -> Появится диалоговое окно уточнения пути сохранения будущей модели -> Нажимаем OK
10) Нас встречает окно с Вашей моделью сохраненной ранее, положение модели в котором вы его экспортировали будучи на 6м шаге!
если не отображается просто нажми на него
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) Как только подогнали хитбокс
если не отображается просто нажми на него
- для более точной настройки используйте значения 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) Открылось
если не отображается просто нажми на него
, материал котого нельзя заменить, но я скажу хитрость, как оттуда взять эту самую текстуру
3) Жмем в правом окошке, где сфера, на полотно 3я кнопка и получаем нашу
если не отображается просто нажми на него
(она может быть статичной или динамичной)
3.1) Статичная - когда картинка не изменяется (показываю на этом примере)
3.2) Динамичная когда что-то переливается
4) Нехитрым способом WIN+SHIFT+S выделяем область нашей текстуры, открываем любой удобный нам редактор, я открою фотошоп
4.1) Создаю новый файл 1024х1024 - размер текстуры -
если не отображается просто нажми на него
4.2) Вставляю туда текстуру, перекрашиваю её
если не отображается просто нажми на него
4.3) Сохранив новую текстуру в формате PNG | TGA | PSD | TIF
4.4) Идем обратно в окно материалов в контекстном меню нажимаем: File -> New -> Он не даст редактировать пока не сохраним! -> File -> Save As.. -> любое название для материала
4.5) Если все сделано верно, то будут доступны функции для материалов и добавление материала, нажимаем на папку для выбора Color:
если не отображается просто нажми на него
4.6) В появившемся окне выбора текстуры вместо параметра: Images выбираем All Images и выбираем Вашу готовую текстуру
если не отображается просто нажми на него
4.7) Сохраняем Ваш материал в контекстном меню кнопка: File -> Save (ctrl+s)
4.8) Теперь нам доступен новый материал в "Asset Browser"
4.9) Идем в папку с Вашей моделью (куда Вы изначально сохранили МОДЕЛЬ.DMX)
4.10) Открываем Вашу модель.DMX редактором: Notepad ++ | Sublime text | Прочими редакторами
4.11) Ищем такую строку:
Код:
"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) Покажу лайфхак как замутить со своей наложенной готовой текстурой иконку для предмета:
если не отображается просто нажми на него

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

ПУТЬ ДЛЯ СОХРАНЕНИЯ ИКОНОК:
ДИСК:\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"
Пример исходного кода с одним кастомным предметом - мечем который я рассматривал в этом уроке:

Код:
"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:
"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 годом, вот вам господа мододелы, исходничек Lua скрипта на ограничение подбора более одного уникального предмета

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

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

code_language.lua:
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
Код:
"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:
--[[
  -- 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
Код:
"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"             "+к урону по мертвым"
    }
}





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

Спасибо за внимание :3
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
28 Июл 2018
Сообщения
551
Реакции[?]
573
Поинты[?]
160K
Добрый день господа, мододелы, вот вам небольшой сборник пассивных способностей

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

Установка в 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" "Название вашей карты на ру"

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

}

}




Код:
"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:
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


Код:
        "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 лет, а их сталь все ещё крепче любого металла!"

Код:
    "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:
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

Код:
        "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"                                "Непрерывная тренировка оттачивает оружие воина в его собственное продолжение."

Код:
"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:
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

Код:
        "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"                                "Годы медитаций позволили вам восстанавливаться гораздо быстрее чем обычный человек"

Код:
"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:
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

Код:
        "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"                            "Ваше магическое сопротивление и сопротивление эффектам снижено"

Код:
"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:
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

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

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

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

Код:
 "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:
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

Код:
        "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"                            "Оттачивая своё мастерство вы уже наперед знаете и видите все слабые места противника"

Код:
"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:
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

Код:
        "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"                    "Ваша броня поломана, без шанса на восстановление"
 
Участник
Статус
Оффлайн
Регистрация
28 Июл 2018
Сообщения
551
Реакции[?]
573
Поинты[?]
160K
Взял из заброшенного RPG проекта! Убрал только лишнее в xml, js не трогал
P.S. Изменил оригинал под более простой пример/исходник через css / xml (добавлял пару Label)
изображение_2022-01-11_012757.png
Исходник прикреплен
 

Вложения

Сверху Снизу