Я хочу чтоб, при нажатии определенной способности, герою который нажал эту способность, скажем дался щит на 300 хп, то есть 300 поглащаемого урона, или же если этого героя бьют то урон не проходит, но если герою нанесут больше чем 300 урона щит спадет и герою снова будет наносится урон. Надеюсь понятно объяснил, просто поглощает некоторое количество урона.

Принятый ответ

  1. событие урона показывает сколько нанесет урона сейчас, но урон еще не пришел. урон происходит через 0.00 сек.
  2. у вас может быть в этот момент максимальный запас здоровья (например у курицы 10 хп). А урон противника получается слишком большим.
раскрыть
  • 2.1. Манипуляциями с хп через команды типа set life of unit вы не всегда можете наперед подправлять. Тк хп может упереться в лимит запаса здоровья юнита. А получаемый урон больше чем запас, и юнит умрет.
  • 2.2. Можно сделать юнита временно неуязвимым, тогда атака не срабатывает
2.3.поэтому самое идеальное даем абилку с максимальным запасом здоровья с 999999к хп. Юнит точно не умрет от урона.
после таймера 0.00 сек убираем абилу и подправляем как надо.
ты можешь делать проверки сколько очков осталось на поглощение

Nemezid, это незаметно, тк все происходит очень быстро.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
32
4 года назад
0
Какой патч?

Ну и придется работать с триггерами чтобы детектить урон.

когда то делал такую способность, код под като
код
Кода довольно много, и он несколько запутанный, от части из за визуального эффекта щита и кол-ва поглощенного урона.
function FormatAirportTrainingBar takes integer fp_n returns string
    local string str = ""

    if ( fp_n <= 0 ) then
        return str
    endif

    loop
        exitwhen fp_n < 10
        if ( udg__TempBarStyle == 0 ) then
            set str = str + "''''''''''"
        else
            set str = str + "||||||||||||||||||||"
        endif
        set fp_n = fp_n - 10
    endloop

    loop
        exitwhen fp_n <= 0
        if ( udg__TempBarStyle == 0 ) then
            set str = str + "'"
        else
            set str = str + "||"
        endif
        set fp_n = fp_n - 1
    endloop

    return str
endfunction

function UpdateAirportTrainingBar takes texttag tt, integer fp_nTick, integer fp_nTickMax returns nothing
    local integer nProgress
    local integer nLen
    local string strTT1
    local string strTT2

    if ( tt == null ) then
        call BJDebugMsg( "text tag hDZzRwuZxFQcXqaMPnML null" )
        return
    endif

    set nLen = R2I( I2R( fp_nTickMax ) / 300 * 100 )
    set nProgress = R2I( I2R( nLen ) / fp_nTickMax * fp_nTick )
    set strTT1 = "" + FormatAirportTrainingBar( nProgress )
    set strTT2 = FormatAirportTrainingBar( nLen - nProgress ) + ""
    call SetTextTagText( tt, "|cff0080c0" + strTT1 + "|r|cffff0000" + strTT2 + "|r", 0.023 )
endfunction

function Get_Staff_of_Purification takes unit runner returns item
    set bj_forLoopAIndex = 0
    set bj_lastCreatedItem = null
    
    if GetUnitAbilityLevel( runner, 'Arun' ) == 0 then
        return null
    endif
    
    loop
        exitwhen bj_forLoopAIndex > 5

        set bj_lastCreatedItem = UnitItemInSlot( runner, bj_forLoopAIndex )
        if GetItemTypeId( bj_lastCreatedItem ) == 'I01A' then
            return bj_lastCreatedItem
        endif

        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop

    return bj_lastCreatedItem
endfunction

function Trig_RunnerDamageDetect_Conditions takes nothing returns boolean
    if GetTriggerEventId( ) == EVENT_UNIT_DAMAGED then
        return GetEventDamage( ) > 0.00 and GetEventDamageSource( ) != GetTriggerUnit( ) and GetEventDamageSource( ) != DummyAttacker
    endif
    return true
endfunction

function HealRunner takes nothing returns nothing
    local DamageData dd = GetDataBX( GetExpiredTimer( ) )
    
    call UnitRemoveAbility( dd.attacked, 'AMhp' )
    call SetUnitState( dd.attacked, UNIT_STATE_LIFE, dd.hp )
    
    call RemoveDataBX( dd.trix )
    call DestroyTimer( dd.trix )
    call dd.clear( )
    call dd.destroy( )
