Вступление.
Для тех, кто не очень понимает, что такое автокаст, я объясню: это способность, похожая на "Ледяные стрелы" у наги, где вы можете щёлкнуть правой кнопкой мыши для того, чтобы заставить способность применяться автоматически (постоянно пускать ледяные стрелы) или же щёлкнуть левой кнопкой мыши и указать цель, чтобы применить способность один раз. Эти два события немного непросто отловить. Здесь я покажу, как можно это легко сделать. Предназначение этой статьи - научить картостроителей создавать триггерные автокаст-спеллы на JASS. Прежде, чем изучать эту статью, рекомендуется ознакомиться с основами JASS и основами спеллмейкерства, т.к. эта статья НЕ является введением в JASS. Так что если вы не очень знакомы с JASS, прочитайте вводные статьи и вернитесь к этому материалу тогда, когда вы уже более-менее освоитесь с JASS. Итак, всё, что вам понадобится для понимания статьи - это World Editor, базовые знания в JASS, JassCraft и система СScache, которую можно скачать у Vexorian'a. В этой статье мы создадим свою подобную систему, однако некоторые мучаться не хотят. Даже подумав, что код может быть восстановлен, не рекомендую использовать в World Editor спеллы, базированные на коде, так как достаточно всего лишь одной маленькой ошибки, чтобы игра выдала ошибку. Согласитесь, это будет весьма неприятно для играющих. Создание способности. Итак, давайте создадим триггер. Назовём его "Auto Attack". Сконвертируем его в код и удалим всё, что там будет. Должен получиться абсолютно чистый триггер. Следующим шагом нужно создать инициализацию триггера и добавить наши события. Наше первое событие будет реагировать всегда, когда какая-либо боевая единица атакована. Второе - когда приводится в действие способность. Так мы и отловим боевую единицу, на которую было совершено нападение при помощи автоприменения способности, или же указания воина вручную. Теперь необходимо добавить события и действия, затем закрыть нашу Init-функцию. Можете называть свои функции как хотите, единственным исключением является функция инициализации триггера. Она должна иметь имя в формате "InitTrig_{НАЗВАНИЕ}", где {НАЗВАНИЕ} - имя функции. В условиях нам надо будет отловить, есть ли у атакующего способность-автокаст или уточнить, что применяемая способность - наш автокаст. Давайте создадим нашу функцию-условие над функцией инициализации, т.к. функция, которая вызывает другую функцию, должна быть ниже, чем вызываемая. P.S.: Условия напишите в одну строку, я перенёс часть условия на другую строку, чтобы не порвать страницу. Итак, у нас два события, которые должны отлавливаться, поэтому нужно проверить оба. Если у нас есть событие, что боевая единица атакована, нужно также проверить, есть ли у атакующего героя нужная способность (я использовал 'A000'). Если она имеется, то возвратить true и запустить наши действия. В случае, если условия не встретились, мы проверяем, был ли эффект от той способности, которая нам нужна (нужно проверить, является ли событием применение способности, после чего elseif запустит условие, которое проверит, атакован ли юнит и нет ли у атакующего нужной способности) и убедиться в том, что применяемая способность - это та, которую мы хотим. Если условия верны, то запустятся действия триггера, если же нет, тогда возвратится false, а триггер не запустит действия. Здесь всё не очень уж и трудно. Нам нужен триггер действий после того, как цель была повреждена, поэтому мы создаём его, также нам нужно действие триггера, которое потом обнулим, и ещё нам понадобится боевая единица, которая была целью. В первую очередь нужно проверить, какое это было событие. Если событием было "Применяет способность", тогда цель будет обозначаться через GetSpellTargetUnit(), если же нет, то должен быть атакованный воин, которого обозначаем через GetTriggerUnit(). Теперь, чтобы проверить, действительно ли получил воин урон, создадим новое событие с указанием на воина. Укажем действия после получения повреждения. Затем ждём. Зачем нужно ждать? Нам нужно уничтожить триггер сразу. Почему же не сделать это сразу в этой функции? Лично я использую время ожидания 2 секунды, т.к. этого времени достаточно для получения урона, также оно очень удобно для блокировки повторного использования способности, поэтому дважды функция не запустится. После ожидания мы удаляем triggeraction и уничтожаем триггер, не забывая обнулять локальные переменные, типы которых наследуются от handle, чтобы избежать утечек памяти. Нам осталось написать функцию действий после получения урона от атаки. P.S.: Условия напишите в одну строку, я перенёс часть условия на другую строку, чтобы не порвать страницу. Итак, в первую очередь зададим локальные переменные. dam отлавливает полученные повреждения, target - это боевая единица, которая получила повреждение, а cast - это тот, кто нанёс урон. Отдельная переменная используется для создания всплывающего текста, который часто используется в способностях, подобный этой, а ещё одна переменная - это реальная, которая потом тоже будет задействована. Это используется для того, чтобы задать количество урона, который будет наноситься цели дополнительно. По моему примеру, дополнительно нанесётся 25% от нормального урона способности. Несколько строк ниже - это всплывающий текст. Вместо использования BJ я вытащил из неё все native-функции в целях оптимизации. Конечно, не очень здесь это и важно, однако мне больше нравится делать так. Затем я приказываю атакующему повредить цель на количество здоровья, указанного в реальной, которую я назначил ранее, это дополнительное повреждение от способности. И, наконец, уничтожим всплывающий текст и выставим его переменной значение null (обнулим её). Я обнулял и уничтожал всплывающий текст в блоке if\endif, т.к. вне этого блока нет всплывающего текста для уничтожения, я создавал этот текст внутри этого блока. Напоследок обнулим оставшиеся переменные, чтобы не провоцировать утечки. Итак, посмотрим на наш триггер-результат. Завершая статью, хочу поделиться с вами фактом про уничтожение триггеров. Было обнаружено, что прямое уничтожение триггеров может спровоцировать ужасные последствия в карте. Ниже я даю вам функцию, которая позволяет уничтожить триггер, избегая ошибки. Она просто берёт ваш триггер и перед его уничтожением ждёт 15 секунд. Я не вижу в ней никакого смысла, но она позволяет избежать ошибки. Может быть использована вместо сall DestroyTrigger() в функции Auto_Attack_Detect_Actions. Вот и всё, у нас получилась автокаст-способность, которую можно использовать в вашей карте. Я надеюсь, что вы узнали что-то новое. Удачного картостроения и оригинальных карт! | |
Просмотров: 2325 | | |
Всего комментариев: 0 | |