XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
MpW

offline
Опыт: 49,815
Активность:
Отлов урона
Смотрите, я сделал наподобие системы на отлов урона. Работает абилка по этому принципу, в добавок она не просто ловит урон, но и отражает полученный урон. Я часть здоровья под %, которое враг отнял возвращаю триггерной командой. И получается некое отражение.
Задача такая : У меня способность отражает урон, так? Допустим, что у героя осталось 100 здоровья (способность отражает 20% урона). Ему наносится урон от способности в 110 ед. урона - он труп, НО он должен выжить, т.к. 22 ед. урона отразится, т.е. у него должно остаться 12 ед. здоровья!
ps где то мусолилась такая тема.
То есть получается, делая системы отлова урона (повесив на юнита событие - "юнит получает урон"), вот полностью отражение - типа отхилить здоровье (дать здоровья). Все действия с хиллом хп работают немного раньше, чем юнит получает урон. Ты либо вылечишь его раньше чем он будет получен (т.е при фулл хп здоровье все равно потратится), либо наоборот, юнит сначала умрет, а потом будет вылечен что уже ничего не изменит.

Отредактировано Steal nerves, 21.10.2013 в 10:24.
Старый 04.09.2012, 19:31
16GB
GhostOne User
offline
Опыт: 60,317
Активность:
Steal_nerves:
Ему наносится урон от способности в 110 ед. урона - он труп, НО он должен выжить, т.к. 22 ед. урона отразится, т.е. у него должно остаться 12 ед. здоровья!
у тебя так выходит или ты там думаешь?
событие на урон срабатывает раньше самого урона, поэтому если ты будешь лечить юнита, то он не должен умереть если только урон не больше его максимального хп
Старый 04.09.2012, 19:36
MpW

offline
Опыт: 49,815
Активность:
Я так думаю.
Старый 04.09.2012, 19:54
Holocauster
INRI
offline
Опыт: 4,249
Активность:
16GB:
поэтому если ты будешь лечить юнита, то он не должен умереть если только урон не больше его максимального хп
Просто лечи его на эти хп триггерно и все. Поставь проверку "нанесенный урон больше или равно текущее хп" И "нанесенный - утраженный урон - текущее хп больше или равно 1" и "макс хп - текущее хп больше или равно отраженный урон" если да, то лечить на отраженный урон.
Проблема будет, если дамаг будет превышать макс хп - отраженный урон.
В этом случае, нанести урон персонажу, затем его хильнуть.
Я так думаю...
Старый 04.09.2012, 20:53
DimanTOoBS

offline
Опыт: 5,791
Активность:
если в доте не решили эту проблему, не думаю что вы сможете её решить, не прибегая к воскрешению или созданию нового юнита...
Старый 04.09.2012, 21:53
Holocauster
INRI
offline
Опыт: 4,249
Активность:
По идее третья пассивка жука все это делает. Может блокировать процент урона, и отражать его. Могу сделать пример.
Старый 04.09.2012, 22:49
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,279
Активность:
Holocauster, Пассивка жука блочит только физический урон от непосредственного попадания по юниту физ атакой, урон полученный от заклинаний, сплешей, ядов, и тп. блокироваться не будет.
quq_CCCP добавил:
16GB, просто действия вшитые в движок происходят раньше чем действия корыте написанные а war#map.j И когда юнит получает урон движок уже решил что юнита нужно убить, так как урон больше чем здоровье юнита, а только потом в движок выполняет инструкцию в которой написано восстановить здоровье юнита...
Старый 05.09.2012, 06:50
asesmo
Я I Jag Ich Jeg Ja Minä!
offline
Опыт: 8,073
Активность:
Holocauster:
третья пассивка жука все это делает
у жука если ты имеешь в виду анубарака уже лет 9 нету пассиовок лол
теперь у него скилл на контр стан при получении урона (если ты о доте)
а в ладдере (насколько я помню) она вроде работает как аура возмездия на 1 человека с повышением брони и отражением мили физ. урона
Старый 05.09.2012, 06:59
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,279
Активность:
asesmo, все говорят про аунбарака из кампании, и мили карт, а не из доты....
И насчёт 9лет загнул, доте стока нету...
Старый 05.09.2012, 07:31
MpW

