Пытался сделать какое-то подобие спелла, но споткнулся об это:
TimerStart(ti,0.01,false,null)
ta[tc] = CreateTrigger()
..registerTimerExpireEvent(ti)
при попытке добавления второго события в этот же триггер, вар крашится
TriggerRegisterUnitEvent(GetTriggeringTrigger(),t[co], EVENT_UNIT_DAMAGED)
Код на Wurst'e
раскрыть


function damageadder()
    int debug = 0
    int co = 0
    int h
    if debug == 0
        h = GetHandleId(GetExpiredTimer())
        DestroyTimer(GetExpiredTimer())
        co = LoadInteger(GHT,h,0)
        FlushChildHashtable(GHT,h)
        //TriggerRegisterUnitEvent(GetTriggeringTrigger(),t[co], EVENT_UNIT_DAMAGED)
        debug++
    /*if debug == 1
        debug++
        print("|cff009900co: "+I2S(co))
        if GetEventDamageSource() == da[co]
            print("|c00000000Damage?")
            UnitDamageTarget(c[co],t[co],dmg[co],true,false,pure,norm,wk)
            DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Orc\\SpiritLink\\SpiritLinkTarget.mdx", t[co], "origin"))
            DestroyTrigger(GetTriggeringTrigger())*/

function alliesQQ()
    unit ca = c[tc]
    tc++
    if tc >= 500
        tc = 0
    unit dummy
    unit u
    u=FirstOfGroup(al)
    GroupRemoveUnit(al,u)
    if u !=null
        dummy = createDummy(ca,null)
        UnitAddAbility(dummy,'A0A1')
        IssueTargetOrder(dummy,"thunderbolt",u)
        c[tc] = ca
        t[tc] = u
        da[tc] = dummy
        dmg[tc] = I2R(GetHeroAgi(c[tc],true)*1000)
        timer ti = CreateTimer()
        SaveInteger(GHT,GetHandleId(ti),0,tc)
        TimerStart(ti,0.01,false,null)
        ta[tc] = CreateTrigger()
        ..registerTimerExpireEvent(ti)
        ..addAction(function damageadder)
        ti = null
    DestroyTimer(GetExpiredTimer())
    print("Timer Destroyed.")

function actionsQQ()
    unit u
    tc++
    if tc >= 500
        tc = 0
    group g = CreateGroup()
    c[tc] = GetSpellAbilityUnit()
    GroupEnumUnitsInRange(g,GetUnitX(GetSpellAbilityUnit()),GetUnitY(GetSpellAbilityUnit()),1500+75.,null)
    for i = 0 to 20
        u=FirstOfGroup(g)
        print("i: "+I2S(i))
        print("u: "+GetUnitName(u))
        if u == null
            return
        GroupRemoveUnit(g,u)
        if isUnitAliveAndAlly(u,GetSpellAbilityUnit())
            GroupAddUnit(al,u)
            TimerStart(CreateTimer(),0.01,true,function alliesQQ)
    DestroyGroup(g)
    print("Enumed")
    print("Enemys: "+I2S(CountUnitsInGroup(en)))
    print("Allies: "+I2S(CountUnitsInGroup(al)))

init
    CreateTrigger()//Shot
    registerSpellEffectEvent('A0A2', function actionsQQ)
Может быть фича, может баг, но такое ещё не встречал

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

По коду честно говоря ничего не понятно. Но в отлове урона это обычная ошибка, когда урон наносится внутри триггера, отлавливающего урон или если он вызывает действия которые наносят урон и снова вызывают этот триггер. Бесконечная рекурсия в общем роняет игру.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
19
6 лет назад
0
Похожие вопросы:

ответ
bladget, блин, посмотри как все делают, примеров 100500.
ответ
Вам сюда, господин хороший. Там есть ответы, практически, на все ваши вопросы.
ответ
Дебаг где? Шторм болт наносит урон трижды, сначала урон который указан в настройках способности, тут же еще 0.00 урона, и получая бафф, после окончания баффа еще раз 0.00 урона. Триггер нужно отключать, или действия делать в кондишене а в акшене удалять из триггера.
ответ
Ну только триггерные системы отрядов, была такая...
Вот пример ссылочка
Были и другие, поиск в помощь.
Вот еще ссылка

