Всего на сайте: 17
Гостей: 17
Пользователей: 0




Скачать Dota Allstars:
DotaПоследняя версия карты
DotA Allstars v6.72f
[ Дота 6.72f Скачать(Ru) ]




База Знаний:



Новые Файлы на Сайте:



Последнии Темы на Форуме:


Меню сайта

Реклама


Купить Рекламное Место

Мини-чат

Поиск

Сейчас On-Line




Наш Баннер
Код кнопки:
 




Главная » Статьи » База Знаний

Система Super Custom Value (SCV) или RB+cache

13. Система Super Custom Value (SCV) или RB+cache

Читатель, мы вплотную подошли к системе SCV. Эта система, которая позволяет сопоставлять ЛЮБОМУ игровому объекту - либо другой объект, либо какое-то значение (или даже массив). Наподобие custom value, но значительно более универсальная. Значение этой системы трудно переоценить. Фактически, она позволяет упростить решение огромного множества задач, избавиться от глобальных переменных и создавать так называемые кешь-переменные прямо во время игры.

С чего тут начать. Пожалуй, с Кеша. Существует такая замечательная вещь, называемая кешь. Программисты называет такие структуры - ассоциативный массив. Кешь в war3 - это особый двумерный массив, в котором в качестве аргументов используются строки. Т.е. вводишь аргументами 2 строки, им сопоставляется значение. Можно сопоставить значение типа integer, типа real, типа string и типа boolean.
Как жаль, что в этот массив нельзя записать ссылку на юниты, предметы, способности и т.п. Стоп, а действительно ли нельзя? Или все таки можно?

Ссылку может и нельзя, но давай вспоминать, что мы узнали про RB. Каждому игровому объекту соответствует уникальный номер, число типа integer. Это число можно найти, и по этому числу можно найти объект. А ведь число типа integer может быть записано в кешь!

(*) Итак, если мы используем кешь не для переброски данных, а для хранения информации, то в качестве хранимой информации кешь способен записать указатели (номера) объектов.

Это первый важный вывод. А теперь подумаем, если мы в кешь можем сохранять объекты, можем ли мы при помощи кешь сопоставить какому-то игровому объекту какое-то значение? Игровой объект имеет свой уникальный номер. Номер есть число, но специальные функции позволяют перевести его в строку.

(**)Договоримся, если мы хотим сопоставить игровому объекту значение в кешь, то в качестве первого аргумента записи будем использовать уникальный номер этого объекта, переведенный в строку.

(***)Что касается второго аргумента кешь, то мы можем использовать его, чтобы дать нашему сопоставлению уникальное имя.

Сопоставь факты, отмеченные выше, и ты поймешь идею SCV.

Рассмотрим функцию вида:
function set_object_iparam takes handle h, string key, integer val returns nothing
call StoreInteger(udg_cache, I2S(H2I(h)), key, val)
endfunction

Эта функция предназначена, чтобы сопоставлять любому объекту параметр типа integer. Аргументами выступает ссылка на объект handle h, строка key - имя сопоставления и переменная val типа integer - это число, которое мы сопоставляем объекту.
udg_cache - это переменная типа кешь - специальный кешь-файл создается в самом начале игры.
В функции единственное действие:
call StoreInteger(udg_cache, I2S(H2I(h)), key, val) 

Это обычная команда занести значение в кешь.

Для записи в кешь, нудно передать 2 строки-аргумента. Первая строка:
I2S(H2I(h)) 


Разберемся подробнее. Здесь написана функция внутри функции. H2I(h) - мы уже рассмотрели выше. Она вернет номер для объекта, переданного через переменную h. Вторая функция I2S(...) - это обычная варкрафтовская функция перевода числа в строку. Итак, вся конструкция в целом приведет к тому, что первая строка - это переведенный в текст уникальный номер объекта.
Вторая строка key - это строка, которую заполняет сам пользователь, давая имя сопоставлению. Параметр для записи val.

Итак, если у тебя есть юнит u и ему нужно сопоставить число 10, то можно использовать команду:
call set_object_iparam(u, "int", 10) 

имя сопоставления "int".