endfunction

function Trig_RunnerDamageLock_Actions takes nothing returns nothing
    local TriggerData st = GetDataBX( GetTriggeringTrigger( ) )
    local DamageData dd
    local eventid id = GetTriggerEventId( )
    
    if id == EVENT_GAME_TIMER_EXPIRED and st.id < st.time and st.attacked != null then
        set st.id = st.id + 1
        if GetUnitAbilityLevel( st.attacked, 'Bcyc' ) > 0  or GetUnitAbilityLevel( st.attacked, 'Bcy2' ) > 0 then
            call SetTextTagPos( st.tt, GetUnitX( st.attacked ) - 60.00, GetUnitY( st.attacked ) - 60.00, 585.00 )
        else
            call SetTextTagPos( st.tt, GetUnitX( st.attacked ) - 60.00, GetUnitY( st.attacked ) - 60.00, 80.00 + GetUnitFlyHeight( st.attacked ) )
        endif
        call UpdateAirportTrainingBar( st.tt, 100 - R2I( st.dmg / st.hp * 100.00 ), 100 )
        
    elseif id == EVENT_UNIT_DAMAGED and st.dmg < st.hp then
        set dd = DamageData.create( )
        set dd.trix = CreateTimer( )
        set dd.attacked = st.attacked
        set dd.dmg = GetEventDamage( )
        set dd.hp = GetUnitState( dd.attacked, UNIT_STATE_LIFE )
        
        call SetDataBX( dd.trix, dd )
        call UnitAddAbility( dd.attacked, 'AMhp' )
        call SetUnitState( dd.attacked, UNIT_STATE_LIFE, dd.hp + dd.dmg )
        
        call TimerStart( dd.trix, 0.00, false, function HealRunner )
        if GetUnitAbilityLevel( st.attacked, 'B015' ) > 0 then
            set st.dmg = st.dmg + dd.dmg - dd.dmg * (0.10 * IMaxBJ( GetBuffLevel( GetUnitAbility( st.attacked, 'B015' ) ), 1 ) ) 
        else
            set st.dmg = st.dmg + dd.dmg
        endif
    else
        call UnitRemoveAbility( st.attacked, 'A08L' )
        call UnitMakeAbilityPermanent( st.attacked, false, 'A08L' )
        call DisableTrigger( st.trg )
        call SetTextTagVisibility( st.tt, false )
        
        if not IsUnitDead( st.attacked ) then
            call UnitRemoveAbility( st.attacked, 'B00A' )
        endif
        
        call RemoveSavedInteger( gg_htb_HashData, ExKeySoPRunner, GetHandleId( st.attacked ) )
        
        call st.RemoveTrigger( )
        call st.destroy( )
    endif
    
    set id = null
endfunction