offline
Опыт: 49,815
Активность:
16GB, Он умирает. Я в РО убрал регенерацию хп, убрал ловкость, влияющую на защиту, силу, влияющую на регенерацию здоровья и на запас гера, и защиту (ловкость и сила - поставил 1). И настроил урон так, что он равен запасу хп моего героя. И при ударе его мой гер умирает. Еще надо как-то замедлить удар.
Нет, мне пассивку не хочется использовать. Я планирую использовать еще одну характеристику героя как зависимость (например зависимость % от ловкости).
Говорят, что можно прям в условии написать нужные действия, так как срабатывает она раньше действия. У меня как то сомнения. как это будет выглядеть, смотрите урона еще не нанесли, а уже есть урон. Ладно хоть действия мгновенные. Мне надо просто избежать смерти героя при превышении урона НР.
Предлагают:
Если урон больше, чем есть здоровья, то сделать доп. функцию. В условии при этом дать юниту неуязвимость, а в функции (которую надо вызвать через ExecuteFunc()) убрать неуязвимость и нанести чистый урон, равный не отраженному. То, тут его она убьет, либо он спасется (это уже без разницы). По скольку действия мгновенны, это не заметно.
Вопрос тогда встает, как проверить это? умирает быстро очень, не успеваю проверить больше или меньше нанесли. И в точности в погрешности ошибок (либо выживает, так как есть вероятность выживания (помогла защита или какая-то глупая случайность), либо умирает потому что защита -2)
Steal nerves добавил:
щас что-то не хочет работать ExecuteFunc(), JassHepper ругается почему-то, зато уже знаю - что это рабочий вариант (неуязвимость спасает героя) - проверил без ExecuteFunc.
Steal nerves добавил:
все решил проблему с ExecuteFunc - кавычки забыл поставить

Отредактировано Steal nerves, 05.09.2012 в 12:49.
Старый 05.09.2012, 11:49
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
в условии попробуй похилить героя на 1 хп
а потом уже на остальное. есть подозрения, что проверки типа GetWidgetLife() + n * 0.22 и тп они работают медленне,чем нанесенее урона

SetWidgetLife(u,1.) попробуй так в условии
Старый 05.09.2012, 12:04
MpW

offline
Опыт: 49,815
Активность:
Багнутый вариант. Первый удар триггер пропускает (не сработало, нет плавающих текстов) чего-то, и остается 3 хп, второй удар уже сам вражеский герой не делает (мой герой стоит рядом с ним, а он застыл с атакой), а спустя некоторое время приходит в себя и убивает моего героя (а над ними кучу плавающих текстов испаряется вверх).

» код
Код:
globals
trigger DamageUnit
real damaDe //просто для проверки
endglobals

function TReturnD takes nothing returns nothing
    local real damage = damaDe 
    local real k = 1.00 -(0.15 + (0.05*GetUnitAbilityLevel(GetTriggerUnit(),'A001'))) //коэффициент полученного урона
    local texttag tag = CreateTextTag()
    call SetUnitInvulnerable( GetTriggerUnit(), false )
    //показывают настоящий урон красным цветом - для проверки
    call SetTextTagPermanent(tag, false)
    call SetTextTagColor(tag, PercentTo255(100.00), PercentTo255(0.00), PercentTo255(0.00), PercentTo255(100.0))
    call SetTextTagLifespan(tag, 2.00)
    call SetTextTagFadepoint(tag, 0.00)
    call SetTextTagVelocity(tag, 0.00, 0.027)
    call SetTextTagText(tag, I2S(R2I(damage)), TextTagSize2Height(10.00))
    call SetTextTagPosUnit(tag, GetEventDamageSource(), 0.00)
    call UnitDamageTarget( GetEventDamageSource(), GetTriggerUnit(),(damage*k), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    set tag = CreateTextTag()
    //показывают отраженный урон красным цветом
    call SetTextTagPermanent(tag, false)
    call SetTextTagColor(tag, PercentTo255(0.00), PercentTo255(100.00), PercentTo255(0.00), PercentTo255(100.0))
    call SetTextTagLifespan(tag, 2.00)
    call SetTextTagFadepoint(tag, 0.00)
    call SetTextTagVelocity(tag, 0.00, 0.027)
    call SetTextTagText(tag, I2S(R2I(damage*k)), TextTagSize2Height(10.00))
    call SetTextTagPosUnit(tag, GetTriggerUnit(), 0.00)
    //прибавляем к текущему здоровью юнита
    //set damage = GetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE) + damage*(1.0-k)
    //call SetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE, RMaxBJ(0.00,damage))
    set tag = null
endfunction
    
function T_ReturnDamage_C takes nothing returns boolean
    call SetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE, (GetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE)+1))
    set damaDe = GetEventDamage() 
    if(GetEventDamage()>=GetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE))then
        call SetUnitInvulnerable( GetTriggerUnit(), true )
        call ExecuteFunc( "TReturnD" )
    endif
    return false
    //return(IsPlayerEnemy(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetEventDamageSource())))and(GetEventDamage()<GetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE))and(GetEventDamage()!=0)
endfunction