Отлично! Как делать запись мы выяснили. А можно ли эту запись прочитать обратно? Да! Во-первых, для удобства создадим вторую функцию:
function get_object_iparam takes handle h, string key returns integer
return GetStoredInteger(udg_cache, I2S(H2I(h)), key)
endfunction

Она похожа по структуре на предыдущую, только аргументов на один меньше. Это потому, что функция нужна не для записи значения в кешь, а для чтения значения из кеша.
return GetStoredInteger(udg_cache, I2S(H2I(h)), key) 


Т.е. наша функция вернет значение выражения GetStoredInteger(udg_cache, I2S(H2I(h)), key) . А что это за выражение? Стандартная функция для чтения из кеша. В качестве первой строки указывается уникальный номер объекта, переведенный в строку. Вторая строка - определена пользователем.

Итак, если мы хотим узнать, что записано в записи кеша "int" для юнита u, используем команду:
set i = get_object_iparam(u, "int")


Т.е. можно и записывать значения и читать их. Читатель, не замечаешь чего-то общего между нашими сопоставлениями и custom value? По сути, custom value - это тоже сопоставление, но менее универсальное, т.к. можно сопоставлять юнитам (и только юнитам) одно (и только одно) значение типа integer. А при помощи SCV можно сопоставить что угодно и чему угодно. Поэтому я называл эту систему Super Custom Value (SCV) , а сопоставления-записи - для краткости cv.

А как сопоставить юниту u - другой юнит u2? Очень просто.
call set_object_iparam(u, "int", H2I(u2)) 


Мы записали в параметр "int" уникальный номер u2.

Этот номер мы можем прочесть обратно. Проблема лишь в том, как при помощи этого номера получить ссылку обратно на u2. Для этого в SCV есть специальные функции.
function I2U takes integer i returns unit
return i
return null
endfunction

и
function get_object_uparam takes handle h, string key returns unit
return I2U(GetStoredInteger(udg_cache, I2S(H2I(h)), key))
endfunction

Первая функция по уникальному номеру возвращает сам юнит, вторая сделана для простоты - она читает уникальный номер из записи в кеше и при помощи первой функции возвращает ссылку на этот юнит.
Так что, если нужно прочесть какой юнит записан в cv "int" для юнита u, используем команду
set u2 = get_object_uparam(u, "int")


Вот и все. Остальное все по аналогии. Есть и другие функции для сопоставления чисел real, строк, флагов boolean. Есть функции для нахождения не только юнитов по их номеру, но и других объектов - точек, регионов, спецэффектов и др.

Есть правда еще одна функция
function flush_object takes handle h returns nothing
call FlushStoredMission(udg_cache, I2S(H2I(h)))
endfunction

- она позволяет быстро отчистить все записи кеша, относящиеся к какому-то объекту.
Скажем, собираешься ты удалить юнит u. Для того, чтобы cv этого объекта не занимали место в памяти, когда объекта уже нет, пишешь команду:
call flush_object(u) 

Все эти функции в сумме вмещаются на 1-1.5 экрана. Переносить систему из сценария в сценарий - элементарно. Просто копируем код, создаем переменную cache и при событии Map Initizlization создаем кешь-файл.

Читатель, попробуй представить себе все возможные способы применения SCV. Вспомни примеры, которые мы рассмотрели ранее. Может быть есть способ что-то сделать проще, быстрее и надежнее ? ;)

Когда ДимонТ выпустил систему, я разработал по ней небольшой обучающий сценарий, который демонстрирует ее возможности, в том числе создание переменных и массивов cv. Я хочу, чтобы ты подробно изучил этот сценарий.

Освоив SCV ты поднимешься на следующую ступень мастерства.

14. Да здравствует SCV!

Рассмотрим один из наших старых примеров – полет юнита снаряда. Можно ли улучшить его при помощи SCV? Раньше нам приходилось использовать массивы, чтобы сохранить информацию, что такой-то юнит-снаряд летит к такой-то цели и имеет такой-то уровень заклинания. Теперь мы можем сопоставить эти данные непосредственно юниту-снаряду при помощи SCV. Т.е. записать все необходимые данные в cv. А как нам сделать периодический цикл по всем юнитам снарядам, чтобы сдвигать их? О, тут у нас появляются новые интересные возможности. Мы можем для каждого юнита-снаряда создать отдельный триггер с периодом 0.05, отвечающий за его передвижения к цели.
Ну допустим, мы создали триггер с событием Периодическое 0.05. А как прописать, что этот триггер должен работать только для определенного юнита-снаряда? Очень просто, мы сопоставим триггеру (триггер ведь тоже игровой объект!) нужный нам юнит-снаряд. И при запуске триггера сможем определить, что нужно двигать такой-то юнит-снаряд.

