WarCraft 3: Поглощаем урон

История одного заклинания
В прошлой статье мы сделали активное заклинание, а теперь добавим ему пассивный эффект и научимся импортировать системы, написанные другими людьми.

Идея

На данный момент наше заклинание даёт какой-то эффект только при использовании. Теперь мы добавим ему пассивный эффект: уменьшение входящего урона на 5*уровень заклинания.

Подготовка

Работа с уроном дело муторное и сопряжено с кучей подводных камней. Да и на каждое заклинание писать обработку урона расточительно. Поэтому мы поступим хитрее и возьмём уже готовую систему. И в дальнейшем будем использовать её для всех заклинаний на нашей карте.

Откроем карту пример, и прочитаем инструкцию.
» оригиральный текст
*   Implementation
*   --------------
*   1.  Copy this trigger to your map. With the AddDamageHandler function you can 
*       add as many handlers as you like (compare the OnDamage scope).
*   2.  Copy the two custom abilities to your map and make sure they have the
*       correct ID in the globals variable block.
*   3.  Go to the locust swarm ability and invert its damage return portion
*       from (default) 0.75 to -0.75.
*   4.  Remove the spell damage reduction ability from the spell damage reduction
*       items you use (runed bracers). You can configure the resistance of this
*       item in the globals block, modifying BRACERS_SPELL_DAMAGE_REDUCTION.
*
**********************************************************************************
*
*   Important Notes
*   ---------------
*   1.  Life Drain does not work with this system, so you should use a triggered 
*       version of this spell if you want to use it.
*   2.  Same for Finger of Death, if you want to use this spell bug free with this
*       system, you should use a triggered version of it.
*   3.  If you use damage modifiers by setting the damage amount variable, you have
*       to use GetUnitLife, GetUnitMaxLife and SetUnitLife instead of GetWidgetLife,
*       GetUnitState for UNIT_STATE_MAX_LIFE and SetWidgetLife in your whole map to
*       ensure there occure no bugs.
*   4.  The boolean USE_SPELL_RESISTANCE_AUTO_DETECT is only neccessary set to true
*       if you want to use a customized damage table with spell damage resistance
*       above 100%. If this is not the case, it should be set to false, as the 
*       system is faster then and still works correct.
*   5.  As already mentioned you can't use the spell reduction ability when using this
*       system (runed bracers and elunes grace). If you want to use them, you can 
*       trigger them by using the damage modifiers. Runed bracers is already considered
*       in this system, so you don't have to code it.
» Google перевод
*   Реализация
* --------------
* 1. Скопируйте этот триггер на вашу карту. С помощью функции AddDamageHandler вы можете добавить столько обработчиков, сколько захотите.( OnDamage).
* 2. Скопируйте две пользовательских способности на карту и убедитесь, что у них есть
* правильный идентификатор в блоке глобальных переменных.
* 3. Перейдите к способности роя саранчи и переверните ее часть, возвращающую урон.
* от (по умолчанию) 0,75 до -0,75.
* 4. Убрать способность к уменьшению урона от заклинаний из снижения урона от заклинаний.
* предметы, которые вы используете (рунические наручи). Вы можете настроить сопротивление этого
* элемент в блоке глобалов, модифицирующий BRACERS_SPELL_DAMAGE_REDUCTION.
*
************************************************** ********************************
*
*   Важные заметки
* ---------------
* 1. Life Drain не работает с этой системой, поэтому вы должны использовать триггер
* версия этого заклинания, если вы хотите использовать его.
* 2. То же самое для Finger of Death, если вы хотите использовать эту заклинание бесплатно с этим
* система, вы должны использовать триггерную версию.
* 3. Если вы используете модификаторы урона, устанавливая переменную величины урона, у вас есть
* использовать GetUnitLife, GetUnitMaxLife и SetUnitLife вместо GetWidgetLife,
* GetUnitState для UNIT_STATE_MAX_LIFE и SetWidgetLife во всей вашей карте, чтобы
* Убедитесь, что нет ошибок.
* 4. Логическое значение USE_SPELL_RESISTANCE_AUTO_DETECT только обязательно установлено в true
* если вы хотите использовать настраиваемую таблицу урона с сопротивлением заклинаниям
* выше 100%. Если это не так, следует установить значение false, так как
* Система работает быстрее и работает правильно.
* 5. Как уже упоминалось, вы не можете использовать способность уменьшения заклинаний при использовании этого
* Система (Рунические наручи и Elunes Grace). Если вы хотите использовать их, вы можете
* вызвать их, используя модификаторы урона. Рунические наручи уже считаются
* в этой системе, так что вам не нужно ее кодировать.
Подводя итоги:
  • Скопировать триггер и две нестандартные способности
  • Если вы используете заклинание "Москиты", инвертируйте Фактор возвращаемого урона. По умолчанию вместо 0.75 установите -0.75.
  • Не использовать способности, уменьшающие урон (лучше настроить триггерно).
  • Заклинания Похищение жизни и Перст Смерти не обрабатываются этой системой и нужно использовать их триггерные аналоги.
  • Для корректной обработки урона, нужно использовать GetUnitLife, GetUnitMaxLife и SetUnitLife, предоставляемых библиотекой.