function Trig_Staff_of_Purification_Actions takes nothing returns nothing
    local TriggerData dd
    local unit Runner = GetSpellAbilityUnit( )
    local integer RunnerId = GetHandleId( Runner )
    local item Staff = LoadItemHandle( gg_htb_HashData, RunnerId, ExKeySoP )
    local integer ChargesCount = 0
    local trigger trig = LoadTriggerHandle ( gg_htb_HashData, ExAtomShield, RunnerId )
    local integer pBuff = 0
    
    if Staff == null then
        set Staff = Get_Staff_of_Purification( Runner )
         
        if Staff == null then
            //call DisplayTextToPlayer( Player( CrashPlayerNumber ), 0.00, 0.00, I2Sx( 'A01Q', CrashPlayerNumber ) )
            call BJDebugMsg( DEBUG + I2Sx( 'A02O', 0 ) + INFO )
            return
        endif
        
        call SaveBoolean( gg_htb_HashData, RunnerId, ExKeyHasStaff, true )
        call SaveItemHandle( gg_htb_HashData, RunnerId, ExKeySoP, Staff )
    endif
    
    set ChargesCount = GetItemCharges( Staff )
    
    if ChargesCount < 1 then
        set Runner = null
        set Staff = null
        set trig = null
        return
    endif
    
    call SetItemCharges( Staff, 0 )
    
    // блокирующие урон способности не складываются.
    //============================================================================================
    if trig != null then
        call TriggerExecute( trig )
    endif
    
    set trig = LoadTriggerHandle( gg_htb_HashData,  ExEtherialShell, RunnerId )
    
    if trig != null then
        call TriggerExecute( trig )
    endif
    
    set trig = null
    
    // Необходимо сбросить PhaseShift для корректной работы щита.
    
    if GetUnitAbilityLevel( Runner, 'Bpsh' ) > 0 then
        call UnitRemoveAbility( Runner, 'Bpsh' )
        call SetUnitInvulnerable( Runner, false )
    endif
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    set dd = TriggerData.create( )
    set dd.attacked = Runner
    set dd.pl = GetOwningPlayer( Runner )
    set dd.trg = CreateTrigger( )
    set dd.trc = TriggerAddCondition( dd.trg, Condition( function Trig_RunnerDamageDetect_Conditions ) )
    set dd.tra = TriggerAddAction ( dd.trg, function Trig_RunnerDamageLock_Actions )
    set dd.tt = CreateTextTag( )
    set dd.hp = 1000.00 * ChargesCount
    set dd.dmg = 1.00
    set dd.id = 0
    set dd.time = 480
    set dd.c = 0.03125
    
    call UnitAddAbility( Runner, 'A07E' )
    set pBuff = GetUnitAbility( Runner, 'A07E' )
    if pBuff > 1  then
       call  SetAbilityHidden( pBuff, 1 )
    endif
  
    call UnitAddAbility( Runner, 'A08L' )
    call UnitMakeAbilityPermanent( Runner, true, 'A08L' )
    
    call SetDataBX( dd.trg, dd )
    call SaveInteger( gg_htb_HashData, ExKeySoPRunner, RunnerId, dd )
    
    call TriggerRegisterPlayerEvent( dd.trg, dd.pl, EVENT_PLAYER_LEAVE )
    call TriggerRegisterDeathEvent( dd.trg, Runner )
    call TriggerRegisterUnitEvent( dd.trg, Runner, EVENT_UNIT_DAMAGED )
    
    call TriggerRegisterTimerEvent( dd.trg, 0.03125, true )
    
    if GetLocalPlayer( ) == dd.pl or IsPlayerAlly( GetLocalPlayer( ), dd.pl ) then
        call SetTextTagVisibility( dd.tt, true )
    else
        call SetTextTagVisibility( dd.tt, false )
    endif
    
    set pBuff = GetUnitAbility( Runner, 'B00A' )
    
    if pBuff < 1 then
        call BJDebugMsg(DEBUG+" " + GetAbilityEffectById( 'A07E', EFFECT_TYPE_TARGET, 1) )
        call BJDebugMsg(INFO)
        return
    endif
    
    set dd.c = TimerGetElapsed( DispTimer )
    call WMem( RMem( pBuff + 0x90 ) + 0x4, mR2I( dd.c + 15.10 ) )
    call WMem( RMem( pBuff + 0x90 ) + 0x8, mR2I( dd.c + 10.408 ) )
    call UpdateAirportTrainingBar( dd.tt, 100, 100 )
    call UnitRemoveAbilityTimed( Runner, 'A07E', 0.00)
    
    set Runner = null
endfunction
    
//===========================================================================
function InitTrig_Staff_of_Purification takes nothing returns nothing
    set udg__TempBarStyle = 0
endfunction
0
18
4 года назад
0
ловишь событие получения урона, даешь миллион хп или че то ещё, запускаешь таймер на 0.00 секунд и в функции таймера убираешь эти миллион хп и т.д

а в новых патчах с этим вроде более гибко теперь, можно регулировать наносимый урон (могу ошибаться)
0
8
4 года назад
0
Мне на варкрафт 3ий 1.26а, я не буду на рефордж переходить.

Может более подробно объясните, а то я не очень понимаю.
0
32
4 года назад
0
Qulore, это работа с триггерами, суть заключается в повышение кол-ва задоровья юнита до кол-ва урона, которое нужно заблокировать, ровно перед уроном, а после все вернуть на место.
0
15
4 года назад
0
quq_CCCP, а это не слишком палевно визуально?
0
27
4 года назад
0
  1. событие урона показывает сколько нанесет урона сейчас, но урон еще не пришел. урон происходит через 0.00 сек.
  2. у вас может быть в этот момент максимальный запас здоровья (например у курицы 10 хп). А урон противника получается слишком большим.
