Такой вопрос. Я пытаюсь сделать щит, который блокирует входящий урон. Я решил это сделать триггерно, через востановление хп, но проблема в том, что в редакторе есть только условие юнит атакован, которое срабатывает в момент до атаки, когда приказ отдан и юнит начинает атаковать. Проблема в том, что я не могу найти команду на проверку урона (приходиться считать из вычитания хп) и не могу найти команду - юнит полчает урон или что-то в этом роде, а не атакован. Без этого выходит, что противник наносящий урон медленно не триггерит щит и это выглядит некрасиво. Вопрос в том, что есть ли команда на принятие входящего урона в момент его получения, а если нет, то как это заменить?

Событие юнит получает урон регистрируется на конкретного юнита.
Для того что бы отлавливать урон по цели твоего "щита", нужно создать для цели (т.е. для того юнита, на которого накладывают щит) отдельное событие на получением им урона. И делать это надо именно в тот момент, когда ты накладываешь щит.
Для этого есть функция добавить событие в триггер, в ней можно указать конкретного юнита и само событие получения урона. Дальше тебе придётся только лишь определить был ли юнит в момент получения урона под действием "щита" и дальше блокировать урона (восстанавливать хп юнита).
Так же надо отметить момент, что если ты для юнита создаёшь больше ОДНОГО события на получение урона - они будут работать каждый сам по себе (т.е. при получении урона 1 раз, будут срабатывать 2 события, и триггер будет срабатывать ДВА раза = больше события и больше срабатываний в один момент времени).
Для этого надо маркеровать юнитов, для которых создаётся событие на получение урона (например заносить их в группу юнитов, а перед этим проверять есть ли юнит в этой группе).
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
32
Было довольно много информации по теме урона, вот один пример ссылка
Суть - Событие - Юнит получает урон, далеко не всегда удобно создавать 1 триггер на всех юнитов, и их создают динамически, по 1 для одного или нескольких юнитов, а затем удаляют.
12
Extremator:
Событие юнит получает урон регистрируется на конкретного юнита.
Для того что бы отлавливать урон по цели твоего "щита", нужно создать для цели (т.е. для того юнита, на которого накладывают щит) отдельное событие на получением им урона. И делать это надо именно в тот момент, когда ты накладываешь щит.
Для этого есть функция добавить событие в триггер, в ней можно указать конкретного юнита и само событие получения урона. Дальше тебе придётся только лишь определить был ли юнит в момент получения урона под действием "щита" и дальше блокировать урона (восстанавливать хп юнита).
Так же надо отметить момент, что если ты для юнита создаёшь больше ОДНОГО события на получение урона - они будут работать каждый сам по себе (т.е. при получении урона 1 раз, будут срабатывать 2 события, и триггер будет срабатывать ДВА раза = больше события и больше срабатываний в один момент времени).
Для этого надо маркеровать юнитов, для которых создаётся событие на получение урона (например заносить их в группу юнитов, а перед этим проверять есть ли юнит в этой группе).
Вот мой код на момент навешивания щита:
function Trig_Unholy_shield_1_Jass_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A00V' ) ) then
return false
endif
return true
endfunction
function Trig_Unholy_shield_1_Jass_Actions takes nothing returns nothing
local real shieldBlock Число, которое показывает колличество блокируемого урона
local real hp Число, которое показывает колличество жизней юнита на момент наложения щита
local unit w = GetSpellTargetUnit() Юнит, на которого повешен щит
local integer h Нужна для проверки соответствия после
local integer j = GetHandleId(w) Узнаём ID юнита, на которого повешен щит
set shieldBlock = 150.00
set hp = GetUnitStateSwap(UNIT_STATE_LIFE, GetSpellTargetUnit())
set h = j
call SaveUnitHandle(udg_hash,j,1,w)
call SaveReal(udg_hash,j,2,shieldBlock)
call SaveReal(udg_hash,j,3,hp)
call SaveInteger(udg_hash,j,4, h)
set w = null
call EnableTrigger( gg_trg_Unholy_shield_2_v2_Jass )
endfunction
===========================================================================
function InitTrig_Unholy_shield_1_Jass takes nothing returns nothing
set gg_trg_Unholy_shield_1_Jass = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Unholy_shield_1_Jass, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Unholy_shield_1_Jass, Condition( function Trig_Unholy_shield_1_Jass_Conditions ) )
call TriggerAddAction( gg_trg_Unholy_shield_1_Jass, function Trig_Unholy_shield_1_Jass_Actions )
endfunction
А это код для срабатывания щита:
function Trig_w_Actions takes nothing returns nothing
local unit attacked = GetAttackedUnitBJ()
local integer j = GetHandleId(attacked)
local real hpA = GetUnitStateSwap(UNIT_STATE_LIFE, GetAttackedUnitBJ())
local real uron
local unit a = LoadUnitHandle(udg_hash, j,1)
local real shieldBlock = LoadReal(udg_hash, j,2)
local real hp = LoadReal(udg_hash, j,3)
local integer h = LoadInteger(udg_hash, j,4)
local real Yron2

