Сейчас 14:57:52 Среда, 18 декабря, 2024 год
[ x ] Главная ⇒ Форум ⇐ RSS Файлы Cтатьи Картинки В о й т и   или   з а р е г и с т р и р о в а т ь с я


[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Модератор форума: PUVer, SirNikolas, Ty3uK  
Триггерные заклинания посредством Jass
DuosoraДата: Пятница, 15 Марта 2013, 15:00:13 | Сообщение # 1
The cats never sleep...
Группа: Ветераны
Сообщений: 6734
Награды: 10
Репутация: 2161
Блокировки:

Статья рассчитана на новичков в Jass, которые хотели бы научиться создавать триггерные заклинания.
Если вы не знакомы с Jass'ом, рекомендую ознакомиться с данным материалом.
Начнём с теории.
Также не помешает ознакомление с данным материалом.

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

Прежде всего нужно продумать наше заклинание. Какие юниты нужны для его исполнения, может быть, стоит создать dummy (опишу их позже) для наложения заклинаний, придумать описание. Лично я сначала описываю заклинание в редакторе объектов, то есть создаю нестандартную способность, заполняю описание, требования и всё в этом духе, а уже потом приступаю к созданию триггеров и прочего.

Вроде, всё ясно? Придумали сложное заклинание, создали способность (рекомендую делать на основе способности Канал, у которой нет побочных эффектов)? Самое время приступить к триггерам.

Для примера создадим триггерное заклинание, которое бы при выборе цели испускало в неё молнию и отскакивало на других врагов, как Chain Lighting, создавая рядом с поражёнными врагами их клонов, атакующих их, причём клоны брали бы часть здоровья монстра (пример: у монстра с 500 хп станет 400 хп и появится клон с 100 хп), а по происшествию некоторого времени клоны бы исчезали, возвращая их жизнь монстрам, если и первые и вторые живы.
Звучит сложно, но зато мы много чему научимся.
Далее будет следовать код на Jass2 (стандартный jass, не vJass/cJass). Для комфортного написания кода, очень рекомендую установить JNGP, так как без него печатать код, по моему скромному мнению, невозможно.
Чтобы не нарушить читаемость статьи, картинки буду класть под спойлеры. Чтобы не возникало массы вопросов, разжую всё, начиная с установки JNGP.
1. Ставим Jass New Gen Pack 5d (не обязательно)
В этой части будет описана загрузка JNGP



2. Приступая к делу
В этой части мы создадим условия для успешного теста нашей способности.
Делаем, как на картинках:


3. Способность в Р.О.
В этой части мы создадим нашу способность в редакторе объектов.
Примечание: На картинках изменялась стандартная способность Канал, в то время, т.к. таких способностей может быть много, рекомендуется создавать нестандартную способность на основе канала и менять её.
Делаем как на картинках:


4. Триггеры
В этой части мы приступим к триггерам: создадим молнии и добавим звуковой эффект
Тут будет уже более подробное описание


5. Триггеры, часть вторая
В этой части мы создадим клонов и всё что с ними связано.
[spoiler=Спойлер]У нас на руках код из предыдущей части и мы начинаем модифицировать его.
Для начала нам нужно создать рядом с каждым врагом его клона.
Добавим новую переменную u2 типа unit:

Теперь будем с каждым врагом создавать клона.
Создаём клона для первой цели:

И для 3-ёх последующих:

Если вам не ясна строка
Код
call SetUnitVertexColor(u2, 155, 15, 155, 155)

То я объясню: она изменяет отображение модели юнита, причём первый аргумент (u2) - юнит, второй, третий и четвёртый (155, 15, 155) - значения красного, зелёного и синего цветов соответственно, а последний (155) - прозрачность (а точнее, непрозрачность).
Цифровые аргументы располагаются в диапазоне от 0 до 255, то есть 0 - это 0% красного/синего/зеленого/непрозрачности (100% прозрачности), а 255 - наоборот, полностью красный/зелёный/синий/непрозрачный.
Чтобы это понять, я покажу, как это действует:
Если все аргументы, кроме красного и непрозрачности, выдать 0-ми, а первые - 255-ми, мы увидим полностью красного юнита, так как другие цвета пикселей умножены на 0%, и остался только красный:

А в нашем случае:
Код
call SetUnitVertexColor(u2, 155, 15, 155, 155)

Получится вот что:

Но вы можете сделать его серым или ещё каким-то, поэкспериментировав с аргументами (если кто не знает, аргументы - это переменные или значения, передаваемые в функцию между круглых скобок).

Добавлено (15 Марта 2013, 15:00:13)
---------------------------------------------
Теперь, если запустить карту, вот что мы увидим:

На первый взгляд всё хорошо, всё сработало, жизни, я вас уверяю, распределились как нужно.
Но важно протестировать код со всех сторон, для этого, давайте пересмотрим наш алгоритм:
1. Выбирается цель заклинания
2. К ней идёт молния, и рядом с целью создаётся её клон
3. В цикле 3 раза выбирается группа юнитов вокруг цели, которая подходит в качестве цели, один из критериев отбора - юниты, уже выбранные как цели, и в эту группу наша первая цель не включается.
Проверим это допущение в деле, применим молнию на 1-го юнита. Как думаете, что произойдёт? Создастся 1 клон, скажут невнимательные/недогадливые читатели.


А вот и нет, создадутся 2 клона, так как в цикле следующей целью будет выбрана цель заклинания, ведь она подходит по всем параметрам, для исправления этого добавим нашу первую цель в группу выбранных врагов.

Запускаем ещё раз:

Теперь всё хорошо, осталось позаботится о своевременном удалении клонов и возвращении остатков здоровья.
Тут нам понадобится воспользоваться хэш-таблицей для сохранения клонов и их целей, а также ещё один таймер.
Разумеется можно не городить на 1 таймер 4 клона и 4 цели, а создать 4 таймера на одинаковое время и рпивязать к каждому своего клона и цель, но зачем, если время исчезновения одинаково?
Итак, новые переменные: таймер t2 и целочисленная id2.

Сохраняем наше богатство из клонов и их оригиналов в хэш, через таймер t2.
Для начала цель заклинания:

А потом в цикле врагов:

Теперь неплохо бы запустить этот таймер и создать соответствующую функцию.
Функция удаления иллюзий:

Запускаем таймер:

Теперь можно запустить карту и наблюдать, как всё работает.
Кажется, всё? На протяжении всего кода я частично оставлял без внимания одну важную часть. Возможно, вы догадались - это утечки.
Пробежимся по коду и обратим на них внимание, но всё по порядку.

В этой функции вообще нет переменных и объектов, поэтому об утечках и речи быть не может.

Тут две переменные, таймер и целочисленная, так как целочисленная не наследуется от типа handle (в моём понимании это ссылка на объект, описывающая как объект, так и его тип) её обнулять не нужно, а таймер мы обнулили (set t = null), но мы забыли его уничтожить, а это очень важно, ведь объект - таймер, так и находится в памяти и нагружает наш варкрафт, для этого изменим нашу функцию:
Также необходимо очистить хэш, ведь больше ячейку с идом таймера мы не используем.

Хорошо, идём дальше:

Здесь дело пострашнее, не обнуляются две переменные типа unit, наследуемые от handle, а также не уничтожается таймер. С таймером всё просто, но вот что на счёт юнитов?
Почему нужно уничтожать таймер, но не нужно уничтожать юнитов? Об этом позаботится движок игры, юнитов он удаляет сам после смерти (88 секунд после смерти, когда заканчивается разложение, если оно включено).
А вот таймер никто, кроме нас, не уничтожит :) Так сделаем же это!
Точно так же, как прежде, освобождаем ячейку хэш-таблицы.

