Многие знают, что каждый юнит в игре может иметь своё индивидуальное число - custom value. Иногда некоторые создатели карт находят нужным использовать именно его а не какую-то переменную. Иногда нам однако нужно сохранить целую массу данных о каждом юните(ну или таких юнитов просто очень много) Но вот беда - custom value у юнита всего 1 и хотя может хранить любое целое число - он может хранить лишь одно число, о хранении имени, навыков и прочего речи быть не может. Можнет быть некоторые наталкивались на мысль закодировать это число так, чтобы из него можно было извлечь несколько разных данных, но эт во первых геморрно, а во вторых особо много не поместишь - число ограничено по количеству знаков. Многие попросту плюнули на custom value, посчитав что это единственная индивидуальная частичка юнита, которую легко менять, как то без надобности. Однако эту частичку можно использовать как счётчик. Точнее благодаря custom value мы можем дать каждому юниту свой номер и использовать этот индекс в своих грязных целях. Многие делают триггерные заклинания, которые нетрудно использовать в картах, где игрок управляет 1 героем и цели заклинания в основном - единственный герой другого игрока. Но что делать, если героев несколько у игрока или мы просто хотим, чтобы заклинания действовали и на крипов? или мы хотим завести "индивидуальную карточку" каждого существа на карте и вести его стату. Разумеется без гор текста и кода. Данная мини-статья разжуёт эту простую мысль, а в наработке присутствуют два примера по MUI спеллам, используя custom values.
Грамотное использование Custom Value
Рассмотрим вышесказанное на примере - попробуем сделать парочку заклинаний, используя custom values юнитов. Итак: Задачка 1 Сделаем что-то наподобие ульты Ancient apparition из доты. В указанной области вражеские юниты теряют способность восстанавливать здоровье каким-либо способом в течении нескольких секунд, а каждую секунду теряют несколько баллов здоровья. Если Здоровье юнита упадёт ниже определённого процента - юнит погибает от руки кастера. При многократном наложении убийцей будет считаться последний кастер, а продолжительность обморожения - складывается. На юнитах под этим заклинанием должен висеть эффект до смерти или окончания срока действия заклятия.
Задачка 2 Сделаем что-то попроще. В указанной области вражеские герои теряют часть своей ловкости на несколько секунд. При многократном наложении увеличивается длительность похищения ловкости. На юнитах под этим заклинанием должен висеть эффект до окончания срока действия заклятия.
Приступаем... В качестве способностей-пустышек возьмём Буран и Огненный столбы - заменим баффы и уберём все стандартные визуальные эффекты.
1. Создание переменных.
Общее: ObjectCounter(Целочисленная) - эта переменная будет счётчиком юнитов, на которые мы обращаем своё внимание. При появлении нового юнита, данные которого мы хотим учитывать - мы увеличиваем эту переменную на 1 и присваиваем custom value юнита эту переменную. Обратите внимание, что сначала мы проверим - не имеет ли юнит уже номер, то есть custom value должен быть равен 0. GroupForspells(Отряд, массив) - здесь мы будем хранить юнитов для разных заклинаний, например в группе 1 будут юниты для заклинания А, в группе 2 - юниты для заклинания Б и т.д. Можно создавать разноимённые групп и даже массивы разноимённых групп, сейчас нам хватит и такой. Name(Строка, массив) - Массив переменных для хранения имён юнитов, мы можем дать имя каждому когда пожелаем, если пожелаем. PointCaster(точка) - точка, утечку которой надо будет удалять в момент каста заклинания.
Для задачи 1 создаём следующее:
HPdrain(реальная, массив) - значения "замороженного здоровья" юнитов, при обморожении мы заносим текущее здоровье каждого юнита в эту переменную. HPdrainDur(целочисленная, массив) - массив времени действия заклинания. Единицы измерения менятся в зависимости от того, какой периодичности наш триггер заклинания. Поскольку интервал триггера для этой задачи - 0.03, то чтобы заклинание действовало 1 секунду - мы даём длительность 33 единицы. HPDrainCaster(боевая единица, массив) - в этой переменной каждый юнит помнит того, кто наслал на него обморожение последним, то есть от кого принять смерть, если здоровье упадёт ниже критического уровня. EffectHP(спецэффект, массив) - на каждого юнита мы лепим спецэффект и заносим в память, для последующего разрушения спецэффекта и удаления утечки.
Для задачи 2 создаём следующее: AgilityDrain(целочисленная, массив) - часть ловкости, которую мы отнимем у каждого героя, попавшего под заклинание, у каждого это число будет своё, разумеется. AgilDur(целочисленная, массив) - массив времени действия заклинания. Единицы измерения менятся в зависимости от того, какой периодичности наш триггер заклинания. Поскольку интервал триггера для этой задачи - 1.00, то чтобы заклинание действовало 1 секунду - мы даём длительность 1 единица. EffectAg(спецэффект, массив) - на каждого юнита мы лепим спецэффект и заносим в память, для последующего разрушения спецэффекта и удаления утечки.
2. Построение триггеров.
Триггер с событием каста способности.
К 1 заданию
Ко 2 заданию
При касте любого из наших заклинаний мы выбираем подходящие по критериям юниты в нужном нам радиусе от точки-цели и заносим их во временную 0 группу, во первых для создания переменных, во вторых - для удаления утечки. Выбираем все юниты в группе. Делаем проверку, имеет ли юнит уже номер и если нет - увеличиваем счётчик, даём его(номер), даём имя юниту если надо и прочую индивидуальную хрень при "знакомстве" с новым юнитом. После задаём данные заклинания, то есть для обморожения - здоровье юнитов, убийц и время обморожения, для потери ловкости - высчитываем количество ловкости, отнимаем её у целей и ставим продолжительность состояния. Создаём спецэффекты на целях и также заносим в память. После - включаем соответствующий триггер. Если триггер уже включён - это действие "сделает ничего".
Триггеры заклинаний.
К 1 заданию
Ко 2 заданию
Мы выбираем всех юнитов в группе с номером нашего заклинания, например в группе 1 для обморожения и в группе 2 для потери ловкости. (Если группа пуста - выключаем триггер, нет нужды его выполнять если нет целей. Если группа не пуста то двигаемся дальше по действиям) Сразу проверяем, не прошло ли действие заклинания у юнита - проверяем его ___Dur переменную. Если прошло - уничтожаем эффект юнита и удаляем его из группы. Если действие ещё не прошло - отнимаем единицу из продолжительности. Если здоровье юнита больше чем его порог здоровья(для обморожения) - устанавливаем здоровье на порог. Если меньше - приравниваем порог к текущему здоровью, т.е. мы позволяем здоровью уменьшаться, но не увеличиваться. Для обморожения - каждые 33 единицы аремени(каждую секунду) - отнимаем у юнитов фиксированное количество здоровья, зависящее от уровня способности у его "потенциального убийцы". Если процент здоровья меньше 10-11-12% - делаем "потенциального убийцу" юнита реальным убийцей, нанося жертве 99999 чистого урона. Убираем спецэффект и стави оставшуюся длительность заклинания для юнита = 0. Во 2 задаче просто дожижаемся пока срок действия для юнита пройдёт и возвращаем отнятую ловкость.
Для удобства можно заносить внутри цикла custom value of picked unit в целочисленную и использовать её. Будет выглядеть не так страшно. Вот пожалуй и осветил часть потенциала использования custom values. Надеюсь, многим это поможет.