set uron = ( hp - hpA )
if ( shieldBlock > 0.00 ) then
if ( shieldBlock > uron) then
call SetUnitLifeBJ( GetAttackedUnitBJ(), ( GetUnitStateSwap(UNIT_STATE_LIFE, GetAttackedUnitBJ()) + uron ) )
set shieldBlock = ( shieldBlock - uron )
call SaveReal(udg_hash,j,2,shieldBlock)
else
set Yron2 = (uron - shieldBlock)
call SetUnitLifeBJ( GetAttackedUnitBJ(), ( GetUnitStateSwap(UNIT_STATE_LIFE, GetAttackedUnitBJ()) + Yron2 ) )
set shieldBlock = ( shieldBlock - uron )
call SaveReal(udg_hash,j,2,shieldBlock)
endif
else
if ( shieldBlock <= 0.00 ) then
call UnitRemoveBuffBJ( 'B009', GetTriggerUnit() )
endif
endif

endfunction
===========================================================================
function InitTrig_Unholy_shield_2_v2_Jass takes nothing returns nothing
set gg_trg_Unholy_shield_2_v2_Jass = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Unholy_shield_2_v2_Jass, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddAction( gg_trg_Unholy_shield_2_v2_Jass, function Trig_w_Actions )
endfunction
Я не до конца понимаю несколько вещей. Где мне найти функцию на добавление в триггер и как проверить наложен ли щит(я только так придумал), т.к. не знаю как проверить имеется ли щит на юните.
Понимаю что много прошу. но всё же, можно разьяснить это в коде? Пожалуйста

Стас Орлов:
Extremator:
Событие юнит получает урон регистрируется на конкретного юнита.
Для того что бы отлавливать урон по цели твоего "щита", нужно создать для цели (т.е. для того юнита, на которого накладывают щит) отдельное событие на получением им урона. И делать это надо именно в тот момент, когда ты накладываешь щит.
Для этого есть функция добавить событие в триггер, в ней можно указать конкретного юнита и само событие получения урона. Дальше тебе придётся только лишь определить был ли юнит в момент получения урона под действием "щита" и дальше блокировать урона (восстанавливать хп юнита).
Так же надо отметить момент, что если ты для юнита создаёшь больше ОДНОГО события на получение урона - они будут работать каждый сам по себе (т.е. при получении урона 1 раз, будут срабатывать 2 события, и триггер будет срабатывать ДВА раза = больше события и больше срабатываний в один момент времени).
Для этого надо маркеровать юнитов, для которых создаётся событие на получение урона (например заносить их в группу юнитов, а перед этим проверять есть ли юнит в этой группе).
Вот мой код на момент навешивания щита:
function Trig_Unholy_shield_1_Jass_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A00V' ) ) then
return false
endif
return true
endfunction
function Trig_Unholy_shield_1_Jass_Actions takes nothing returns nothing
local real shieldBlock Число, которое показывает колличество блокируемого урона
local real hp Число, которое показывает колличество жизней юнита на момент наложения щита
local unit w = GetSpellTargetUnit() Юнит, на которого повешен щит
local integer h Нужна для проверки соответствия после
local integer j = GetHandleId(w) Узнаём ID юнита, на которого повешен щит
set shieldBlock = 150.00
set hp = GetUnitStateSwap(UNIT_STATE_LIFE, GetSpellTargetUnit())
set h = j
call SaveUnitHandle(udg_hash,j,1,w)
call SaveReal(udg_hash,j,2,shieldBlock)
call SaveReal(udg_hash,j,3,hp)
call SaveInteger(udg_hash,j,4, h)
set w = null
call EnableTrigger( gg_trg_Unholy_shield_2_v2_Jass )
endfunction
===========================================================================
function InitTrig_Unholy_shield_1_Jass takes nothing returns nothing
set gg_trg_Unholy_shield_1_Jass = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Unholy_shield_1_Jass, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Unholy_shield_1_Jass, Condition( function Trig_Unholy_shield_1_Jass_Conditions ) )
call TriggerAddAction( gg_trg_Unholy_shield_1_Jass, function Trig_Unholy_shield_1_Jass_Actions )
endfunction
А это код для срабатывания щита:
function Trig_w_Actions takes nothing returns nothing
local unit attacked = GetAttackedUnitBJ()
local integer j = GetHandleId(attacked)
local real hpA = GetUnitStateSwap(UNIT_STATE_LIFE, GetAttackedUnitBJ())
local real uron
local unit a = LoadUnitHandle(udg_hash, j,1)
local real shieldBlock = LoadReal(udg_hash, j,2)
local real hp = LoadReal(udg_hash, j,3)
local integer h = LoadInteger(udg_hash, j,4)
local real Yron2

