Почему-то карта фаталит, если нанести триггерно несмертельный урон юниту, который был обработан данной функцией:
library SetUnitMaxState initializer Init

    globals
//      The rawcode of the life ability:
        private    constant    integer    MAX_STATE_LIFE_ABILITY    =    'A013'
        
//      The rawcode of the mana ability:
        private    constant    integer    MAX_STATE_MANA_ABILITY    =    'A014'
        
//      The maximum power of two the abilitys use:
        private    constant    integer    MAX_STATE_MAX_POWER       =    8
    endglobals

    globals
        private integer array PowersOf2
    endglobals

    function SetUnitMaxState takes unit u, unitstate state, real newValue returns nothing
        local integer stateAbility
        local integer newVal = R2I(newValue)
        local integer i = MAX_STATE_MAX_POWER
        local integer offset
        
        if state == UNIT_STATE_MAX_LIFE then
            set stateAbility = MAX_STATE_LIFE_ABILITY
        elseif state == UNIT_STATE_MAX_MANA then
            set stateAbility = MAX_STATE_MANA_ABILITY
        else
            return
        endif
        
        set newVal = newVal - R2I(GetUnitState(u, state))
        
        if newVal > 0 then
            set offset = MAX_STATE_MAX_POWER + 3
        elseif newVal < 0 then
            set offset = 2
            set newVal = -newVal
        else
            return
        endif

        loop
            exitwhen newVal == 0 or i < 0
            if newVal >= PowersOf2[i] then
                call UnitAddAbility(u, stateAbility)
                call SetUnitAbilityLevel(u, stateAbility, offset + i)
                call UnitRemoveAbility(u, stateAbility)
                set newVal = newVal - PowersOf2[i]
            else
                set i = i - 1
            endif
        endloop
    endfunction

    function AddUnitMaxState takes unit u, unitstate state, real addValue returns nothing
        call SetUnitMaxState(u, state, GetUnitState(u, state) + addValue)
    endfunction

    private function Init takes nothing returns nothing
        local integer i = 1
        
        set PowersOf2[0] = 1
        loop
            set PowersOf2[i] = PowersOf2[i - 1] * 2
            set i = i + 1
            exitwhen i == MAX_STATE_MAX_POWER + 3
        endloop
    endfunction

endlibrary

ScopteRectuS, ну как я и догадывался, что идет рекурсия.
10 событий - юнит получает урон, на одного юнита... Нужны именно такого типа проверки, всегда в условии триггера проверяй от кого урон и какой этот урон с помощью флага глобалки как в примере.В блоге лича хорошо описаны костыли доты, почитай для общего развития чтобы не наступать на эти грабли еще раз.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
32
ScopteRectuS, как то ты события криво вешаешь, сразу по несколько на 1 юнита походу. Карту в студию.
21
    function RegisterUnitDamaged takes unit whichUnit returns nothing
        local integer unitId = GetHandleId( whichUnit )

        if HaveSavedHandle( REGISTER_UNIT_DAMAGED_HASHTABLE, unitId, HASHTABLE_FLAG_KEY ) then
//          call BJDebugMsg("TriggerRegisterDamagedEvent(...) :    Attempt to add new event.")

        else
            call SaveTriggerEventHandle( REGISTER_UNIT_DAMAGED_HASHTABLE, unitId, HASHTABLE_FLAG_KEY, TriggerRegisterUnitEvent( gg_trg_UnitDamaged, whichUnit, EVENT_UNIT_DAMAGED ) )
        endif
    endfunction
на одном юните не может быть более одного повешанного события.
Загруженные файлы
28
ScopteRectuS, что за костыль?
нафига вообще тут хештейбл
ты когда вызываешь эту функцию?
и вообще
готовых систем 100500
нафига свои костыли придумывать?
21
Готовые системы вешают событие на всех юнитов, а я сделал так, чтобы вешало лишь на тех, на кого мне нужно
library RegisterUnitDamaged

//  GetEventDamageSource() - Источник урона (атаковавший юнит).
//  GetEventDamage()       - Величина нанесённого урона.
//  GetTriggerUnit()       - Цель урона (атакованный юнит).

    globals
        public    constant    hashtable    REGISTER_UNIT_DAMAGED_HASHTABLE    =    InitHashtable( )
        public    constant    integer      HASHTABLE_FLAG_KEY                 =    0
    endglobals

    function RegisterUnitDamaged takes unit whichUnit returns nothing
        local integer unitId = GetHandleId( whichUnit )

        if HaveSavedHandle( REGISTER_UNIT_DAMAGED_HASHTABLE, unitId, HASHTABLE_FLAG_KEY ) then
//          call BJDebugMsg("TriggerRegisterDamagedEvent(...) :    Attempt to add new event.")

        else
            call SaveTriggerEventHandle( REGISTER_UNIT_DAMAGED_HASHTABLE, unitId, HASHTABLE_FLAG_KEY, TriggerRegisterUnitEvent( gg_trg_UnitDamaged, whichUnit, EVENT_UNIT_DAMAGED ) )
        endif
    endfunction

    public function Actions takes nothing returns nothing
        call ConditionalTriggerExecute( gg_trg_GreedIsGood )
        call ConditionalTriggerExecute( StormHammer_TRIGGER )
    endfunction

endlibrary

function InitTrig_UnitDamaged takes nothing returns nothing
    set gg_trg_UnitDamaged = CreateTrigger()
    call TriggerAddAction( gg_trg_UnitDamaged, function RegisterUnitDamaged_Actions )
endfunction
21
Не знаю, нужно ли создавать новый вопрос, вообщем пишу сюда.
Подредактировал свой код под ваши указания, и карта перестала фаталится. Но обнаружилась другая проблема: сперва всё работает как надо, но в один момент снова начинается цепная реакция (рекурсия, но это не точно), но уже не фаталит, а просто убивает юнита. Дальше всё снова начинает работать как надо, но не надолго. После нескольких нормальных срабатываний триггера, срабатывает 1 с рекурсией, и всё по-новой.
Причину бага я нашёл, это происходило потому что юниту снова наносился триггерный урон, но уже совсем в другом триггере.
    set udg_IsDamaged = false
    call UnitDamageTarget( whichUnit, target, amount, attack, ranged, attackType, damageType, weaponType )
    set udg_IsDamaged = true
28
ScopteRectuS, можно юзать дефайны
define UnitDamageTarget(whichUnit, target, amount, attack, ranged, attackType, damageType, weaponType ) ={
	udg_IsDamaged = false;
	call Unit##DamageTarget( whichUnit, target, amount, attack, ranged, attackType, damageType, weaponType );
	udg_IsDamaged = true;
}
вставь это в шапку карты и если я написал правильно то оно при компиляции заменит все UnitDamageTarget на код в фигурных скобках
32
ScopteRectuS, ну как я и догадывался, что идет рекурсия.
10 событий - юнит получает урон, на одного юнита... Нужны именно такого типа проверки, всегда в условии триггера проверяй от кого урон и какой этот урон с помощью флага глобалки как в примере.В блоге лича хорошо описаны костыли доты, почитай для общего развития чтобы не наступать на эти грабли еще раз.
Принятый ответ
22
а чем не угодил менять урон числом а потом уже наносить последный урон... А то события ловит каждый урон так и появилось рекурсия
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.