1
32
6 лет назад
1
Просите какая то ерунда, вы пытаетесь сделать стандартный снаряд?
Есть метод проще, да еще одно но, при касте негативной абилки - сначала 0.00 урона в цель, потом после попадания 0.00 урона + дебафф если он есть. Проверили бы все обьекты, да и откуда GetTriggeringTrigger() в потоке вызванном таймером?
Я юзаю примерно следующий код:
Dummy Missile
scope DummyMissile

    function AddTimedAnimation takes nothing returns nothing
        local timer t = GetExpiredTimer( )
        call SetUnitAnimation( LoadUnitHandle( gg_htb_HashData, GetHandleId(t), 0  ), "spell" )
        call FlushChildHashtable( gg_htb_HashData, GetHandleId(t) )
        call DestroyTimer(t)
        
        set t = null
    endfunction


    struct DMD
        trigger trg
        triggercondition trc
        triggeraction tra
        triggeraction extra
        unit cast
        unit targ
        unit ex
        integer id
        timer trix
        boolean del
            
        method FlushData takes nothing returns nothing
            call DisableTrigger( .trg )
            call TriggerRemoveCondition( .trg, .trc )
            call TriggerRemoveAction( .trg, .tra )
            call TriggerRemoveAction( .trg, .extra )
            call TriggerClearActions( .trg )
            call TriggerClearConditions( .trg )
            call RemoveDataBX( .trg )
            call RemoveDataBX( .trix )
            call DestroyTrigger( .trg )
            call DestroyTimer( .trix )

            set this.trg = null
            set this.trc = null
            set this.tra = null
            set this.extra = null
            set this.cast = null
            set this.targ = null
            set this.ex = null
            set this.trix = null
            set this.id = 0
            set this.del = false
        endmethod
    endstruct

    function IsTargetHasBuff takes nothing returns boolean
        local DMD st = GetDataBX( GetTriggeringTrigger( ) )
        set bj_lastEventId = GetTriggerEventId( )
        
        if bj_lastEventId == EVENT_WIDGET_DEATH then
            call TriggerRemoveAction( st.trg, st.tra )
            return true
        endif
        
        if bj_lastEventId == EVENT_UNIT_DAMAGED then
            if  GetEventDamageSource( ) == DummyAttacker then
                return false
            elseif GetEventDamage( ) == 0.00 and GetEventDamageSource( ) == st.cast  and GetUnitAbilityLevel( st.targ, 'BNss' ) > 0  then
                call TriggerRemoveAction( st.trg, st.tra )
                return true
            endif
        endif
    
        return GetEventDamage( ) == 0.00 and GetUnitAbilityLevel( st.targ, st.id ) > 0 and GetEventDamageSource( ) == st.cast 
    endfunction

    function Destroy_DMD takes nothing returns nothing
        local DMD st = GetDataBX( GetExpiredTimer( ) )
        call st.FlushData( )
        call st.destroy( )
    endfunction
    
    function RemoveDMDBuff takes nothing returns nothing
        local DMD st = GetDataBX( GetTriggeringTrigger( ) )
        if st.del then
            call UnitRemoveAbility( st.targ, st.id )
        endif
        call PauseTimer( st.trix )
        call DisableTrigger( st.trg )
        call TimerStart( st.trix, 10.00, false, function Destroy_DMD )
        return
    endfunction
    
    function DummyMissile takes unit target, unit caster, integer buffid, real time, boolean del, code actions returns nothing
        local DMD st = DMD.create( )
        set st.cast = caster
        set st.targ = target
        set st.id = buffid
        set st.del = del
        set st.trix = CreateTimer( )
        set st.trg = CreateTrigger( )
        set st.trc = TriggerAddCondition( st.trg, Condition( function IsTargetHasBuff ) )
        set st.tra = TriggerAddAction( st.trg, actions )
        set st.extra = TriggerAddAction( st.trg, function RemoveDMDBuff )
        call TriggerRegisterUnitEvent( st.trg, target, EVENT_UNIT_DAMAGED )
        //call TriggerRegisterUnitEvent( st.trg, target, EVENT_UNIT_SPELL_EFFECT)
        call TriggerRegisterDeathEvent( st.trg, target )
        call TimerStart( st.trix, time, false, function Destroy_DMD )
        call SetDataBX( st.trg, st )
        call SetDataBX( st.trix, st )
    endfunction
    
    function Timer_DummyMovement_Expires takes nothing returns nothing
        local TriggerData dd = GetDataBX( GetExpiredTimer( ) )
        
        set dd.time = dd.time + 1
        
        if not IsUnitDead( dd.attacker ) then
            call SetUnitX( dd.dummy, GetUnitX( dd.attacker ) )
            call SetUnitY( dd.dummy, GetUnitY( dd.attacker ) )
        endif
        
        if dd.time > 64 then
            call PauseTimer( dd.trix )
            call RemoveDataBX( dd.trix )
            call DestroyTimer(  dd.trix)
        endif
        
    endfunction 
    
    function DummyMissileEx_Check_Buff_Codnditions takes nothing returns boolean
        local TriggerData st = GetDataBX( GetTriggeringTrigger( ) )
        set bj_lastEventId = GetTriggerEventId( )
        
        if bj_lastEventId == EVENT_WIDGET_DEATH or bj_lastEventId == EVENT_GAME_TIMER_EXPIRED then
            call TriggerRemoveAction( st.trg, st.tra )
            return true
        endif
        
        if bj_lastEventId == EVENT_UNIT_DAMAGED then
            if  GetEventDamageSource( ) != st.dummy then
                return false
            elseif GetEventDamage( ) == 0.00 and GetEventDamageSource( ) == st.dummy  and GetUnitAbilityLevel( st.attacked, 'BNss' ) > 0  then
                call TriggerRemoveAction( st.trg, st.tra )
                return true
            endif
        endif
        
        return GetEventDamage( ) >= 0.00 and GetUnitAbilityLevel( st.attacked, st.id ) > 0 and GetEventDamageSource( ) == st.dummy 
        return false
    endfunction
    
    function DummyMissileEx_ExtraActions takes nothing returns nothing
        local TriggerData st = GetDataBX( GetTriggeringTrigger( ) )
        
        call DisableTrigger( st.trg )
        
        if st.trix != null then
            call PauseTimer(st.trix)
            call RemoveDataBX( st.trix )
            call DestroyTimer(st.trix)
        endif
        
        if not IsUnitDead( st.attacked ) then
            if GetUnitAbilityLevel( st.attacked, st.id ) > 0 then
                call UnitRemoveAbility( st.attacked, st.id )
            endif
        endif
    
        call RemoveUnit( st.dummy )
    
        call st.RemoveTrigger()
        call st.destroy()
    endfunction
    
    function DummyMissileEx takes unit target, unit caster, boolean spell, integer missileid, integer order, integer buffid, code actions returns boolean
        local TriggerData st = TriggerData.create()
        local timer t
        local boolean b = false
        
        if spell then
            set t= CreateTimer( )
            call SaveUnitHandle( gg_htb_HashData, GetHandleId(t),0, caster )
            call TimerStart( t, 0.10, false, function AddTimedAnimation )
            set t = null
        endif
        
        set st.attacker = caster
        set st.attacked = target
        set st.id = buffid
        set st.pl = GetOwningPlayer( st.attacker )
        set TempAX = GetUnitX( st.attacker )
        set TempAY = GetUnitY( st.attacker )
        set st.dummy = CreateUnit( st.pl, 'hatk',TempAX,TempAY,GetUnitFacing(st.attacked))
        set st.trg = CreateTrigger( )
        set st.trc = TriggerAddCondition( st.trg, Condition( function DummyMissileEx_Check_Buff_Codnditions  ) )
        set st.tra = TriggerAddAction( st.trg, actions )
        set st.extra = TriggerAddAction( st.trg, function DummyMissileEx_ExtraActions )
        set st.trix = CreateTimer() 
         
        call SetUnitPathing(st.dummy, false)
        call SetUnitX(st.dummy,TempAX)
        call SetUnitY(st.dummy,TempAY)
        call UnitApplyTimedLife(st.dummy, 'BTLF', 10.00 )
        call UnitAddAbility( st.dummy, missileid )
        
        call UnitShareVision( st.attacked, st.pl, true )
        set b = IssueTargetOrderById( st.dummy, order, st.attacked )  // incenerate arrow
        call UnitShareVision( st.attacked, st.pl, false )
        
        call TriggerRegisterDeathEvent( st.trg, st.attacked )
        call TriggerRegisterUnitEvent( st.trg, st.attacked, EVENT_UNIT_DAMAGED )
        call TriggerRegisterTimerEvent( st.trg, 10.00, false )
        
        call SetDataBX( st.trg, st )
        
        if b then
            call SetDataBX( st.trix, st )
            set st.time = 1
            call TimerStart( st.trix, 0.03125, true, function Timer_DummyMovement_Expires )
        endif
    
        return b
    endfunction

endscope
Первый вариант - когда юнит сам кастует спелл, второй когда спелл кастует даммик.
3
17
6 лет назад
Отредактирован GetLocalPlayer
3
По коду честно говоря ничего не понятно. Но в отлове урона это обычная ошибка, когда урон наносится внутри триггера, отлавливающего урон или если он вызывает действия которые наносят урон и снова вызывают этот триггер. Бесконечная рекурсия в общем роняет игру.
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.