Кстати, два важных момента:
- Под словом обнулять я подразумеваю присвоить значение null, что означает 0, то есть отсутствие чего-либо, в данном случае указателя, это необходимо чтобы указатель не занимал память.
- При уничтожении объектов, как таймер, важно СНАЧАЛА уничтожить, а уже ПОТОМ обнулять, часто новички обнуляют переменную и пытаются после её удалить, но как можно удалить 0?
Идём дальше:

Как много всего, даже не знаю, с чего и начать.
Перечислим переменные, наследуемые от handle, и, следовательно, необходимые для обнуления:
l, caster, target, g, illusions (ОЙ! Эту переменную мы не использовали, с чистой совестью стираем строчку с её объявлением!), t, t2, target, u, u2
то есть real, integer и boolean обнулять не нужно, это не указатели, а основные типы.

Вот так, но вы можете спросить: "Почему мы не уничтожаем таймеры, используя функцию DestroyTimer()"?
Ответ прост, эти таймеры еще работают, мы их запустили, а уничтожатся они в других функциях, когда надобность в них пропадёт, мы же просто обнуляем ссылки на них.
Молнию уничтожать нет смысла, т.к. это только последняя созданная молния, и вообще молнии должны уничтожаться через время, что у нас и происходит.
Идём дальше:

Так, какой-то boolexpr, это такая штука, так скажем, указатель на функцию-условие, который тоже нужно обнулить т.к. он наследуется от handle, а уничтожать его не нужно, т.к. он используется триггером.
Кстати, то же самое можно было написать по-другому, создавая условие прямо в регистрации события:

Теперь и обнулять ничего не нужно, по-моему, так лучше, но я не сделал так в начале, чтобы наглядней показать устройство нашего триггера.[/spoiler]

6. Вместо заключения
Ну вот и всё, на выходе должен получится такой код:


Надеюсь, вам понравилась статья, если что-то плохо объяснил или ошибся, прошу милости писать в комментариях или в личные сообщения, буду регулярно следить за Вашими ответами.
Признаюсь, я мало времени уделил handle, и, если вы с ним не знакомы, советую почитать это.
Кстати, некоторые опытные jass'еры советуют вместо Save(Unit/Lightning/...)Handle использовать SaveAgentHandle, чего я не сделал, чтобы наглядно показать типы переменных, которые мы вытаскивали из хэша.
Также рекоммендуется использовать SetWidgetX/Y вместо GetUnitX/Y, первое вроде как работает быстрее, однако тут на любителя ;)

Статья написана за 4 дня, и если честно, это были 4 ужасных дня, не буду больше писать статьи :D Да и думаю, вышло ужасно, трудно найти баланс - насколько подробно что-либо описывать.
Было бы неплохо, если бы хоть кому-нибудь эта статья открыла свет хотя бы на часть вопросов, посвещённых тематике jass и триггерных заклинаний.
Код написан на jass2, а не на vJass/cJass из-за соображений, что новички пользуются первым, да и аудитория вроде как побольше получится.
Сильно строго не судите.
-------------------by Hexing-------------------
...всем cJass, пацаны...




Комментарий от меня (Duosora): В Каталоге статей статья была отключена из-за просроченных картинок. Готов её вернуть, если будут убраны ссылки на сторонние ресурсы и восстановлены картинки.


Не зли других и сам не злись.
Мы - гости в этом мире.
И если что не так - смирись,
Будь поумнее - улыбнись,
Ведь в мире всё закономерно.
Зло, излучённое тобой,
К тебе вернётся непременно.
 

  • Страница 1 из 1
  • 1
Поиск:

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