В целом система организации движения юнита-снаряда становится довольно простой. На основе этого принципа я сделал несколько геройских заклинаний - предлагаю тебе ознакомиться с ними. К примеру, герой Лорд Хаоса. Заклинания Звездный конус, Групповой файербол и Сфера Хаоса сделаны таким способом. Это открывает широчайшие возможности по созданию триггерных заклинаний любой сложности.

Рекомендую глянуть примеры подобных наработок здесь:
- наработка Димона: герой Seal master
- моя наработка: герой Еретик
- моя наработка: герой Лорд Хаоса

Кстати, огромное достоинство системы SCV, что ее можно легко дополнить. Допустим, нам нужно чтобы объектам можно было сопоставлять триггеры и таймеры. К функциям SCV добавим новые:
function I2Tm takes integer i returns timer
return i
return null
endfunction

function I2Tr takes integer i returns trigger
return i
return null
endfunction

и еще две
function get_object_tmparam takes handle h, string key returns timer
return I2Tm(GetStoredInteger(udg_cache, I2S(H2I(h)), key))
endfunction

function get_object_trparam takes handle h, string key returns trigger
return I2Tr(GetStoredInteger(udg_cache, I2S(H2I(h)), key))
endfunction

Вот и все.

Автор системы SCV DimonT написал про нее отдельную статью, которую можно посмотреть на нашем сайте.
прикрепление: SCV.w3x (27 kb) Описание:

13. Система Super Custom Value (SCV) или RB+cache

Читатель, мы вплотную подошли к системе SCV. Эта система, которая позволяет сопоставлять ЛЮБОМУ игровому объекту - либо другой объект, либо какое-то значение (или даже массив). Наподобие custom value, но значительно более универсальная. Значение этой системы трудно переоценить. Фактически, она позволяет упростить решение огромного множества задач, избавиться от глобальных переменных и создавать так называемые кешь-переменные прямо во время игры.

С чего тут начать. Пожалуй, с Кеша. Существует такая замечательная вещь, называемая кешь. Программисты называет такие структуры - ассоциативный массив. Кешь в war3 - это особый двумерный массив, в котором в качестве аргументов используются строки. Т.е. вводишь аргументами 2 строки, им сопоставляется значение. Можно сопоставить значение типа integer, типа real, типа string и типа boolean.
Как жаль, что в этот массив нельзя записать ссылку на юниты, предметы, способности и т.п. Стоп, а действительно ли нельзя? Или все таки можно?

Ссылку может и нельзя, но давай вспоминать, что мы узнали про RB. Каждому игровому объекту соответствует уникальный номер, число типа integer. Это число можно найти, и по этому числу можно найти объект. А ведь число типа integer может быть записано в кешь!

(*) Итак, если мы используем кешь не для переброски данных, а для хранения информации, то в качестве хранимой информации кешь способен записать указатели (номера) объектов.

Это первый важный вывод. А теперь подумаем, если мы в кешь можем сохранять объекты, можем ли мы при помощи кешь сопоставить какому-то игровому объекту какое-то значение? Игровой объект имеет свой уникальный номер. Номер есть число, но специальные функции позволяют перевести его в строку.

(**)Договоримся, если мы хотим сопоставить игровому объекту значение в кешь, то в качестве первого аргумента записи будем использовать уникальный номер этого объекта, переведенный в строку.

(***)Что касается второго аргумента кешь, то мы можем использовать его, чтобы дать нашему сопоставлению уникальное имя.

Сопоставь факты, отмеченные выше, и ты поймешь идею SCV.

Рассмотрим функцию вида:
function set_object_iparam takes handle h, string key, integer val returns nothing
call StoreInteger(udg_cache, I2S(H2I(h)), key, val)
endfunction

