Фаталит карта
Почему-то фаталит карта. Причину не могу сказать, даже примерно.
логи прилагаются:

Лучший ответ:
ScopteRectuS, нет, таймед лайф это своего рода бафф, он сам следит есть ли юнит. Если юнит сдохнет бафф самовыпилится самостоятельно, так что нет. Смотри баффы иллюзий и волков, они не проигрывают анимации смерти. Подбираешь бафф и все, анимации смерти невидно.
Хайдить тоже можно, под хайдом юнит нормально умирает и разлагается.



Просмотров: 251

XGM Bot #1 - 2 недели назад 0
Похожие вопросы:

» ответ
почему так долго грузится карта
Потому что огромный Нестандартные объекты может тысяч или больше или Спелл герой до 100 уровень.
из них 60 загрузка просто висит на 1/5.
Если нетак? Проверь если есть файлы war3map.j папка Game\WarcraftIII, надо удалить файл. очень давно тоже 1 раз что за вылет или неправильно выполняет триггер.
Есть способы ускорить загрузку карты не экономя в редакторе объектов
Есть Widgetizer, там очень быстрая загрузка игра, но плохо работает спелл или текст.
» ответ
Проблема решена.
» ответ
Было создано 22 366 679 экземпляров класса CUnitListNode, которые заняли 255.9 МБ памяти.
При очередной попытке выделения, игра упала.
Виной всему утечки памяти: за 21 минуту набралось 80 тысяч групп и 20 тысяч точек.
Также, из-за выполнения большого количества кода, сильно лагает.
На стадии выбора героя (первые две минуты), выполняется 550 000 операций в секунду, а далее — 1 200 000.
Для сравнения: лимит потока — 300 000 операций.
Хорошо, что ты приложил карту, так как в логе маловато информации.
» ответ
ScopteRectuS, ну как я и догадывался, что идет рекурсия.
10 событий - юнит получает урон, на одного юнита... Нужны именно такого типа проверки, всегда в условии триггера проверяй от кого урон и какой этот урон с помощью флага глобалки как в примере.В блоге лича хорошо описаны костыли доты, почитай для общего развития чтобы не наступать на эти грабли еще раз.

KingMaximax #2 - 2 недели назад (отредактировано ) 2
Хоть бы уточнили, когда происходит фатал. Какие примерно вы действия делали до того, как стала происходить данная ошибка. Причиной ошибки могут быть способности (нест. ясновидение тени) , кривой импорт, и т.п. Если у вас фаталит при инициализации, то это ещё может быть проблема в триггерах или вы списали в globals для переменной типа rect функцию GetWorldBounds()...
DracoL1ch #3 - 2 недели назад 2
при вхождении цели в область агра юнита у этой самой цели отсутствует объект с хп и игра крашится
разбирайся, кто к кому у тебя там подходит/появляется/саммонится перед фаталом
хз как этот объект может исчезнуть, в худшем случае это могла бы быть самоуничтожающаяся иллюзия, но в движке еще есть и incinerate, тоже удаляющий сходу из игры. Короче, проблема не совсем в тебе, но в событиях на приближение
ScopteRectuS #4 - 2 недели назад 0
DracoL1ch, на карте есть герой со способностью, которая создает дамми, проигрывающую анимацию атаки на враге, который атаковал героя. То есть дамми создается и удаляется через одну или две секунды, а при её создании ей дается неуязвимость. Может ли дамми оказаться причиной фатала?
типа дамми агрит врагов - враги агрятся. дамми получает нецязвимость - враг не может атаковать, как следствие - фатал ерор.
quq_CCCP #5 - 2 недели назад 2
ScopteRectuS, даммики не должны агрить врагов, москиты вовсе исключены из допустимых целей у всех юнитов...
ScopteRectuS #6 - 2 недели назад 0
quq_CCCP, ну у даммика изначально нету москитов, они добавляются после создания даммика. или это не важно? я подумал, что фатал успевает призойти между созданием дамми и добавлением москитов
quq_CCCP #7 - 2 недели назад 2
ScopteRectuS, а вручить сразу то не судьба?
Это вовсе странно нахрена делать в коде то что, изи делается в РО?
ScopteRectuS #8 - 2 недели назад 0
quq_CCCP, не могу так сделать. на самом деле мой даммик - это тот же самый герой, я не стал создавать нового юнита, а использую модель героя также и для даммика, вручая ему москитов и т.д.
quq_CCCP #9 - 2 недели назад 2
ScopteRectuS, а зачем тебе создавать героя ? Делать нефиг? Если это только анимация, создавай модель и проигрывай ей анимацию мемхаком или делай даммика с моделью героя, создание довольно ресурсозатрано если что.
ScopteRectuS #10 - 2 недели назад 0
quq_CCCP, мемхак убрал с карты, а использовал героя только для того, чтобы не создавать новую боевую единицу, захламляя редактор объектов. Когда в редакторе становится много объектов становится сложно разбираться во всем этом. Ну и собственно, мой первый вопрос, мог ли этот даммик быть причиной фатала?
quq_CCCP #11 - 2 недели назад 2
ScopteRectuS, а вот хрен его знает, пытайся повторить фатал, бери героя, юзай его способности по кд, пока не фатальнет, пиши лог.
Тогда станет понятно наверняка.
DracoL1ch #12 - 2 недели назад 2
это могло быть что угодно, без ограничений. если у тебя нет 100% рабочего способа повторить фатал, ты причину хер найдешь
ScopteRectuS #13 - 2 недели назад (отредактировано ) 0
DracoL1ch, 100% рабочего способа вызвать фатал у меня действительно нету. Но я нашел участок кода, при отключении которого, карта перестает критовать. Это был обычный триггер, который удалял юнита после его смерти, но сам этот триггер не критует, он начинает критовать только если герой прокачивает данный спелл.
» spell
scope Omnislash



    globals

