Урок Спавним паки через время после смерти.

AlkY

Пользователь
4 Фев 2016
25
5
В этом маленьком гайде я расскажу как легко спавнить группы мобов через время после смерти последнего моба на споте.
ВНИМАНИЕ
Это мои первые строки кода на Lua. Любые рекомендации приветствуются.
Нам потребуется:
  • timers.lua
  • пара тестовых юнитов
  • пара info_target
Первым делом ставим на карту info_target. Делается это с помощью Entity tool(Shift + E), далее указываем класс нашей энтити(info_target), устанавливаем ее на карту и прописываем ей желаемое имя в поле Name
Подключаем timers.lua в addon_game_mode.lua
Далее нам понадобится таблица, для хранения информации о мобах в паке, где их спавнить и тд.
Пример таблицы:
Код:
packTest = {    --эта таблица хранит инфу о паке
    creeps = { npc_test = 3, npc_test_2 = 1}, --тут мы храним инфу о том кого мы спавним и в каком количестве. Имя - ключ, количество - значение.
    spawnPoint = {"pack_target_1", AbsOrigin = "" }, -- тут мы храним инфу о спавнпоинте, имя ставите такое же как указали у спавнпоинта
    isAlive = true --флаг, что пак "живой"
}
locTest = { --информация о локациях, может быть избыточна для вас
    packs = { packTest }, --информация о паках на локации
    locationLevel = 1 -- текущий уровень локации
}
map = { --хранит всю инфу об объектах на карте, может быть избыточна для вас
    locations = {  --тут мы храним все локации
        locTest
    }
}
Моя таблица избыточна, если вам что-то не нужно - упрощайте.
Далее нам понадобятся 3 функции:
  • Инитор паков. Вставит инфу о спавн поинтах:
Вызываем эту функцию, когда хотим впервые заспавнить паки.
Less:
function EFGM:initPacks()
    for i = 1, #map.locations do
        for j = 1, #map.locations[i].packs do
                map.locations[i].packs[j].spawnPoint.AbsOrigin = Entities:FindByName(nil, map.locations[i].packs[j].spawnPoint[1] ):GetAbsOrigin() --сохраняем вектор спавнпоинта, чтобы не искать каждый раз
                EFGM:SpawnPack(map.locations[i].packs[j])    --спавним пак
        end  
    end
    Timers:CreateTimer(5, --каждые 5 секунд будем чекать спавны
    function()
      EFGM:CheckPacks()
      return 5.0 -- чтобы функция запускалась циклично
    end)
end

  • Респавнер паков. Респавнит крипов в паке на нужный спавнпоинт:
Less:
function EFGM:SpawnPack(pack)
    for k,v in pairs(pack.creeps) do
                    for c = 1, v do
                        CreateUnitByName(
                        k,
                        pack.spawnPoint.AbsOrigin + RandomVector(150),
                        true,
                        nil,
                        nil,
                        DOTA_TEAM_NEUTRALS)  
                    end
                end  
    pack.isAlive = true --ставим флажок, что пак живой.
    end
  • Чекер паков. Смотрит, сколько крипочков осталось возле спавнпоинта:
Less:
function EFGM:CheckPacks()
    for i = 1, #map.locations do
        for j = 1, #map.locations[i].packs do
            if map.locations[i].packs[j].isAlive then --бегаем только по "живым" пакам
                local creepCount =  FindUnitsInRadius(DOTA_TEAM_NEUTRALS, map.locations[i].packs[j].spawnPoint.AbsOrigin ,nil, 800, 1, 2, 0, 0, false)
                -- в этой функции нам интересно ток DOTA_TEAM_ и 800. 800 - радиус поиска крипочков. По остальным параметрам - смотрите API
                if  #creepCount == 0 then
                    map.locations[i].packs[j].isAlive = false
                    Timers:CreateTimer(5, --тут вместо 5 указываем время, через которое должен реснуться пак
                        function()
                          EFGM:SpawnPack(map.locations[i].packs[j])
                    end)
                end
            end
        end
    end      
end
Чекер бегает по всем пакам и если пак "живой", то ищет крипочков вокруг него. Если не находит, то вызывает отложенную функцию спавна для этого пака и ставит флажок isAlive = false.
Зачем нужен этот флаг:
Я не очень знаю насколько быстрый Lua и API, потому думаю что каждый раз вызывать FindUnitsInRadius для каждого пака - слишком затратно.
Флаг isAlive и позволяет на время респауна скипать такие паки при проверке.
Как добавить новый пак:
Установить новый спавнпоинт
Добавить в таблицу новый пак:
Код:
packTest2 = {
    creeps = { npc_test = 1, npc_test_2 = 1},
    spawnPoint = {"pack_target_2", AbsOrigin = "" },
    isAlive = true
}
locTest = {
    packs = { packTest, packTest2},
    locationLevel = 1
}
Минус, который я нашел - крипов можно застакать, если отвести их от поинта.
Любые критика, улучшения или другие варианты решения задачи приветствуются.
Спасибо @Дикий Пёс за помощь с Lua
 
Последнее редактирование:
  • Нравится
Реакции: vulkantsk

vulkantsk

Супермодератор
Команда форума
21 Июн 2017
1,147
196
www.dotabuff.com
Проект
Roshan defense
Я читал несколько, но все они спавнили юнитов по 1ому(либо мы про разные гайды говорим).
Я ставил целью спавнить сразу группу.
Понял, тогда полезно может быть.
Для таких гайдов лучше сделать репозиторий с игровым примером, чтобы понятно как это работает.
Как я например "Шаблон Hero defense", на будущее )
 
Реклама: