Система отлова нанесённого урона

» опубликован
» Способ реализации: cJass
» Тип: Наработка
Библиотека, которая позволяет добавлять общее событие "юнит получает урон":
» cJass
library UnitDamaged initializer InitRect
{
    region Region
    nothing Adder()
    {
        if(GetEnteringUnit()!=null)
        {
            TriggerRegisterUnitEvent(GetTriggeringTrigger(),GetEnteringUnit(),EVENT_UNIT_DAMAGED)
        }
    }
    
    nothing AnyUnitDamagedEvent(trigger trg)
    {
        group CurrentUnits = CreateGroup()
        unit Picked
        GroupEnumUnitsInRect(CurrentUnits,bj_mapInitialPlayableArea,null)
        loop
        {
            Picked = FirstOfGroup(CurrentUnits)
            exitwhen Picked == null
            TriggerRegisterUnitEvent(trg,Picked,EVENT_UNIT_DAMAGED)
            GroupRemoveUnit(CurrentUnits,Picked)
        }
        TriggerRegisterEnterRegion(trg,Region,null)
        TriggerAddAction(trg,function Adder)
        DestroyGroup(CurrentUnits)
        CurrentUnits=null
    }
    
    nothing InitRect()
    {
        Region = CreateRegion()
        RegionAddRect(Region, bj_mapInitialPlayableArea)
    }
}
» vJass
library UnitDamaged initializer InitRect
    globals
        region Region
    endglobals
    function Adder takes nothing returns nothing
        if GetEnteringUnit()!=null then
            call TriggerRegisterUnitEvent(GetTriggeringTrigger(),GetEnteringUnit(),EVENT_UNIT_DAMAGED)
        endif
    endfunction

    function AnyUnitDamagedEvent takes trigger trg returns nothing
        local group CurrentUnits = CreateGroup()
        local unit Picked
        call GroupEnumUnitsInRect(CurrentUnits,bj_mapInitialPlayableArea,null)
        loop
            set Picked = FirstOfGroup(CurrentUnits)
            exitwhen Picked == null
            call TriggerRegisterUnitEvent(trg,Picked,EVENT_UNIT_DAMAGED)
            call GroupRemoveUnit(CurrentUnits,Picked)
        endloop
        call TriggerRegisterEnterRegion(trg,Region,null)
        call TriggerAddAction(trg,function Adder)
        call DestroyGroup(CurrentUnits)
        set CurrentUnits=null
        set Picked=null
    endfunction

    function InitRect takes nothing returns nothing
        set Region = CreateRegion()
        call RegionAddRect(Region, bj_mapInitialPlayableArea)
    endfunction
endlibrary

Регистрация события идёт следующим образом:
  1. все существующие юниты на карте добавляются в группу и на каждого нужному триггеру добавляется событие получения урона.
  2. указанному триггеру регистрируется событие "юнит входит на игровую территорию".
  3. при реакции на добавленное событие для юнита сразу добавляется событие получения урона.

Есть одна проблема: при создании нового юнита сработает каждый триггер с событием на урон.
» Лечится введением условия.
function TrigFunc takes someone returns somemore
if GetEnteringUnit() == null then
    //действия при получении урона
endif
endfunction

Событие добавляется так:
    call AnyUnitDamagedEvent(SomeTrigger)

Ссылки на сущности при использовании системы:
Источник урона (атаковавший юнит):
GetEventDamageSource()
Величина нанесённого урона:
GetEventDamage()
Цель урона (атакованный юнит):
GetTriggerUnit() 

Никаких дополнительных переменных вводить не нужно, достаточно просто скопировать в Нестандартный Код Карты.

Версия без проблемы с условием, но с дополнительным массивом триггеров (не использовать в динамических триггерах):
» Код
library UnitDamaged initializer InitRect
{
    private region  Region
    private group   Group
    private int     TrigsNum = 0
    private trigger array Trigger
    
    private void Adder()
    {
        int i = 0
        loop
        {
            TriggerRegisterUnitEvent(Trigger[i],GetEnteringUnit(),EVENT_UNIT_DAMAGED)
            exitwhen i==TrigsNum
            i++
        }
        GroupAddUnit(Group,GetEnteringUnit())
    }
    
    private void Registrator()
    {
        TriggerRegisterUnitEvent(Trigger[TrigsNum],GetEnumUnit(),EVENT_UNIT_DAMAGED)
    }
    
    void AnyUnitDamagedEvent(trigger trg)
    {
        Trigger[TrigsNum]=trg
        ForGroup(Group,function Registrator)
        TrigsNum++
    }

    private void InitRect()
    {
        trigger trg = CreateTrigger()
        Group = CreateGroup()
        Region = CreateRegion()
        GroupEnumUnitsInRect(Group,bj_mapInitialPlayableArea,null)
        RegionAddRect(Region, bj_mapInitialPlayableArea)
        TriggerRegisterEnterRegion(trg,Region,null)
        TriggerAddAction(trg,function Adder)
    }
}


Просмотров: 16 193