//      Ability rawcode.
        private    constant    integer       SPELL_ID            =    'A00K'

//      Dummy image rawcode.
        private    constant    integer       DUMMY_ID            =    'o000'

//      Timer's period.
        private    constant    real          FPS                 =    0.03125

//      Times between slashes.
        private    constant    real          BASE_ATTACK_TIME    =    0.375

        private    constant    real          ENEMY_SEARCH_RADIUS    =    600.0

//      Blademaster's attack range.
        private    constant    real          ATTACK_RANGE        =    100.0

//      Effect on dealing damage.
        private    constant    string        EFFECT_01           =    "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl"

//      Effect on weapon.
        private    constant    string        EFFECT_02           =    "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"

//      Is damage attack?
        private    constant    boolean       ATTACK_FLAG         =    true

//      Is damage ranged?
        private    constant    boolean       RANGED_FLAG         =    false

//      Attack type.
        private    constant    attacktype    ATTACK_TYPE         =    ATTACK_TYPE_HERO

//      Damage type.
        private    constant    damagetype    DAMAGE_TYPE         =    DAMAGE_TYPE_NORMAL

//      Weapon type.
        private    constant    weapontype    WEAPON_TYPE         =    WEAPON_TYPE_METAL_HEAVY_SLICE

    endglobals



    private function GetUnitAttackDamage takes unit blademaster returns integer
        local  integer  agility  =  GetHeroAgi( blademaster, true )
        local  integer  sides    =  3
        local  integer  dice     =  3

        return GetRandomInt( ( agility + dice ), ( agility + dice * sides ) )
    endfunction



    private function GetAnimationIndex takes nothing returns integer
        local integer i = GetRandomInt( 0, 2 )

        if ( i == 0 ) then
            return 2

        elseif ( i == 1 ) then
            return 3
        endif

        return 8
    endfunction



    struct omnislashdummy
        private        unit     dummy
        private        integer  alpha
        private        effect   fx

        private        thistype prev
        private        thistype next

        private static timer    period = CreateTimer( )



        private method destroy takes nothing returns nothing
            call DestroyEffect( this.fx )
            call RemoveUnit( this.dummy )

            set this.fx        = null
            set this.dummy     = null

            set this.prev.next = this.next
            set this.next.prev = this.prev

            if ( thistype(0).next == 0 ) then
                call PauseTimer( period )
            endif

            call thistype.deallocate( this )
        endmethod



        private static method iterate takes nothing returns nothing
            local thistype this    = thistype(0).next

            loop
                exitwhen ( this == 0 )

                if ( this.alpha <= 0 ) then
                   call this.destroy( )
                else
                    set this.alpha = this.alpha - 8
                    call SetUnitVertexColor( this.dummy, 255, 255, 255, IMaxBJ( this.alpha, 0 ) )
                endif

                set this = this.next
            endloop
        endmethod



        static method create takes unit target, unit caster returns thistype
            local thistype this = thistype.allocate( )
            local real     x    = GetUnitX( target ) + GetRandomReal( -ATTACK_RANGE, ATTACK_RANGE )
            local real     y    = GetUnitY( target ) + GetRandomReal( -ATTACK_RANGE, ATTACK_RANGE )
            local real     f    = bj_RADTODEG * Atan2(GetUnitY( target ) - y , GetUnitX( target ) - x )

            set this.next = thistype(0)
            set this.prev = thistype(0).prev
            set this.next.prev = this
            set this.prev.next = this

            set this.dummy = CreateUnit( GetOwningPlayer( caster ), DUMMY_ID, x, y, f )
            set this.fx    = AddSpecialEffectTarget( EFFECT_02, this.dummy, "weapon" )
            set this.alpha = 255

            call PauseUnit( this.dummy, true )
            call UnitAddAbility( this.dummy, 'Amrf' )
            call UnitRemoveAbility( this.dummy, 'Amrf' )
            call SetUnitFlyHeight( this.dummy, GetUnitFlyHeight( target ), 0.0 )