раскрыть
  • 2.1. Манипуляциями с хп через команды типа set life of unit вы не всегда можете наперед подправлять. Тк хп может упереться в лимит запаса здоровья юнита. А получаемый урон больше чем запас, и юнит умрет.
  • 2.2. Можно сделать юнита временно неуязвимым, тогда атака не срабатывает
2.3.поэтому самое идеальное даем абилку с максимальным запасом здоровья с 999999к хп. Юнит точно не умрет от урона.
после таймера 0.00 сек убираем абилу и подправляем как надо.
ты можешь делать проверки сколько очков осталось на поглощение

Nemezid, это незаметно, тк все происходит очень быстро.
Принятый ответ
0
22
4 года назад
0
Nemezid:
quq_CCCP, а это не слишком палевно визуально?
ни разу не видел как работают системы с блоком урона?
0
32
4 года назад
0
Nemezid, везде так сделан блок урона, в доте, в многих картах - никто не жаловался.
0
27
4 года назад
0
Если щит действует только на физ дамаг, я бы всучил какие-нибудь доспехи каменные на один удар, которые гарантированно отобьют 300 ед. урона без извращений
0
27
4 года назад
Отредактирован MpW
0
Феникс, у каменных доспех вроде не меньше проблем. ему надо 300 единиц дамага отсчитать, чтобы убрать их в нужный момент. а с каменными доспехами урон всегда будет обнулен, и событие урона сегда будет показывать дамаг нулевым, и как он отсчитает. он наверн хочет сделать подобие энергетического щита. если я не ошибаюсь
0
8
4 года назад
0
Steal nerves:
Феникс, у каменных доспех вроде не меньше проблем. ему надо 300 единиц дамага отсчитать, чтобы убрать их в нужный момент. а с каменными доспехами урон всегда будет обнулен, и событие урона сегда будет показывать дамаг нулевым, и как он отсчитает. он наверн хочет сделать подобие энергетического щита. если я не ошибаюсь
Нет, это как щит эмбера из доты, только блочит любой урон, а не только магический.

quq_CCCP:
Qulore, это работа с триггерами, суть заключается в повышение кол-ва задоровья юнита до кол-ва урона, которое нужно заблокировать, ровно перед уроном, а после все вернуть на место.
Можно по-подробнее. Этот вариант самый понятный.
0
15
4 года назад
0
везде так сделан блок урона, в доте, в многих картах - никто не жаловался
Чтож, значит не палевно) Ни разу не обратил внимания
0
32
4 года назад
0
Qulore, ну куда подробнее, для начала тебе нужно отследить каст способности - для этого требуется триггер, с событием юнит применяет способность, условием что примененная способность и действием :
А тут ты создаешь триггер, динамический, в который добавляешь событи что юнит получает урон, юнит умирает, время вышло.
Все данные нужно сохранить на хендл триггера, для этого используют хештаблицы или структуры.
Так же в новь соданный триггер ты добавляешь tirggercondition и в нем делает ветвление. Так же необходимо учесть утилизацию триггера, смерть юнита (если влетит 100500 урона) и прочее.
Описать тут все тонкости создания таких способностей не реально. Пишутся такие способности на jass, и требуют средний уровень познаний,
0
26
4 года назад
Отредактирован Extremator
0
Так это же 2й скилл Аббадона
Что вы тут два дня размусоливаете?
0
32
4 года назад
0
Extremator, не важно что это за спелл, для чуваков которые даже гуи то не открывали - это не возможно, пусть идет изучать основы.
0
8
4 года назад
0
Прсто, у меня очень много идей, и они все такие сложные, а понять огромные триггеры сложно. Я даже понять не могу как вы такие сложные триггеры делаете. Я в основном в редакторе объектов сижу, и чуть-чуть ы триггерах. Ну спасибо за то, что хотя бы потратили на меня время.
0
26
4 года назад
0
без триггеров можете вообще забыть о чем либо нестандартном
0
22
4 года назад
0
Qulore:
Открываешь статьи по Jass
Открываешь наработки на Jass
Учишься
Чтобы оставить комментарий, пожалуйста, войдите на сайт.