Эта функция предназначена, чтобы сопоставлять любому объекту параметр типа integer. Аргументами выступает ссылка на объект handle h, строка key - имя сопоставления и переменная val типа integer - это число, которое мы сопоставляем объекту.
udg_cache - это переменная типа кешь - специальный кешь-файл создается в самом начале игры.
В функции единственное действие:
call StoreInteger(udg_cache, I2S(H2I(h)), key, val) 

Это обычная команда занести значение в кешь.

Для записи в кешь, нудно передать 2 строки-аргумента. Первая строка:
I2S(H2I(h)) 


Разберемся подробнее. Здесь написана функция внутри функции. H2I(h) - мы уже рассмотрели выше. Она вернет номер для объекта, переданного через переменную h. Вторая функция I2S(...) - это обычная варкрафтовская функция перевода числа в строку. Итак, вся конструкция в целом приведет к тому, что первая строка - это переведенный в текст уникальный номер объекта.
Вторая строка key - это строка, которую заполняет сам пользователь, давая имя сопоставлению. Параметр для записи val.

Итак, если у тебя есть юнит u и ему нужно сопоставить число 10, то можно использовать команду:
call set_object_iparam(u, "int", 10) 

имя сопоставления "int".

Отлично! Как делать запись мы выяснили. А можно ли эту запись прочитать обратно? Да! Во-первых, для удобства создадим вторую функцию:
function get_object_iparam takes handle h, string key returns integer
return GetStoredInteger(udg_cache, I2S(H2I(h)), key)
endfunction

Она похожа по структуре на предыдущую, только аргументов на один меньше. Это потому, что функция нужна не для записи значения в кешь, а для чтения значения из кеша.
return GetStoredInteger(udg_cache, I2S(H2I(h)), key) 


Т.е. наша функция вернет значение выражения GetStoredInteger(udg_cache, I2S(H2I(h)), key) . А что это за выражение? Стандартная функция для чтения из кеша. В качестве первой строки указывается уникальный номер объекта, переведенный в строку. Вторая строка - определена пользователем.

Итак, если мы хотим узнать, что записано в записи кеша "int" для юнита u, используем команду:
set i = get_object_iparam(u, "int")


Т.е. можно и записывать значения и читать их. Читатель, не замечаешь чего-то общего между нашими сопоставлениями и custom value? По сути, custom value - это тоже сопоставление, но менее универсальное, т.к. можно сопоставлять юнитам (и только юнитам) одно (и только одно) значение типа integer. А при помощи SCV можно сопоставить что угодно и чему угодно. Поэтому я называл эту систему Super Custom Value (SCV) , а сопоставления-записи - для краткости cv.

А как сопоставить юниту u - другой юнит u2? Очень просто.
call set_object_iparam(u, "int", H2I(u2)) 


Мы записали в параметр "int" уникальный номер u2.

Этот номер мы можем прочесть обратно. Проблема лишь в том, как при помощи этого номера получить ссылку обратно на u2. Для этого в SCV есть специальные функции.
function I2U takes integer i returns unit
return i
return null
endfunction

и
function get_object_uparam takes handle h, string key returns unit
return I2U(GetStoredInteger(udg_cache, I2S(H2I(h)), key))
endfunction

Первая функция по уникальному номеру возвращает сам юнит, вторая сделана для простоты - она читает уникальный номер из записи в кеше и при помощи первой функции возвращает ссылку на этот юнит.
Так что, если нужно прочесть какой юнит записан в cv "int" для юнита u, используем команду
set u2 = get_object_uparam(u, "int")


Вот и все. Остальное все по аналогии. Есть и другие функции для сопоставления чисел real, строк, флагов boolean. Есть функции для нахождения не только юнитов по их номеру, но и других объектов - точек, регионов, спецэффектов и др.

Есть правда еще одна функция
function flush_object takes handle h returns nothing
call FlushStoredMission(udg_cache, I2S(H2I(h)))
endfunction

- она позволяет быстро отчистить все записи кеша, относящиеся к какому-то объекту.
Скажем, собираешься ты удалить юнит u. Для того, чтобы cv этого объекта не занимали место в памяти, когда объекта уже нет, пишешь команду:
call flush_object(u) 