//          call UnitAddAbility( this.dummy, 'Aloc' )
//          call SetUnitInvulnerable( this.dummy, true )
            call SetUnitPathing( this.dummy, false )
            call SetUnitAnimationByIndex( this.dummy, GetAnimationIndex( ) )

            if ( this.prev == 0 ) then
                call TimerStart( period, FPS, true, function thistype.iterate )
            endif

            return this
        endmethod



    endstruct



    struct omnislash
        private        unit     caster
        private        unit     target
        private        effect   fx
        private        integer  slash
        private        real     bat
        private        real     range
        private        real     casterX
        private        real     casterY
        private        real     targetX
        private        real     targetY

        private        thistype prev
        private        thistype next

        private static group    group   = CreateGroup( )
        private static timer    period  = CreateTimer( )
        private static trigger  trigger = CreateTrigger( )



        private method destroy takes nothing returns nothing
            call DestroyEffect( this.fx )
            call PauseUnit( this.caster, false )
//          call SetUnitInvulnerable( this.caster, false )
            call SetUnitPathing( this.caster, true )
            call SetUnitTimeScale( this.caster, 100 * 0.01)
            call SetUnitVertexColor( this.caster, 255, 255, 255, 255 )
            call SetUnitFlyHeight( this.caster, 0.0, 0.0 )

            set this.caster = null
            set this.target = null
            set this.fx     = null

            set this.prev.next = this.next
            set this.next.prev = this.prev

            if ( thistype(0).next == 0 ) then
                call PauseTimer( period )
            endif

            call thistype.deallocate( this )
        endmethod



        private static method getParabolaZ takes real maxHeight, real maxRange, real currentRange returns real
            return ( 4 * maxHeight / maxRange ) * ( maxRange - currentRange ) * ( currentRange / maxRange )
        endmethod



        private method getRandomUnitFromGroup takes nothing returns unit
            call GroupEnumUnitsInRange( thistype.group, this.casterX, this.casterY, ENEMY_SEARCH_RADIUS, null )

            loop
                set bj_groupRandomConsidered  = 0
                set bj_groupRandomCurrentPick = null
                call ForGroup( thistype.group, function GroupPickRandomUnitEnum )
                exitwhen ( bj_groupRandomCurrentPick == null ) or ( IsUnitEnemy( bj_groupRandomCurrentPick, GetOwningPlayer( this.caster ) ) and IsUnitAlive( bj_groupRandomCurrentPick ) and ( not IsUnitType( bj_groupRandomCurrentPick, UNIT_TYPE_STRUCTURE ) ) )
                call GroupRemoveUnit( thistype.group, bj_groupRandomCurrentPick )
            endloop

            call GroupClear( thistype.group )
            return bj_groupRandomCurrentPick
        endmethod



        private static method iterate takes nothing returns nothing
            local thistype this    = thistype(0).next

            local real     range

            loop
                exitwhen ( this == 0 )

                if ( this.slash > 0 ) and IsUnitAlive( this.caster ) then
                    call SetUnitFacing( this.caster, ( bj_RADTODEG * Atan2( this.targetY - this.casterY, this.targetX - this.casterX ) ) )

                    if ( this.bat <= 0.0 ) then
                        set this.targetX = GetUnitX( this.target )
                        set this.targetY = GetUnitY( this.target )
                        set range = SquareRoot( ( this.targetX - this.casterX ) * ( this.targetX - this.casterX ) + ( this.targetY - this.casterY ) * ( this.targetY - this.casterY ) )

                        if ( range <= 120 ) then
                            set this.casterX = this.targetX + GetRandomReal( -ATTACK_RANGE, ATTACK_RANGE )
                            set this.casterY = this.targetY + GetRandomReal( -ATTACK_RANGE, ATTACK_RANGE )
                            call SetUnitX( this.caster, this.casterX )
                            call SetUnitY( this.caster, this.casterY )
                            call SetUnitFlyHeight( this.caster, 0.0, 0.0 )
                            call omnislashdummy.create( this.target, this.caster )
                            call SetUnitAnimationByIndex( this.caster, GetAnimationIndex( ) )
                            call DestroyEffect( AddSpecialEffectTarget( EFFECT_01, this.target, "origin" ) )
                            call UnitDamageTarget( this.caster, this.target, ( GetHeroAgi( this.caster, true ) + 25.0 ), ATTACK_FLAG, RANGED_FLAG, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE )
                            set this.bat = BASE_ATTACK_TIME

                            set this.target = this.getRandomUnitFromGroup( )
                            if ( this.target != null ) then
                                set this.slash    =  ( this.slash - 1 )
                                set this.targetX  =  GetUnitX( this.target )
                                set this.targetY  =  GetUnitY( this.target )
                                set this.range    =  SquareRoot( ( this.targetX - this.casterX ) * ( this.targetX - this.casterX ) + ( this.targetY - this.casterY ) * ( this.targetY - this.casterY ) )

                            else
                                call this.destroy( )
                            endif

                        else
                            set this.casterX = this.casterX + 60.0 * ( ( this.targetX - this.casterX ) / range )
                            set this.casterY = this.casterY + 60.0 * ( ( this.targetY - this.casterY ) / range )
                            call SetUnitX( this.caster, this.casterX )
                            call SetUnitY( this.caster, this.casterY )
                            call SetUnitFlyHeight( this.caster, thistype.getParabolaZ( 180.0, this.range, ( this.range - range ) ), 0.0 )
                        endif

                    else
                        set this.bat = this.bat - FPS
                    endif

                else
                    call this.destroy( )
                endif

                set this = this.next
            endloop
        endmethod



        private static method actions takes nothing returns nothing
            local eventid  id          = GetTriggerEventId( )
            local thistype this
            local unit     blademaster
            local unit     attacker

            if ( id  == EVENT_PLAYER_UNIT_ATTACKED ) then
                set blademaster = GetTriggerUnit( )
                set attacker    = GetAttacker( )

                call omnislashdummy.create( attacker, blademaster )
                call UnitDamageTarget( blademaster, attacker, GetUnitAttackDamage( blademaster ), ATTACK_FLAG, RANGED_FLAG, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE )

                set blademaster = null
                set attacker    = null

            elseif ( id == EVENT_PLAYER_UNIT_SPELL_EFFECT ) then
                set this = thistype.allocate( )

                set this.next      = thistype(0)
                set this.prev      = thistype(0).prev
                set this.next.prev = this
                set this.prev.next = this

                set this.caster    = GetSpellAbilityUnit( )
                set this.casterX   = GetUnitX( this.caster )
                set this.casterY   = GetUnitY( this.caster )
                set this.target    = GetSpellTargetUnit( )
                set this.targetX   = GetUnitX( this.target )
                set this.targetY   = GetUnitY( this.target )
                set this.fx        = AddSpecialEffectTarget( EFFECT_02, this.caster, "weapon" )
                set this.slash     = GetUnitAbilityLevel( this.caster, SPELL_ID ) * 2 + 10
                set this.bat       = 0.0
                set this.range     = SquareRoot( ( this.targetX - this.casterX ) * ( this.targetX - this.casterX ) + ( this.targetY - this.casterY ) * ( this.targetY - this.casterY ) )

                call UnitAddAbility( this.caster, 'Amrf' )
                call UnitRemoveAbility( this.caster, 'Amrf' )
                call PauseUnit( this.caster, true )