Принимая все риски, скопируем триггер DamageEvent и нужные способности.
Так как при копировании равкоды изменились.
Укажем это в настройках библиотеки.
private constant integer DAMAGE_TYPE_DETECTOR = 'A001'
private constant integer SET_MAX_LIFE = 'A002'
И в завершении, система предоставляет свои функции GetUnitLife, GetUnitMaxLife и SetUnitLife, вместо стандартных. Заменим их в своём заклинании.

Реализация

Создадим ещё один триггер DamageEventSetting где и будем настраивать работу с уроном.
library DamageEventSetting requires DamageEvent, SpellMassHeal {
    function onInit(){
        AddDamageHandler(function(){
            
        });
    }
}
И в наше заклинание добавим публичные методы для использования в DamageEventSetting.
public {
	// Возвращаем равкод способности для использования в DamageEventSetting
	function SpellMassHealAbilityIdGet() -> integer {
		return AbilityID;
	}
	// Возвращаем количество поглощённого урона для использования в DamageEventSetting
	function SpellMassHealDamageAbsorbGet() -> real {
		return 5.0;
	}
}
И собственно настраиваем получение урона.
library DamageEventSetting requires DamageEvent, SpellMassHeal {
    function onInit(){
        AddDamageHandler(function(){
            /*
            unit PDDS.target - тот по которому нанесли урон
            unit PDDS.source - тот кто нанёс урон
            real PDDS.amount - количество нанесённого урона
            */
            
            integer AbilityLevel; // Заведём переменную с уровнем способности на будущее
        
            // Настраиваем SpellMassHeal
            AbilityLevel = GetUnitAbilityLevel(PDDS.target, SpellMassHealAbilityIdGet());
            if (AbilityLevel > 0){
                // Уменьшаем количество урона используя RMaxBJ,
                // чтоб отрицательный урон не лечил кастера
                PDDS.amount = RMaxBJ(0, PDDS.amount - I2R(AbilityLevel) * SpellMassHealDamageAbsorbGet());
            }
        });
    }
}
Опять красивое описание способности придётся оставить в качестве домашнего задания.

Просмотров: 530

NazarPunk #2 - 9 месяцев назад 0
Эта система не позволяет менять количество урона на лету.
Clamp #3 - 9 месяцев назад 0
NazarPunk, с чего бы, лол? Это исключительно вопрос логики твоей способности; система даёт возможность поймать урон, работа с этим уроном в неё не заложена.
NazarPunk #4 - 9 месяцев назад (отредактировано ) 0
Clamp:
NazarPunk, с чего бы, лол? Это исключительно вопрос логики твоей способности; система даёт возможность поймать урон, работа с этим уроном в неё не заложена.
Поэтому я и выбрал другую систему, где работа с уроном заложена. Как вы с момощью вашей системы реализуете "уменьшение входящего урона на 5*уровень заклинания"?
Притом в ней нельзя различить физический и магический урон.
Clamp #5 - 9 месяцев назад 0
"уменьшение входящего урона на 5*уровень заклинания"?
По точно такой же логике, по которой в доте работают (или работали в прошлом) все подобные способности - компенсацией урона перед его получением.
NazarPunk #6 - 9 месяцев назад 0
По точно такой же логике, по которой в доте работают (или работали в прошлом) все подобные способности - компенсацией урона перед его получением.
Если урон больше максимального хп, юнит сначала умрёт. При этом нельзя заблокировать полностью весь урон, потому что нельзя установить хп выше максимального.
Clamp #7 - 9 месяцев назад 0
Все указанные проблемы решаются выдачей неуязвимости перед получением пойманного урона и нанесением нужных значений после. Включи фантазию, если всерьёз что-то думаешь о программировании.