Все эти функции в сумме вмещаются на 1-1.5 экрана. Переносить систему из сценария в сценарий - элементарно. Просто копируем код, создаем переменную cache и при событии Map Initizlization создаем кешь-файл.

Читатель, попробуй представить себе все возможные способы применения SCV. Вспомни примеры, которые мы рассмотрели ранее. Может быть есть способ что-то сделать проще, быстрее и надежнее ? ;)

Когда ДимонТ выпустил систему, я разработал по ней небольшой обучающий сценарий, который демонстрирует ее возможности, в том числе создание переменных и массивов cv. Я хочу, чтобы ты подробно изучил этот сценарий.

Освоив SCV ты поднимешься на следующую ступень мастерства.

14. Да здравствует SCV!

Рассмотрим один из наших старых примеров – полет юнита снаряда. Можно ли улучшить его при помощи SCV? Раньше нам приходилось использовать массивы, чтобы сохранить информацию, что такой-то юнит-снаряд летит к такой-то цели и имеет такой-то уровень заклинания. Теперь мы можем сопоставить эти данные непосредственно юниту-снаряду при помощи SCV. Т.е. записать все необходимые данные в cv. А как нам сделать периодический цикл по всем юнитам снарядам, чтобы сдвигать их? О, тут у нас появляются новые интересные возможности. Мы можем для каждого юнита-снаряда создать отдельный триггер с периодом 0.05, отвечающий за его передвижения к цели.
Ну допустим, мы создали триггер с событием Периодическое 0.05. А как прописать, что этот триггер должен работать только для определенного юнита-снаряда? Очень просто, мы сопоставим триггеру (триггер ведь тоже игровой объект!) нужный нам юнит-снаряд. И при запуске триггера сможем определить, что нужно двигать такой-то юнит-снаряд.

В целом система организации движения юнита-снаряда становится довольно простой. На основе этого принципа я сделал несколько геройских заклинаний - предлагаю тебе ознакомиться с ними. К примеру, герой Лорд Хаоса. Заклинания Звездный конус, Групповой файербол и Сфера Хаоса сделаны таким способом. Это открывает широчайшие возможности по созданию триггерных заклинаний любой сложности.

Рекомендую глянуть примеры подобных наработок здесь:
- наработка Димона: герой Seal master
- моя наработка: герой Еретик
- моя наработка: герой Лорд Хаоса

Кстати, огромное достоинство системы SCV, что ее можно легко дополнить. Допустим, нам нужно чтобы объектам можно было сопоставлять триггеры и таймеры. К функциям SCV добавим новые:
function I2Tm takes integer i returns timer
return i
return null
endfunction

function I2Tr takes integer i returns trigger
return i
return null
endfunction

и еще две
function get_object_tmparam takes handle h, string key returns timer
return I2Tm(GetStoredInteger(udg_cache, I2S(H2I(h)), key))
endfunction

function get_object_trparam takes handle h, string key returns trigger
return I2Tr(GetStoredInteger(udg_cache, I2S(H2I(h)), key))
endfunction

Вот и все.

Автор системы SCV DimonT написал про нее отдельную статью, которую можно посмотреть на нашем сайте.
прикрепление: SCV.w3x (27 kb)

Источник: http://xgm.ru
Категория: База Знаний | Добавил: Kapitan_Morgan (07/Август/2008)
Просмотров: 3024 | Рейтинг: 0.0/0 | Сказать автору

Всего комментариев: 2
0  
2 Sesaru     (07/Июнь/2009 16:27)
полезная весч )

0  
1 kroll_slevin     (03/Май/2009 19:07)
мдам.......... huh mamba wacko

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа
Логин:
Пароль:

Реклама


Купить Рекламное Место

Случайные Обои

Случайные Файлы

Друзья Сайта

Добавить в друзья ICQ 474-682-630

Статистика
Счетчик тИЦ и PR

Наш опрос
Сколько вам лет?
Всего ответов: 2554


Copyright WC3Gamer © 2008-2010 Сообщество WarCraft 3 | Dota Allstars | Battle.net | Garena | Карты | Хаки | Новости | Гайды | Патчи | Хостинг от uCoz Все Права Защищены.
Полное или частичное использование материалов сайта www.WC3Gamer.com возможно только с установленной прямой ссылки на источник.