//              call SetUnitInvulnerable( this.caster, true )
                call SetUnitPathing( this.caster, false )
                call SetUnitTimeScale( this.caster, 250 * 0.01 )
                call SetUnitVertexColor( this.caster, 255, 255, 255, 100 )

                if ( this.prev == 0 ) then
                    call TimerStart( period, FPS, true, function thistype.iterate )
                endif
            endif

            set id = null
        endmethod



        private static method conditions takes nothing returns boolean
            local eventid eventId     = GetTriggerEventId( )
            local unit    blademaster = GetTriggerUnit( )
            local integer chance      = GetUnitAbilityLevel( blademaster, SPELL_ID ) * 6 + 10
            local boolean b           = false

            if ( eventId == EVENT_PLAYER_UNIT_ATTACKED ) then
                set b = ( GetUnitAbilityLevel( blademaster, SPELL_ID ) > 0 ) and ( GetRandomReal( 0.0, 100.0 ) <= chance )

            elseif ( eventId == EVENT_PLAYER_UNIT_SPELL_EFFECT ) then
                set b = ( GetSpellAbilityId( ) == SPELL_ID )
            endif

            set eventId     = null
            set blademaster = null

            return b
        endmethod



        private static method onInit takes nothing returns nothing
            call PreloadAbility( SPELL_ID )
            call PreloadUnit( DUMMY_ID )
            call PreloadEffect( EFFECT_01 )

            call TriggerRegisterAnyUnitEventBJ( thistype.trigger, EVENT_PLAYER_UNIT_ATTACKED )
            call TriggerRegisterAnyUnitEventBJ( thistype.trigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )

            call TriggerAddCondition( thistype.trigger, Condition( function thistype.conditions ) )
            call TriggerAddAction( thistype.trigger, function thistype.actions )
        endmethod



    endstruct



