Сейчас 11:24:45 Пятница, 17 мая, 2024 год
[ x ] Главная ⇒ Форум ⇐ RSS Файлы Cтатьи Картинки В о й т и   или   з а р е г и с т р и р о в а т ь с я


[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Модератор форума: PUVer, SirNikolas, Ty3uK  
Форум о Warcraft 3 » Раздел для картостроителей » Раздел картостроителя » [Статья] Создания рандомных групп юнитов через unitpool. (Требования: Минимальные знания JASS.)
[Статья] Создания рандомных групп юнитов через unitpool.
lawsonДата: Воскресенье, 05 Февраля 2012, 18:41:38 | Сообщение # 1
Группа: Проверенные
Сообщений: 3482
Награды: 0
Репутация: 974
Блокировки:
И так в этой статье, я бы хотел вам рассказать и научить как создавать рандомно юнитов группами нестандартным способом - через unitpool.
Не так давно ковмэн ДУОС выложил краткий обзор на этот набор апи, но толком не сказал ни чего о практическом применении.
По теории: unitpool можно представить как переменную массив целоисчислительную, тоесть integer в каждой ячейке которого содержится равкод юнита которого мы хотим создать. Но преимущества unitpool'а в том что в какбы одной ячейке можно хранить несколько равкодов посредственно за счет того, что юниты могут создваться с последовательной случайностью, из этого следует что теперь можно отказаться от привычной системы вывода равкода юнита из переменной через GetRandomInt(). Вот и я решил а почему бы не переделать систему рандомного создания нейтральных крипов группами через этот удобный набор апи.
Ну начну с того что во всей этой системе понадобится только одна глобальная - это хеш-таблица через которую мы будет записывать и изменять параметры unitpool'а.
Для начала созданим любой триггер и переведя его в текст удалим все что находится в нем.
Теперь когда наш триггер чист создадим библиотеку library так как она поможет нам нициализировать все функции. Кратко по теории: библиотека или область library/scope это какбы сказать нестандартный код карты который может находится в каком угодно триггере, при этом они могут содержать глобальные переменные и функции которые инициализируются при старте игры.
Создаем библиотеку под названием "InitNeutrals"... далее напишем функцию как инициализатор билиотеки, тоесть функцию которая выполнится при чтении библиотеки, как триггер инициализации игры - который читается автоматически при старте игры.
Code
library InitNeutrals initializer InitTimer

endlibrary


Теперь напишем саму функцию-инициализатор "InitTimer" внутри библиотеки... и наполним ее данными
Code
library InitNeutrals initializer InitTimer


private function InitTimer 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 для каждой области. не забываем что все функции создаем внутри библиотеки.

function AttachPool 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

Сам фильтр:

private function FilterCreeps takes nothing returns boolean
return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0
endfunction

Этот фильтр возвращает нам в группу юнитов только тех у кого здоровье больше 0.
Все эти функции должны быть написаны в библиотеке.
Так ну вот и подходим к концу написания системы...
Теперь переходим к последней функции в системе - функции которая будет вызываться каждые 50 секунд игры чтобы создать рандомных юнитов.
Функция "CreateRandomUnits" выше я уже о ней говорил, по сути является просто ссылкой на область и на функцию по созданию юнитов.

private function CreateRandomUnits takes nothing returns nothing - ни чего не берет и не возвращает
call GetRandomUnit(gg_rct_ОБЛАСТЬ, 2) - вызывает функцию "GetRandomUnit" которая создаст нам рандомных юнитов. Функция ьерет область и кол-во юнитов для создания. Кол-во может быть любым от 0 до ...
endfunction

И так вот как выглядит вся система:


Теперь перезодим к самому создани 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 function CreateRandomUnits 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
 

DreiiДата: Воскресенье, 05 Февраля 2012, 18:55:31 | Сообщение # 2
10 уровень
Группа: Проверенные
Сообщений: 4991
Награды: 0
Репутация: 603
Блокировки:
Quote (lawson)
GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0

Code
GetWidgetLife(GetFilterUnit())>.405


Code
DestroyUnitPool(unitpool)

и да юнитпул лучше в глобал




Сообщение отредактировал Dreii - Воскресенье, 05 Февраля 2012, 19:11:37
 

lawsonДата: Воскресенье, 05 Февраля 2012, 19:19:11 | Сообщение # 3
Группа: Проверенные
Сообщений: 3482
Награды: 0
Репутация: 974
Блокировки:
Quote (Dreii)
юнитпул лучше в глобал

Для каждой области создаются новые равкоды, поэтому глобалка не подходит.

Добавлено (05 Февраль 2012, 19:19:11)
---------------------------------------------
Quote (Dreii)
DestroyUnitPool

Ну читай ты внимательней зачем мне дестрой там?


Nic nie wiem bo mam chuj.
редактирую посты! ВСЕ!


Сообщение отредактировал lawson - Воскресенье, 05 Февраля 2012, 19:30:10
 

DreiiДата: Воскресенье, 05 Февраля 2012, 19:26:54 | Сообщение # 4
10 уровень
Группа: Проверенные
Сообщений: 4991
Награды: 0
Репутация: 603
Блокировки:
Code
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


 

lawsonДата: Воскресенье, 05 Февраля 2012, 19:29:49 | Сообщение # 5
Группа: Проверенные
Сообщений: 3482
Награды: 0
Репутация: 974
Блокировки:
Dreii, Не понял намек.
Quote (lawson)
зачем мне дестрой там?


Nic nie wiem bo mam chuj.
редактирую посты! ВСЕ!
 

SirNikolasДата: Воскресенье, 05 Февраля 2012, 20:25:40 | Сообщение # 6
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
Quote (lawson)
Condition(function FilterCreeps)
Filter
Quote (lawson)
if (FirstOfGroup(g) == null) then
return true
Уничтожать и обнулять группу все равно надо.
Quote (lawson)
loop
exitwhen times == 0
Вот это правильно сделал. Гораздо лучше создания локалки.
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
call UnitPoolAddUnitType(LoadUnitPoolHandle(Hash, GetHandleId®, 0), id, times)
Quote (lawson)
call GetRandomUnit(gg_rct_NC1, 2)
Что за глобальный rect?
Quote (lawson)
local unitpool up = CreateUnitPool()
call SaveUnitPoolHandle(Hash, GetHandleId®, 0, up)
set up = null
call SaveAgentHandle(Hash, GetHandleId®, 0, CreateUnitPool())
Quote (lawson)
set gg_trg_NeutralCreeps = CreateTrigger()
call TriggerRegisterTimerEvent(gg_trg_NeutralCreeps, 50, true)
call TriggerAddAction(gg_trg_NeutralCreeps, function CreateRandomUnits)
call TimerStart(CreateTimer, 50., true, function CreateRandomUnits)

Из-за отсутствия знаков препинания статью дочитать не смог.
lawson, один вопрос: зачем ты грузишь читателей vJASS'ом?


 

lawsonДата: Воскресенье, 05 Февраля 2012, 22:53:15 | Сообщение # 7
Группа: Проверенные
Сообщений: 3482
Награды: 0
Репутация: 974
Блокировки:
Quote (SirNikolas)
SaveAgentHandle

Эт уже чисто придирки, от этого работа системы не изменится.
Quote (SirNikolas)
call UnitPoolAddUnitType(LoadUnitPoolHandle(Hash, GetHandleId®, 0), id, times)
Ага, чтоб меня Тузик затролил почему не зписываю все в переменные. Сам любитель делать как можно больше в одной строке.
Quote (SirNikolas)
call SaveAgentHandle(Hash, GetHandleId®, 0, CreateUnitPool())

Спасибо, действительно проще.
Quote (SirNikolas)
call TimerStart

Мне до сути всеравно, просто чтобы глобальный триггер без дела не сидел, зарегистрировал на него событие.
Quote (SirNikolas)
зачем ты грузишь читателей vJASS'ом?

Это какбы сказать обучающая статья, а с синтаксисом сЖасса не очень дружу.
Слишком сложно думаешь?


Nic nie wiem bo mam chuj.
редактирую посты! ВСЕ!


Сообщение отредактировал lawson - Воскресенье, 05 Февраля 2012, 22:55:56
 

DragoNДата: Воскресенье, 05 Февраля 2012, 23:23:26 | Сообщение # 8
Инквизитор
Группа: Стримеры
Сообщений: 4348
Награды: 7
Репутация: 2776
Блокировки:
Quote (lawson)
Кратко по теории: библиотека или область library/scope это какбы сказать нестандартный код карты который может находится в каком угодно триггере, при этом они могут содержать глобальные переменные и функции которые инициализируются при старте игры.

убило, иди учи матчасть
при компиляции либа переноситься под нестандартный код карты, а область остаётся на своём месте


El Psy Congroo
 

lawsonДата: Понедельник, 06 Февраля 2012, 01:29:28 | Сообщение # 9
Группа: Проверенные
Сообщений: 3482
Награды: 0
Репутация: 974
Блокировки:
Quote (DragoN)
убило, иди учи матчасть

DragoN, Я не ДУОС и не ты, я объясняю так как сам понимаю и как будет легче понять новичкам. А ты своей мат.частью мозги в кисель переводишь.

Добавлено (06 Февраль 2012, 01:29:28)
---------------------------------------------
Quote (DragoN)
а область остаётся на своём месте

Я знаю что область остается на своем месте и то что библиотеки могут содержать области, спасибо за уточнение.


Nic nie wiem bo mam chuj.
редактирую посты! ВСЕ!


Сообщение отредактировал lawson - Понедельник, 06 Февраля 2012, 01:35:18
 

Ty3uKДата: Понедельник, 06 Февраля 2012, 08:19:49 | Сообщение # 10
Группа: Ветераны
Сообщений: 6125
Награды: 2
Репутация: 1617
Блокировки:
Видимо ты обо мне совсем уж плохого мнения :| тебе достаточно будет поглядеть на мой спелл, который я выложил на хайв, чтобы увидеть там не менее длинные строки (Ник видел :)). А вообще, согласен с Ником- зачем vjass? Для новичков будет жуть как непонятно