function T_ReturnDamage_A takes nothing returns nothing
    local real damage = GetEventDamage()  
    local real k = 1.00 -(0.15 + (0.05*GetUnitAbilityLevel(GetTriggerUnit(),'A001'))) //коэффициент полученного урона
    local texttag tag = CreateTextTag()
    //показывают настоящий урон красным цветом - для проверки
    call SetTextTagPermanent(tag, false)
    call SetTextTagColor(tag, PercentTo255(100.00), PercentTo255(0.00), PercentTo255(0.00), PercentTo255(100.0))
    call SetTextTagLifespan(tag, 2.00)
    call SetTextTagFadepoint(tag, 0.00)
    call SetTextTagVelocity(tag, 0.00, 0.027)
    call SetTextTagText(tag, I2S(R2I(damage)), TextTagSize2Height(10.00))
    call SetTextTagPosUnit(tag, GetEventDamageSource(), 0.00)

    set tag = CreateTextTag()
    //показывают отраженный урон красным цветом
    call SetTextTagPermanent(tag, false)
    call SetTextTagColor(tag, PercentTo255(0.00), PercentTo255(100.00), PercentTo255(0.00), PercentTo255(100.0))
    call SetTextTagLifespan(tag, 2.00)
    call SetTextTagFadepoint(tag, 0.00)
    call SetTextTagVelocity(tag, 0.00, 0.027)
    call SetTextTagText(tag, I2S(R2I(damage*k)), TextTagSize2Height(10.00))
    call SetTextTagPosUnit(tag, GetTriggerUnit(), 0.00)
    //прибавляем к текущему здоровью юнита
    set damage = GetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE) + damage*(1.0-k)
    call SetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE, RMaxBJ(0.00,damage))
    set tag = null
endfunction

function Trig_DAMAGE_C takes nothing returns boolean
    return((GetLearnedSkill()=='A001')and(GetUnitAbilityLevel(GetLearningUnit(),'A00  1')==1))
endfunction

function Trig_DAMAGE_A takes nothing returns nothing
    //вешаем событие, что он получил урон
    call TriggerRegisterUnitEvent( DamageUnit, GetLearningUnit(), EVENT_UNIT_DAMAGED )
    call UnitAddAbility(GetLearningUnit(), 'A000')
    //даю склад (Abun), специально чтобы лишить его атаки (дабы никого не убил), для проверки отражения урона
    call UnitAddAbility(GetLearningUnit(), 'Abun')
endfunction

//===========================================================================
function InitTrig_ReturnDamageAbility takes nothing returns nothing
    //1
    set gg_trg_ReturnDamageAbility = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ReturnDamageAbility, EVENT_PLAYER_HERO_SKILL )
    call TriggerAddCondition( gg_trg_ReturnDamageAbility, Condition( function Trig_DAMAGE_C ) )
    call TriggerAddAction( gg_trg_ReturnDamageAbility, function Trig_DAMAGE_A )
    //2
    set DamageUnit = CreateTrigger()
    call TriggerAddCondition( DamageUnit, Condition( function T_ReturnDamage_C ) )
    //call TriggerAddAction( DamageUnit, function T_ReturnDamage_A )
endfunction
Старый 05.09.2012, 12:43
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
попробуй использовать вместо ExecuteFunc обычный вызов call
Старый 05.09.2012, 13:20
16GB
GhostOne User
offline
Опыт: 60,317
Активность:
вроде так
Прикрепленные файлы
Тип файла: w3x ReturnDamage.w3x (19.4 Кбайт, 16 просмотров )
Старый 05.09.2012, 16:43
MpW

offline
Опыт: 49,815
Активность:
16GB, он у меня до сих пор умирает, на экран выводит, что нанес 79, а у того был запас здоровья 125 - получается что урон наносится раньше чем триггер вызовет функцию Action? разницу почему то не заметил ((

Steal nerves добавил:
примерчик
Старый 05.09.2012, 18:19
16GB
GhostOne User
offline
Опыт: 60,317
Активность:
так пробуй
Прикрепленные файлы
Тип файла: w3x ReturnDamage.w3x (19.8 Кбайт, 19 просмотров )
Старый 05.09.2012, 18:33
MpW

offline
Опыт: 49,815
Активность:
16GB, спасибо заработало=)) Тему клоуз.
Старый 05.09.2012, 19:01
16GB
GhostOne User
offline
Опыт: 60,317
Активность:
ты хоть догадался зачем я даммика использовал?
чтобы возврат урона не возвращал урон от возврата иначе будет зацикливание, пока урон 0 не будет
Старый 05.09.2012, 19:45
DaeDR

offline
Опыт: 8,074
Активность:
Итак, идеальный вариант, который работает даже когда урон больше, чем у юнита максимальное ХП.
И не надо говорить, что такое сделать нельзя. Подобные наработки валяются в барахолке уже очень давно.
» code
scope ReturnDamage

    globals
    private real dmg
    
    private timer array T
    private unit array UNIT
    private unit array UNIT_SOURCE
    private real array DAMAGE
    private real array DMG
    private integer N = 0
    endglobals
    
    define {
        // НАСТРОЙКИ //
    SPELL_ID = 'A001'
    // можно запихать сюда много
    }
    
function DamageTaken_Timer takes nothing returns nothing
    local integer i = 1
    //Когда срабатывает таймер, то перебираем все таймеры и 
    //убираем неуязвимость всем сразу
    loop { exitwhen i > N
        call SetUnitInvulnerable(UNIT[i], false)
        //Выключаем триггер, чтобы не было косяков с бесконечными циклами
        call DisableTrigger(gg_trg_ReturnDamage)
        //Наносим урон, который не отразился
        call UnitDamageTarget(UNIT_SOURCE[i], UNIT[i], DAMAGE[i] - DMG[i], false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        //наносим отраженный урон противнику
        call UnitDamageTarget(UNIT[i], UNIT_SOURCE[i], DMG[i], false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        //Включаем
        call EnableTrigger(gg_trg_ReturnDamage)
        //Убираем таймер
        call DestroyTimer(T[i])
    i++ }
    //Обнуляем кол-во таймеров
    set N = 0
endfunction
    
function DamageTaken_Condition takes nothing returns boolean
    //Проверяем, если это противник и урон больше нуля
    if IsPlayerEnemy(GetOwningPlayer(GetTriggerUnit()),GetOwningPlayer(GetEventDamageSource())) and GetEventDamage() > 0. then
        //Сразу вбиваем в переменную отраженный урон, т.к. он нам по любому понадобится
        // лучше через глобалку, т.к. меньше нагрузка будет
        set dmg = GetEventDamage()*(0.15+(0.05*GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)))
        // Самое интересное - если урон больше, чем у юнита ХП.
        if GetEventDamage() > GetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE) then
            //Даем юниту неуязвимость!
            call SetUnitInvulnerable( GetTriggerUnit(), true )
            // И тут запускается таймер и вешаются на него нужные переменные
            N++
            set T[N] = CreateTimer()
            call TimerStart(T[N], .0, false, function DamageTaken_Timer)
            set UNIT[N] = GetTriggerUnit()
            set DAMAGE[N] = GetEventDamage()
            set UNIT_SOURCE[N] = GetEventDamageSource()
            set DMG[N] = dmg
            //Лечить юнита не надо
            return false
        else
            // Если не больше, то прсто лечим
            return true
        endif
    endif
    return false
endfunction
    
function DamageTaken_Action takes nothing returns nothing
    // Если у нас наносится обычный урон, то просто лечим юнита и наносим отвеный урон
    call SetUnitState(GetTriggerUnit() ,UNIT_STATE_LIFE, GetUnitState(GetTriggerUnit(), UNIT_STATE_LIFE) + dmg)
    //Выключаем триггер, чтобы не было косяков с бесконечными циклами
    call DisableTrigger(gg_trg_ReturnDamage)
    call UnitDamageTarget(GetTriggerUnit(), GetEventDamageSource(), dmg, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
    call EnableTrigger(gg_trg_ReturnDamage)
endfunction

function Trig_ReturnDamage_Actions takes nothing returns nothing
    //Добавляем событие, если уровень прокаченной способности равен 1
    call TriggerRegisterUnitEvent( gg_trg_ReturnDamage, GetTriggerUnit(), EVENT_UNIT_DAMAGED )
endfunction

//===========================================================================
function Trig_ReturnDamage_Conditions takes nothing returns boolean
    return GetLearnedSkill() == SPELL_ID and GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID) == 1
endfunction
function InitTrig_ReturnDamage takes nothing returns nothing
    // Создаем триггер для события прокачки
    set gg_trg_ReturnDamage = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ReturnDamage, EVENT_PLAYER_HERO_SKILL )
    call TriggerAddCondition( gg_trg_ReturnDamage, Condition( function Trig_ReturnDamage_Conditions ) )
    call TriggerAddAction( gg_trg_ReturnDamage, function Trig_ReturnDamage_Actions )
    // Создаем триггер для события получения урона. Используем уже имеющуюся переменную
    set gg_trg_ReturnDamage = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_ReturnDamage, Condition( function DamageTaken_Condition ) )
    call TriggerAddAction( gg_trg_ReturnDamage, function DamageTaken_Action )
endfunction

endscope
Может, слегка замудрено, зато 100% работает без Хеша и дополнительных юнитов.
Прикрепленные файлы
Тип файла: w3x ReturnDamage.w3x (20.4 Кбайт, 18 просмотров )
Старый 05.09.2012, 20:33
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 10:21.