endscope
также, если удалить этот триггер, удаляющий юнитов после смерти. А вместо него в редакторе констант выставить минимальные значения разложения трупа, то карта снова начинает критовать.

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

P.S.: это Omnislash Juggernaut'a из доты, правда немного изменённый. Также, у данной способности есть пассивная составляющая - каждый раз, когда героя атакуют, имеется какой-то шанс, контратаковать атакующего (создается даммик, который проигрывает анимацию атаки и врагу наносится урон).
Hate #14 - 2 недели назад 0
так ты без этого кода попробуй убить этого юнита, или удалить, и посмотри что будет
DracoL1ch #15 - 2 недели назад 2
Ээээ.. А нахера ты юнита удаляешь вручную? И время разложения надо ставить хотя бы долю секунды. Не надо выполнять за движок его работу, он сам всё нормально сделает, RemoveUnit максимально небезопасна. Это объясняет отсутствие объекта хп
ScopteRectuS #16 - 2 недели назад 0
DracoL1ch, причина удаления юнитов у меня странная, - мне не нравится трупы юнитов, которые везде валяются. Если юнитов нельзя удалять, то как мне спрятать юнита? Если спрятать юнита функцией ShowUnit(), удалится ли юнит после полного разложения его трупа? или же это функция может как-то воспрепятствовать удалению юнита движком игры?
quq_CCCP #17 - 2 недели назад 0
ScopteRectuS, TimedLife с баффом BTLF не не слышал?, при смерти рили можно хайдить, труп разложится как положено.
ScopteRectuS #18 - 2 недели назад 0
quq_CCCP, quq_CCCP, ну так я же хочу, чтобы не было трупа. а TimedLife просто убивает юнита, в моём случае, он попытается еще раз убить юнита, который уже мертв.
quq_CCCP #19 - 2 недели назад 2

ScopteRectuS, нет, таймед лайф это своего рода бафф, он сам следит есть ли юнит. Если юнит сдохнет бафф самовыпилится самостоятельно, так что нет. Смотри баффы иллюзий и волков, они не проигрывают анимации смерти. Подбираешь бафф и все, анимации смерти невидно.
Хайдить тоже можно, под хайдом юнит нормально умирает и разлагается.