╭∩╮(︶︿︶)╭∩╮
"Ульта Тайда мне в жопу!" © k0fe1n
Статьи: MUI-1|MUI-2|Шрифт
Полезности: JASP|JNGP|Уголок библиотек
 

SirNikolasДата: Понедельник, 06 Февраля 2012, 09:36:30 | Сообщение # 11
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
Quote (lawson)
Ага, чтоб меня Тузик затроллил, почему не записываю все в переменные. Сам любитель делать как можно больше в одной строке.
Все, что ты занес в переменные, используется только один раз, следовательно, переменные не нужны.
Quote (DragoN)
убило
+1. Забыл написать.
Quote (DragoN)
при компиляции либа переносится под нестандартный код карты
над*
Quote (lawson)
Мне по сути все равно, просто чтобы глобальный триггер без дела не сидел, зарегистрировал на него событие.
Создается больше объектов, а триггер еще и памяти побольше требует.
P. S. С помощью cJASS можно удалить триггер:
Code
define <trigger gg_trg_NeutralCreeps = null>


 

DragoNДата: Понедельник, 06 Февраля 2012, 14:38:44 | Сообщение # 12
Инквизитор
Группа: Стримеры
Сообщений: 4348
Награды: 7
Репутация: 2776
Блокировки:
Quote (lawson)

