И так в этой статье, я бы хотел вам рассказать и научить как создавать рандомно юнитов группами нестандартным способом - через unitpool. Не так давно ковмэн ДУОС выложил краткий обзор на этот набор апи, но толком не сказал ни чего о практическом применении. По теории: unitpool можно представить как переменную массив целоисчислительную, тоесть integer в каждой ячейке которого содержится равкод юнита которого мы хотим создать. Но преимущества unitpool'а в том что в какбы одной ячейке можно хранить несколько равкодов посредственно за счет того, что юниты могут создваться с последовательной случайностью, из этого следует что теперь можно отказаться от привычной системы вывода равкода юнита из переменной через GetRandomInt(). Вот и я решил а почему бы не переделать систему рандомного создания нейтральных крипов группами через этот удобный набор апи. Ну начну с того что во всей этой системе понадобится только одна глобальная - это хеш-таблица через которую мы будет записывать и изменять параметры unitpool'а. Для начала созданим любой триггер и переведя его в текст удалим все что находится в нем. Теперь когда наш триггер чист создадим библиотеку library так как она поможет нам нициализировать все функции. Кратко по теории: библиотека или область library/scope это какбы сказать нестандартный код карты который может находится в каком угодно триггере, при этом они могут содержать глобальные переменные и функции которые инициализируются при старте игры. Создаем библиотеку под названием "InitNeutrals"... далее напишем функцию как инициализатор билиотеки, тоесть функцию которая выполнится при чтении библиотеки, как триггер инициализации игры - который читается автоматически при старте игры.
Code
library InitNeutrals initializer InitTimer
endlibrary
Теперь напишем саму функцию-инициализатор "InitTimer" внутри библиотеки... и наполним ее данными
Code
library InitNeutrals initializer InitTimer
private functionInitTimer takes nothing returns nothing set gg_trg_ИмяВашегоТриггера = CreateTrigger() - создаст нам триггер который будет выполнять дейтсвия через период вермени call TriggerRegisterTimerEvent(gg_trg_ИмяВашегоТриггера, 50, true) - зарегистрируем событие триггера через каждые 50 секунд call TriggerAddAction(gg_trg_ИмяВашегоТриггера, function CreateRandomUnits) - добавим функцию которая будет выполняться через период времени endfunction
Code
endlibrary
Функцию "CreateRandomUnits" пока я описывать не буду так как ее работа заключается лишь в ссылке на функцию создания юнитов. Теперь получается чтобы для каждой области создать тип рандомных юнитов нужно использовать тоже кол-во unitpool'ов, сначала решил делать через массив, но оказалось легче будет просто создавать локально unitpool и просто сохранять его в хеш-таблицу для каждой области. Тогда напишем функцию которая будет создать и аттачить через хеш unitpool для каждой области. не забываем что все функции создаем внутри библиотеки.
functionAttachPool takes rect r returns nothing - функция берет в виде аргумента область rect r local unitpool up = CreateUnitPool() - создаем локальный unitpool call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up) - сохраняем в хеш локально созданный unitpool для каждой области. set up = null - оптимизация endfunction
Эту функцию "AttachPool" мы будет вызывать в триггере - инициализации карты, чтобы создать и присвоить для каждой области его unitpool.
Теперь напишем функцию "AddTypes" которая поможет нам изменять параметры unitpool'а и записыать в нее равкоды юнитов.
function AddTypes takes rect r, integer id, real times returns nothing - функция берет значения: область, рав-код, уровень слуайности. local unitpool up = LoadUnitPoolHandle(Hash, GetHandleId®, 0) - загружаем unitpool для выбранной области call UnitPoolAddUnitType(up, id, times) - добавляем рав-код в unitpool и уровень случайности call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up) - сохраняем unitpool для выбранной области в хеш-таблицу. set up = null endfunction
Не забываем то пишем функцию внутри библиотеки. И так эту функцию мы тоже будем вызывать через триггер-инициализация игры. В ней мы будем указывать такие знчения: область - в хендле которой записан его unitpool с равкодами юнита, сам рав-код выбранного юнита, "уровень случайности" - реальная которая указывает на период случайного создания юнита - чем меньше период тем больше шанс создать данного юнита. В этой системе будут использоваться уровни отличающися только на одну единицу. Про случайность: unitpool первоначально создает юнита с самым маленьким периодом случайности: тоесть если рав-код юнита обладает уровнем в 1, а другой рав-код в этом же unitpool'е обладающим уровнем в 2, будет создан следующим после первого.
И так мы еще не закончили с системой... Дальше нам надо написать саму систему по которой будут вычисляться эти "рандомные" юниты.. Напишем функцию "GetRandomUnit" которая берет аргумент область для которой сохранен unitpool и целоисчислительная которая будет показывать сколько раз нам создать рандомного юнита.
private function GetRandomUnit takes rect r, integer times returns nothing - берет область rect r, integer times local unitpool up = LoadUnitPoolHandle(Hash, GetHandleId®, 0) - загружаем из хеша unitpool if (LocalUnits®) then - условия которое оишу далее, даст нам значение true если в области отстуствуют уже крипы. Тоесть крипы убиты. loop - далее простейший цикл exitwhen times == 0 - сколько раз надо создать рандомного юнита. call PlaceRandomUnit(up, Player(PLAYER_NEUTRAL_AGGRESSIVE), GetRectCenterX®, GetRectCenterY®, 0) - создаем юнит для игрока в позиции call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up) - сохраняем уже изменившиеся параметры unitpool'а - это обязательно. set times = times - 1 endloop endif set up = null endfunction
И так эта функция будет создать нам рандомных юнитов из unitpool'а сохраненного в хеш. С выполненым условием функции "LocalUnits" которая будет проверять есть ли юниты в выбранной области... Далее о ней... Функция "LocalUnits", не смотрите что она большая, на деле ее работа не значительна.
private function LocalUnits takes rect r returns boolean - берет в виде аргумента область local group g = CreateGroup() - создаем локальную группу call GroupEnumUnitsInRect(g, r, Condition(function FilterCreeps)) - пикаем в группу юнитов через фильтр if (FirstOfGroup(g) == null) then - проверяем - есть ли в группе юниты return true - если условие выполнилось возвращаем true - тоесть юнитов в группе НЕТ. endif call DestroyGroup(g) - удаляем группу set g = null return false - иначе возвращаем false endfunction
Этот фильтр возвращает нам в группу юнитов только тех у кого здоровье больше 0. Все эти функции должны быть написаны в библиотеке. Так ну вот и подходим к концу написания системы... Теперь переходим к последней функции в системе - функции которая будет вызываться каждые 50 секунд игры чтобы создать рандомных юнитов. Функция "CreateRandomUnits" выше я уже о ней говорил, по сути является просто ссылкой на область и на функцию по созданию юнитов.
private function CreateRandomUnits takes nothing returns nothing - ни чего не берет и не возвращает call GetRandomUnit(gg_rct_ОБЛАСТЬ, 2) - вызывает функцию "GetRandomUnit" которая создаст нам рандомных юнитов. Функция ьерет область и кол-во юнитов для создания. Кол-во может быть любым от 0 до ... endfunction
private function LocalUnits takes rect r returns boolean local group g = CreateGroup() call GroupEnumUnitsInRect(g, r, Condition(function FilterCreeps)) if (FirstOfGroup(g) == null) then return true endif call DestroyGroup(g) set g = null return false endfunction
private function GetRandomUnit takes rect r, integer times returns nothing local unitpool up = LoadUnitPoolHandle(Hash, GetHandleId®, 0) if (LocalUnits®) then loop exitwhen times == 0 call PlaceRandomUnit(up, Player(PLAYER_NEUTRAL_AGGRESSIVE), GetRectCenterX®, GetRectCenterY®, 0) call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up) set times = times - 1 endloop endif set up = null endfunction
function AddTypes takes rect r, integer id, real times returns nothing local unitpool up = LoadUnitPoolHandle(Hash, GetHandleId®, 0) call UnitPoolAddUnitType(up, id, times) call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up) set up = null endfunction
function AttachPool takes rect r returns nothing local unitpool up = CreateUnitPool() call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up) set up = null endfunction
private function InitTimer takes nothing returns nothing set gg_trg_NeutralCreeps = CreateTrigger() call TriggerRegisterTimerEvent(gg_trg_NeutralCreeps, 50, true) call TriggerAddAction(gg_trg_NeutralCreeps, function CreateRandomUnits) endfunction
endlibrary
Теперь перезодим к самому создани unitpool'ов в триггере-инициализации... В инициализации необходимо делать несколько вещей... Для начала вам нужно в вызвать функцию "AttachPool" для каждой область - тоесть создать unitpool для выбранной области..
call AttachPool(gg_rct_ОБЛАСТЬ1) call AttachPool(gg_rct_ОБЛАСТЬ2) и так далее и следующее - указать рав-коды юнитов и уровень случайности для каждого из них
Пишем...
call AddTypes(gg_rct_ОБЛАСТЬ1, 'равкод1', 1) - уровень случайности 1 - тоесть первыйм создастся этот юнит call AddTypes(gg_rct_ОБЛАСТЬ1, 'равкод2', 1) - тоже самое только с другим рав-кодом.. call AddTypes(gg_rct_ОБЛАСТЬ1, 'равкод3', 2) - равкод следующего юнита для области 1 с уровенем 2 что будет означать что юнит создается вторым по последовательной случайности.
и так далее для каждой области можно создать сколько угодно рав-кодов с разной случайностью. Но если вы каждый раз регистрируете новый unitpool вы должны указать в функции "CreateRandomUnits" какую область вы включили в список создания юнитов: тоесть
private functionCreateRandomUnits takes nothing returns nothing call GetRandomUnit(gg_rct_ОБЛАСТЬ1, 2) call GetRandomUnit(gg_rct_ОБЛАСТЬ2, 3) - область 2 теперь включена в список, и можно для нее писать новые рандомные рав-коды с уровнями случайности. call GetRandomUnit(gg_rct_ОБЛАСТЬ3, 3) endfunction
Все наша система закончена полностью и готова в использованию. Удачи, всего наилучшего Lawson
Nic nie wiem bo mam chuj. редактирую посты! ВСЕ!
Сообщение отредактировал lawson - Воскресенье, 05 Февраля 2012, 19:14:41
private function GetRandomUnit takes rect r, integer times returns nothing local unitpool up = LoadUnitPoolHandle(Hash, GetHandleId®, 0) if (LocalUnits®) then loop exitwhen times == 0 call PlaceRandomUnit(up, Player(PLAYER_NEUTRAL_AGGRESSIVE), GetRectCenterX®, GetRectCenterY®, 0) call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up) set times = times - 1 endloop endif set up = null endfunction
Вот это правильно сделал. Гораздо лучше создания локалки.
Quote (lawson)
call SaveUnitPoolHandle
SaveAgentHandle
Quote (lawson)
local unitpool up = LoadUnitPoolHandle(Hash, GetHandleId®, 0) call UnitPoolAddUnitType(up, id, times) call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up) set up = null
Кратко по теории: библиотека или область library/scope это какбы сказать нестандартный код карты который может находится в каком угодно триггере, при этом они могут содержать глобальные переменные и функции которые инициализируются при старте игры.
убило, иди учи матчасть при компиляции либа переноситься под нестандартный код карты, а область остаётся на своём месте
Видимо ты обо мне совсем уж плохого мнения :| тебе достаточно будет поглядеть на мой спелл, который я выложил на хайв, чтобы увидеть там не менее длинные строки (Ник видел :)). А вообще, согласен с Ником- зачем vjass? Для новичков будет жуть как непонятно
DragoN, Я не ДУОС и не ты, я объясняю так как сам понимаю и как будет легче понять новичкам. А ты своей мат.частью мозги в кисель переводишь.
это в статье было моей, значит ты не так понимаешь и неправильно учишь новичков
Quote (SirNikolas)
над*
Библиотека (library) - отрезок кода, который будет объявлен независимо от его положения в коде сразу после объявление глобальных переменных и выше CustomScriptCode. да, извиняюсь, скосячил