set uron = ( hp - hpA )
if ( shieldBlock > 0.00 ) then
if ( shieldBlock > uron) then
call SetUnitLifeBJ( GetAttackedUnitBJ(), ( GetUnitStateSwap(UNIT_STATE_LIFE, GetAttackedUnitBJ()) + uron ) )
set shieldBlock = ( shieldBlock - uron )
call SaveReal(udg_hash,j,2,shieldBlock)
else
set Yron2 = (uron - shieldBlock)
call SetUnitLifeBJ( GetAttackedUnitBJ(), ( GetUnitStateSwap(UNIT_STATE_LIFE, GetAttackedUnitBJ()) + Yron2 ) )
set shieldBlock = ( shieldBlock - uron )
call SaveReal(udg_hash,j,2,shieldBlock)
endif
else
if ( shieldBlock <= 0.00 ) then
call UnitRemoveBuffBJ( 'B009', GetTriggerUnit() )
endif
endif

endfunction
===========================================================================
function InitTrig_Unholy_shield_2_v2_Jass takes nothing returns nothing
set gg_trg_Unholy_shield_2_v2_Jass = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Unholy_shield_2_v2_Jass, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddAction( gg_trg_Unholy_shield_2_v2_Jass, function Trig_w_Actions )
endfunction
Я не до конца понимаю несколько вещей. Где мне найти функцию на добавление в триггер и как проверить наложен ли щит(я только так придумал), т.к. не знаю как проверить имеется ли щит на юните.
Понимаю что много прошу. но всё же, можно разьяснить это в коде? Пожалуйста
Понимаю, что код не идеален, сам много особенностей нашёл. например, что он востанавливает хп, но если вылечить, то он вернёт хп к тому моменту, когда щит наложили. И если юнита убивают под щитом, то щит не поможет
32
Чувак, ваще не тот подход к созданию подобного спела, смотри готовые примеры.
Потом конверты гуи не юзай.

Вот код из моей карты, это щит блокирующий определенное кол-во урона, еще и показывающий визуальный граффик позлащенного урона.
Пример
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
P.S тут событий триггера нет на каст способности, ибо тут несколько иная реализация.
12
quq_CCCP:
Чувак, ваще не тот подход к созданию подобного спела, смотри готовые примеры.
Потом конверты гуи не юзай.

Вот код из моей карты, это щит блокирующий определенное кол-во урона, еще и показывающий визуальный граффик позлащенного урона.
Пример
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
P.S тут событий триггера нет на каст способности, ибо тут несколько иная реализация.
Большое спасибо, буду учиться. А где можно найти все команды Jass?
32
Стас Орлов,
Большое спасибо, буду учиться. А где можно найти все команды Jass?
ссылка
12
DamageData
Что такое DamageData и TriggerData?? Такого типа переменных нет и мне выдаёт ошибку
32
Структуры куда ведется запись данных чтобы передавать их между потоками таймера \ триггеров.

Ну пока не морочь голову конкретными функциями и стилистикой написания кода, твоя задача понять базовый алгоритм.
Что сперва ты ждешь пока юнит применит скилл, ты записываешь в хештаблицу этого юнита, все нужные данные, а так же создаешь для него отдельный триггер, которому ставишь события, что юнит умер, юнит получает урон, время вышло, ну добавляешь триггеру условия, действия, где производишь манипуляции с юнитом в зависмости от события, на которое сработал триггер.
При уроне выше 0 и от нужных тебе юнитов, вручаешь юниту способность на 100500 хп (в моем случае я сделал способность с ро кодом 'Amhp' на 150000 хп), записываешь в хештаблицу кол-во здоровья перед ударом, и запускаешь таймер на 0.00 секунд, как он кончится, удаляешь способность и разумеется устанавливаешь хп - сколько было.

В коде это хорошо видно. На всякие там фишечки и визуалки не обращай внимания тебе еще рано.
Возможны и другие реализации когда один триггер обслуживает сразу множество юнитов, к примеру отвечает за каку-нибудь пассивку на атаку вроде крита или баша (кастомного), у крипов коих десятки. Да такие варианты лучше, но они гораздо сложнее, и я не советую начинающим рассматривать их.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.