DragoN, Я не ДУОС и не ты, я объясняю так как сам понимаю и как будет легче понять новичкам. А ты своей мат.частью мозги в кисель переводишь.

это в статье было моей, значит ты не так понимаешь и неправильно учишь новичков
Quote (SirNikolas)
над*

Библиотека (library) - отрезок кода, который будет объявлен независимо от его положения в коде сразу после объявление глобальных переменных и выше CustomScriptCode.
да, извиняюсь, скосячил


El Psy Congroo
 

Prokhor-andrewДата: Воскресенье, 08 Апреля 2012, 21:56:28 | Сообщение # 13
6 уровень
Группа: Пользователи
Сообщений: 215
Награды: 0
Репутация: 0
Блокировки:
Я НОВИЧОК, И Я ЗНАЯ ДЖАЗЗ НА НАЧАЛЬНОМ УРОВНЕ НИФИГА НЕ ПОНЯЛ. а вы говорите что статья для новичков?
Как мне вот щас что то сдесь понять?


(-_-)
 

DreiiДата: Воскресенье, 08 Апреля 2012, 23:13:03 | Сообщение # 14
10 уровень
Группа: Проверенные
Сообщений: 4991
Награды: 0
Репутация: 603
Блокировки:
Quote (Prokhor-andrew)
Я НОВИЧОК, И Я ЗНАЯ ДЖАЗЗ НА НАЧАЛЬНОМ УРОВНЕ НИФИГА НЕ ПОНЯЛ. а вы говорите что статья для новичков? Как мне вот щас что то сдесь понять?

Вернись в школу.


 

Форум о Warcraft 3 » Раздел для картостроителей » Раздел картостроителя » [Статья] Создания рандомных групп юнитов через unitpool. (Требования: Минимальные знания JASS.)
  • Страница 1 из 1
  • 1
Поиск:

Copyright © 2006 - 2024 Warcraft3FT.info При копировании материалов c сайта ставьте, пожалуйста, активную обратную ссылку на нас • Design by gReeB04ki ©
Хостинг от uCoz