ScorpioT1000 #101 - 5 лет назад 0
Ну так эвалюейт триггера работает дольше простого вызова функции =)
А лямбда классы в вжасс уже есть?
Faion #102 - 5 лет назад 0
Ну так эвалюейт триггера работает дольше простого вызова функции =)
А с чего ты взял что там происходит эвалюейт триггера?
А лямбда классы в вжасс уже есть?
Хз, можно сказать не юзаю вжасс, мне и сжасса хватает.
ScorpioT1000 #103 - 5 лет назад 0
А с чего ты взял что там происходит эвалюейт триггера?
При любом срабатывании event происходит эвалюэйт триггера, или ты что-то иное имеешь ввиду под этим словом?
Faion #104 - 5 лет назад 0
или ты что-то иное имеешь ввиду под этим словом?
Да... туплю, о другом подумал.
Кста наткнулся сча еще на такой свой вариант реализации:
» тык
library EventUnitDamaged
{
    private trigger registerEventDamage = null
    private trigger registerEnterRect = null
    
    private void Core()
    {
        // создаем триггер
        registerEventDamage = CreateTrigger();
        // создаем группу
        group g = CreateGroup()
        // получаем всех юнитов на карте
        GroupEnumUnitsInRect(g, GetWorldBounds(), null)
        // вешаем на каждого юнита эвент получения урона
        ForGroup(g, lambda void(){
            TriggerRegisterUnitEvent(registerEventDamage,GetEnumUnit(),EVENT_UNIT_DAMAGED)
        });
        GroupClear(g);
        DestroyGroup(g);
        g = null;
        
        // добавляем отслеживание появления новых юнитов
        registerEnterRect = CreateTrigger();
        TriggerRegisterEnterRectSimple(registerEnterRect,GetWorldBounds())
        
        // и при появлении новых юнитов добавляем им эвент
        TriggerAddAction(registerEnterRect, lambda void() {
            TriggerRegisterUnitEvent(registerEventDamage,GetEnteringUnit(),EVENT_UNIT_DAMAGED)
        });
    }
    
    public void AddEventAction(code func)
    {
        if (registerEventDamage == null)
        {
            Core();
        }
        TriggerAddAction(registerEventDamage, func)
    }
}
ScorpioT1000 #105 - 5 лет назад 0
Хмм юнита то чекать придется
Faion #106 - 5 лет назад 0
Хмм юнита то чекать придется
Кстати да. Над будет чонить придумать, или вообще юзать другую мою либу для детекта урона)
Стоп, там все ок, юзается 2 разных триггера. Или ты про какую то другую проверку?
ScorpioT1000 #107 - 5 лет назад (отредактировано ) 0
Про ту что я система, я пришел, зарегал на моих юнитов эвент и работаю только с ним, а мне будет сыпаться всякий хлам от чужих систем.
Faion #108 - 5 лет назад 0
Про ту что я система, я пришел, зарегал на моих юнитов эвент и работаю только с ним, а мне будет сыпаться всякий хлам от чужих систем.
А ну разумно. Но реализовывать такое наверно не буду, т.к. нет необходимости в избирательности...
EAX #109 - 5 лет назад 0
У меня не получилось применить систему. Выдает Fatal Eror при проверке карты после того, как я вставляю функцию в Нестандартный Код Карты. Использую Jass New Gen Pack 5d Exp2. Пробовал все 3 функции, каждая выдает ошибку проверке карты. Еще до того, как начал применять саму функцию. А система отлова урона нужна. В чем моя ошибка?
Clamp #110 - 5 лет назад 0
Только в том, что ты не сказал, какую ошибку выдает редактор =)
Faion #111 - 5 лет назад 0
EAX, мои требуют последний сжасс.
Clamp #112 - 5 лет назад -2
Твои требуют генетических отклонений в сторону любви к жестким извращениям.
ScorpioT1000 #113 - 5 лет назад (отредактировано ) 0
Создал таск Ханабиши для JNGP.
EAX, Перепакуй и обнови wehack.lua до последнего cjass
Darklight #114 - 5 лет назад -1
Ничего выдающегося :(
ведь реально больше есть потребность не просто зарегистрировать получения урона, но и определить:
  1. Источник урона (атакующий)
  2. Тип атаки
  3. Тип урона
  4. Вид заклинания (для урона, полученного заклинанием или способностью)
  5. Величину урона (как реальную, так и базовую)
но на WC3 это очень сложно - особенно с заклинаниями - тут всё дамаг систему нужно перелывать
Clamp #115 - 5 лет назад (отредактировано ) 0
Источник урона (атакующий)
GetEventDamageSource()
Величину урона
GetEventDamage()
* facepalm *
WakVellios #116 - 1 год назад -2
Какая команда получает боевую еденицу получившую урон?
quq_CCCP #117 - 1 год назад 1
WakVellios:
Какая команда получает боевую еденицу получившую урон?
GetTriggerUnit()
JASS API в помощь.
WakVellios #118 - 1 год назад 0
Тьфу блин, как банально хД Спасибо
Dota_2015 #119 - 1 год назад -4
а как использовать эту систему
говорят самый лучший детектор урона это
и не вижу тут vjass
Clamp #120 - 1 год назад (отредактировано ) 0
говорят самый лучший детектор урона это
The system is written in pure JASS and realizes damage handler functions with a variable event
Тут выше было обсуждение, почему это не очень хорошо. В целом, моя система просто даёт возможность создать глобальное событие "юнит получает урон", а любые дополнительные проверки при необходимости накручиваются уже поверх. Прелесть в том, что алгоритмически эта система является ноу-хау, по крайней мере я не встречал подобного компактного решения в 30 строк.
Dota_2015:
и не вижу тут vjass
Библиотеки, например, являются функционалом из vJass, как и globals/endglobals.
Dota_2015:
а как использовать эту систему
Скопировал в нестандартный код карты, для нужного триггера вызываешь call AnyUnitDamagedEvent(Trigger). Всё описано в ресурсе.

А, ну и эта появилась раньше на джва месяца!
2 комментария удалено