XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Закрытая тема
 
ARHUI

offline
Опыт: 3,341
Активность:
Заклинание с прожектилом. Лаги.
Башня стреляет с атакой 0, определяется какая башня (из 5 уровней) стреляла, вычисляется коэффициент k, который задает эти уровни для урона и отбрасывания, появляется даммик который летит к юниту, по которому башня стреляла, если юнит-цель умер во время полёта даммика, то он все равно долетает до его позиции и взрывается. При взрыве последовательно увеличивается радиус области, каждый раз берутся юниты в области, даммик наносит им урон, и позиция юнита меняется. Все просто в теории...
Играло нас 8 человек... Башен было штук 15, но лаги были шопясдох. Оперативы вар выделил 900 метров! Я подумал, что скорей всего даммики не удаляются, но нет! Проверив их численность после тестового запуска с ~40 башнями и ~300 крипами, я убедился, что даммики удаляются, то есть после сумасшедших лагов количество даммиков на карте равнялось 0. Все умершие крипы через 0.7сек удаляются из игры, однако после такого тестового побоища, которое длилось около минуты, оперативы съедено было 350 метров.
» Вот код, подскажите где я там совершил те ужасные ошибки, которые приводят к не менее ужасным лагам?
globals
    hashtable           ht                  =       InitHashtable()
    integer             loopsn              =       1000
endglobals

function MoveUnitToLocCallBack takes nothing returns nothing
    local timer         tm                  =       GetExpiredTimer( )
    local integer       pkey                =       GetHandleId( tm )
    local real          step                =       LoadReal( ht, pkey, 0 )
    local unit          dummy               =       LoadUnitHandle( ht, pkey, 1 )
    local integer       min_dist            =       LoadInteger( ht, pkey, 3 )
    local boolean       movement_type_flag  =       LoadBoolean( ht, pkey, 4 )
    local real          x1                  =       GetUnitX( dummy )
    local real          y1                  =       GetUnitY( dummy )
    local real          x2                  =       LoadReal(ht,pkey,2)
    local real          y2                  =       LoadReal(ht,pkey,5)
    local real          angle               =       Atan2( y2 - y1, x2 - x1 )
    local real          dst                 =       SquareRoot( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) )
    set x2 = x1 + Cos( angle ) * step
    set y2 = y1 + Sin( angle ) * step
    if dst <= 80 then 
        call FlushChildHashtable( ht, pkey )
        call FlushChildHashtable( ht, GetHandleId( dummy ) )
        call DestroyTimer( tm )
        call SetUnitAnimation( dummy, "stand" )
        call SetUnitTimeScale( dummy, 1 )
    else
        call SetUnitFacing( dummy, bj_RADTODEG * angle )
        if movement_type_flag != true then
            call SetUnitPosition( dummy, x2, y2 )
        else
            call SetUnitX( dummy, x2 )
            call SetUnitY( dummy, y2 )
        endif
    endif
    set tm = null
    set dummy = null
endfunction

function MoveUnitToLoc takes unit dummy, location target, real speed, integer min_dist, boolean movement_type_flag returns nothing
    local timer         tm                   =       CreateTimer()
    local integer       pkey                 =       GetHandleId( tm )
    local integer       dummy_handle         =       GetHandleId( dummy )
    local real          x1                   =       GetUnitX( dummy )
    local real          y1                   =       GetUnitY( dummy )
    local real          x2                   =       GetLocationX( target )
    local real          y2                   =       GetLocationY( target )
    local real          l                    =       SquareRoot( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) )
    local real          time                 =       l / speed
    local real          step                 =       l / loopsn
    local real          angle                =       Atan2( y2 - y1, x2 - x1 )
    if dummy_handle == GetHandleId( LoadUnitHandle( ht, dummy_handle, 0 ) ) then
        return
    endif
    call SetUnitFacing( dummy, bj_RADTODEG * angle )
    call SetUnitAnimationByIndex( dummy, 10 )
    call SetUnitTimeScale( dummy, ( speed / GetUnitDefaultMoveSpeed( dummy ) ) )
    call SaveReal( ht, pkey, 0, step)
    call SaveUnitHandle( ht, pkey, 1, dummy )
    call SaveReal( ht, pkey, 2, x2)
    call SaveReal( ht, pkey, 5, y2)
    call SaveInteger( ht, pkey, 3, min_dist )
    call SaveBoolean( ht, pkey, 4, movement_type_flag )
    call SaveUnitHandle( ht, dummy_handle, 0, dummy )
    call TimerStart( tm, ( time / loopsn ) , true, function MoveUnitToLocCallBack )
    set tm = null
endfunction

function MoveUnitToUnitCallBack takes nothing returns nothing
    local timer         tm                  =       GetExpiredTimer( )
    local integer       pkey                =       GetHandleId( tm )
    local real          step                =       LoadReal( ht, pkey, 0 )
    local unit          dummy               =       LoadUnitHandle( ht, pkey, 1 )
    local unit          target              =       LoadUnitHandle( ht, pkey, 2 )
    local integer       min_dist            =       LoadInteger( ht, pkey, 3 )
    local boolean       movement_type_flag  =       LoadBoolean( ht, pkey, 4 )
    local real          x1                  =       GetUnitX( dummy )
    local real          y1                  =       GetUnitY( dummy )
    local real          x2                  =       GetUnitX( target )
    local real          y2                  =       GetUnitY( target )
    local real          angle               =       Atan2( y2 - y1, x2 - x1 )
    local real          dst                 =       SquareRoot( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) )
    set x2 = x1 + Cos( angle ) * step
    set y2 = y1 + Sin( angle ) * step
    
    if (GetUnitState(target,UNIT_STATE_LIFE)<=0) then
        call FlushChildHashtable( ht, pkey )
        call FlushChildHashtable( ht, GetHandleId( dummy ) )
        call DestroyTimer( tm )
        call SetUnitAnimation( dummy, "stand" )
        call SetUnitTimeScale( dummy, 1 )
        call MoveUnitToLoc(dummy, Location(x2,y2), 2000.00, 1,  true)
        return
    endif
    
    if dst <= 80 then 
        call FlushChildHashtable( ht, pkey )
        call FlushChildHashtable( ht, GetHandleId( dummy ) )
        call DestroyTimer( tm )
        call SetUnitAnimation( dummy, "stand" )
        call SetUnitTimeScale( dummy, 1 )
    else
        call SetUnitFacing( dummy, bj_RADTODEG * angle )
        if movement_type_flag != true then
            call SetUnitPosition( dummy, x2, y2 )
        else
            call SetUnitX( dummy, x2 )
            call SetUnitY( dummy, y2 )
        endif
    endif
    set tm = null
    set dummy = null
    set target = null
endfunction

function MoveUnitToUnit takes unit dummy, unit target, real speed, integer min_dist, boolean movement_type_flag returns nothing
    local timer         tm                   =       CreateTimer()
    local integer       pkey                 =       GetHandleId( tm )
    local integer       dummy_handle         =       GetHandleId( dummy )
    local integer       target_handle        =       GetHandleId( target )
    local real          x1                   =       GetUnitX( dummy )
    local real          y1                   =       GetUnitY( dummy )
    local real          x2                   =       GetUnitX( target )
    local real          y2                   =       GetUnitY( target )
    local real          l                    =       SquareRoot( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) )
    local real          time                 =       l / speed
    local real          step                 =       l / loopsn
    local real          angle                =       Atan2( y2 - y1, x2 - x1 )
    if dummy_handle == GetHandleId( LoadUnitHandle( ht, dummy_handle, 0 ) ) then
        return
    endif
    call SetUnitFacing( dummy, bj_RADTODEG * angle )
    call SetUnitAnimationByIndex( dummy, 10 )
    call SetUnitTimeScale( dummy, ( speed / GetUnitDefaultMoveSpeed( dummy ) ) )
    call SaveReal( ht, pkey, 0, step)
    call SaveUnitHandle( ht, pkey, 1, dummy )
    call SaveUnitHandle( ht, pkey, 2, target )
    call SaveInteger( ht, pkey, 3, min_dist )
    call SaveBoolean( ht, pkey, 4, movement_type_flag )
    call SaveUnitHandle( ht, dummy_handle, 0, dummy )
    call TimerStart( tm, ( time / loopsn ) , true, function MoveUnitToUnitCallBack )
    set tm = null
endfunction



function ExplosionUnitCondition takes nothing returns boolean
if (GetOwningPlayer(GetFilterUnit())==Player(11)) && ( GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0 ) then
return true
else
return false
endif
endfunction


function ExplosionActions takes nothing returns nothing
    local timer tm = GetExpiredTimer()
    local integer pkey = GetHandleId( tm )
    local integer iteration = LoadInteger( ht, pkey, 0 )
    local real CurrentRadius = LoadReal( ht, pkey, 1 )
    local real EpicenterX = LoadReal( ht, pkey, 2 )
    local real EpicenterY = LoadReal( ht, pkey, 3 )
    local unit dummy = LoadUnitHandle( ht, pkey, 4 )
    local real K = LoadReal( ht, pkey, 5 )
    local real EnemyX
    local real EnemyY
    local location NewEnemyLoc
    local unit enemy
    local group EnemiesGroup = CreateGroup()
    local real MoveDistance = Pow(bj_E,((-30*(iteration*0.01))*(0.01*Sin(Deg2Rad(iteration*0.01))+0.1*Cos(Deg2Rad(iteration*0.01))​)))*20*(I2R(1)/K)
    //call DisplayTextToPlayer(Player(0),0,0,R2S(CurrentRadius))
    set CurrentRadius = CurrentRadius + MoveDistance
    call SaveReal( ht, pkey, 1, CurrentRadius )
    call GroupEnumUnitsInRange(EnemiesGroup,EpicenterX,EpicenterY,CurrentRadius,function ExplosionUnitCondition)
    loop
        set enemy = FirstOfGroup(EnemiesGroup)
        exitwhen enemy == null
        set EnemyX = GetUnitX(enemy) + ( CosBJ(AngleBetweenPoints(Location(EpicenterX, EpicenterY), GetUnitLoc(enemy))) * MoveDistance )
        set EnemyY = GetUnitY(enemy) + ( SinBJ(AngleBetweenPoints(Location(EpicenterX, EpicenterY), GetUnitLoc(enemy))) * MoveDistance )
        set NewEnemyLoc = Location(EnemyX,EnemyY)
        call SetUnitPositionLoc( enemy, NewEnemyLoc )
        call UnitDamageTarget(dummy, enemy, MoveDistance, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
        if (GetUnitState(enemy,UNIT_STATE_LIFE)>0)&&(MoveDistance < 0.5) then
            if ( GetDestructableLife(udg_gates[GetUnitUserData(enemy)]) > 0.00 ) then
                call IssueTargetOrderById( enemy, OrderId("attack"), udg_gates[GetUnitUserData(enemy)] )
            else
                call IssuePointOrderByIdLoc( enemy, OrderId("attack"), GetUnitLoc(udg_The_House) )
            endif
        endif
        call GroupRemoveUnit(EnemiesGroup,enemy)
    endloop
    if MoveDistance < 0.5 then
        call DestroyTimer(tm)
        local effect e = LoadEffectHandle(ht,pkey,6)
        call DestroyEffect(e)
        set e = null
        call FlushChildHashtable( ht, pkey )
        call RemoveUnit(dummy)

    else
            call SaveInteger(ht,pkey,0,iteration+1)
    endif
    call RemoveLocation(NewEnemyLoc)
    set NewEnemyLoc = null

    set tm = null
endfunction

function InitExplosionWave takes unit dummy, real k returns nothing
        local timer tm = CreateTimer()
        local integer pkey = GetHandleId(tm)
        local real x = GetUnitX( dummy )
        local real y = GetUnitY( dummy )
        local integer iteration = 0
        local real b = 0
        set bj_lastCreatedEffect = AddSpecialEffectLoc("SoulshotD-gradeTarget.mdx", Location(x,y))
        call SaveInteger(ht,pkey,0,iteration)
        call SaveReal(ht,pkey,1,b)
        call SaveReal(ht,pkey,2,x)
        call SaveReal(ht,pkey,3,y)
        call SaveUnitHandle(ht,pkey,4,dummy)
        call SaveReal(ht,pkey,5,k)
        call SaveEffectHandle(ht,pkey,6,bj_lastCreatedEffect)
        call TimerStart(tm,(I2R(10)/I2R(loopsn)),true,function ExplosionActions)
        set tm  = null
endfunction

function CreateExplosion takes nothing returns nothing
    local timer    tm                    =       GetExpiredTimer()
    local integer  pkey                  =       GetHandleId( tm )
    local unit     dummy                 =       LoadUnitHandle( ht, pkey, 0 )
    local real k = LoadReal(ht,pkey,1)

    call DestroyTimer(tm)
    call FlushChildHashtable(ht,pkey)
    //call DisplayTextToPlayer(Player(0),0,0,"on place")
    set tm = null
    call InitExplosionWave(dummy,k)
endfunction







function EarthquakeCast takes nothing returns nothing

    local timer      tm                  =       GetExpiredTimer()
    local integer pkey = GetHandleId( tm )
    local unit       dummy               =       LoadUnitHandle( ht, pkey, 0 )
    local real k = LoadReal(ht,pkey,1)
    call UnitAddAbility(  dummy, 'A00Z' )
    call IssuePointOrderByIdLoc(  dummy, OrderId("earthquake"), GetUnitLoc(dummy) )
    call KillUnit(dummy)
    call DestroyTimer(tm)
    call FlushChildHashtable(ht,pkey)
    set pkey = 0
    //call DisplayTextToPlayer(Player(0),0,0,"killed")
    set tm = null
    set tm = CreateTimer()
    set pkey = GetHandleId( tm )
    call SaveUnitHandle( ht, pkey, 0, dummy )
    call SaveReal( ht, pkey, 1, k )
    call TimerStart( tm, 0.05, false, function CreateExplosion )
    //call DisplayTextToPlayer(Player(0),0,0,"started2")
    set tm = null
endfunction


function ElectroTowerAttackReal takes nothing returns nothing
    local timer      tm                  =       GetExpiredTimer()
    local integer pkey = GetHandleId( tm )
    local unit       dummy               =       LoadUnitHandle( ht, pkey, 0 )
    local real k = LoadReal(ht,pkey,1)
    call UnitAddAbility(  dummy, 'A00Z' )
    call IssuePointOrderByIdLoc(  dummy, OrderId("earthquake"), GetUnitLoc(dummy) )
    call FlushChildHashtable(ht,pkey)
    set pkey = 0
    set tm = null
    set tm = CreateTimer()
    set pkey = GetHandleId( tm )
    call SaveUnitHandle( ht, pkey, 0, dummy )
    call SaveReal( ht, pkey, 1, k )
    call TimerStart( tm, 0.001, false, function EarthquakeCast )
    set tm = null
endfunction


function ElectroTowerAttack takes nothing returns nothing
    local unit dummy
    local location atacker_location = GetUnitLoc(GetAttacker())
    local location target_location = GetUnitLoc(GetTriggerUnit())
    local real x1=GetLocationX(atacker_location)
    local real y1=GetLocationY(atacker_location)
    local real x2=GetLocationX(target_location)
    local real y2=GetLocationY(target_location)
    local real speed = 2000
    local real dx = x1 - x2
    local real dy = y1 - y2
    local integer a = 0
    local real k
    local boolean IsAttackerNotATower = true
    loop
        exitwhen a == 5
        if GetUnitTypeId(GetAttacker()) == udg_ElectroTowerTypes[ a ] then
            set IsAttackerNotATower = false
            set k = (I2R(7)/(I2R(a+1)))
        endif
        set a = a + 1
    endloop
    if k == 7.00 then
        set k = 5
    endif
    if IsAttackerNotATower then
        //call DisplayTextToPlayer(Player(0),0,0,"not a tower")
        return
    endif
    local real time = (SquareRoot(dx * dx + dy * dy)/speed)
    set dummy=CreateUnitAtLoc(GetOwningPlayer(GetAttacker()),'e000',atacker_location, bj_UNIT_FACING )
    call SetUnitVertexColor(dummy, 128, 128, 128, 255)
    call SetUnitUserData( dummy, 123 )
    call MoveUnitToUnit( dummy, GetTriggerUnit(), speed, 1, true )
    local timer tm = CreateTimer()
    call SaveUnitHandle( ht, GetHandleId( tm ), 0, dummy )
    call SaveReal(ht,GetHandleId( tm ),1,k)
    call TimerStart( tm, time, false, function ElectroTowerAttackReal )
    set tm = null
    set dummy = null
    call RemoveLocation( atacker_location)
    call RemoveLocation( target_location)
    set  atacker_location = null
    set  target_location = null

endfunction

//===========================================================================
function InitTrig_InitElectroTowerAttacks takes nothing returns nothing
    set gg_trg_InitElectroTowerAttacks = CreateTrigger(  )
    call TriggerRegisterPlayerUnitEvent(gg_trg_InitElectroTowerAttacks, Player(11), EVENT_PLAYER_UNIT_ATTACKED, null)
    call TriggerAddAction( gg_trg_InitElectroTowerAttacks, function ElectroTowerAttack )
endfunction
ARHUI добавил:
Кода много, но в основном там повторения - сначала сделаю чтобы работало, потом напишу нормально...
Старый 30.04.2011, 23:02
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Код:
local location atacker_location = GetUnitLoc(GetAttacker())
    local location target_location = GetUnitLoc(GetTriggerUnit())
    local real x1=GetLocationX(atacker_location)
    local real y1=GetLocationY(atacker_location)
    local real x2=GetLocationX(target_location)
    local real y2=GetLocationY(target_location)


Что за индийский код? Тебе за каждую строчку кода отдельно платят чтоли?

Или попросту религия не позволяет сделать так:

Код:
local real x1=GetUnitX(GetAttacker())
    local real y1=GetUnitY(GetAttacker())
    local real x2=GetUnitX(GetTriggerUnit())
    local real y2=GetUnitY(GetTriggerUnit())



dummy нигде не удаляешь >_<

Дальше не стал смотреть, т.к. эт ппц.
Старый 30.04.2011, 23:16
ARHUI

offline
Опыт: 3,341
Активность:
Dummy передается, так сказать, из рук в руки и удаляется ф-ей взрыва
if MoveDistance < 0.5 then
        call DestroyTimer(tm)
        local effect e = LoadEffectHandle(ht,pkey,6)
        call DestroyEffect(e)
        set e = null
        call FlushChildHashtable( ht, pkey )
        call RemoveUnit(dummy)
else
...
Старый 30.04.2011, 23:21
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
ток не обнуляешь переменную dummy и вообще, юзай глобалки, что б в каждой функции заново не обновлять одни и те же значения.
Старый 30.04.2011, 23:32
ARHUI

offline
Опыт: 3,341
Активность:
Башни не подряд бьют, а когда придется, поэтому не нахожу способа использовать глобальные переменные, может поподробней?
Старый 01.05.2011, 01:31
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
ко второму посту могу еще предложить заменить пик на событие Unit Comes Within Range.
думаю при массовом применении это уменьшит лаги.
Старый 01.05.2011, 11:46
Doc

offline
Опыт: 63,163
Активность:
Unit Comes Within Range.
при массовом применении это создаст огромнейшие лаги.
fastfix*
Старый 01.05.2011, 13:02
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
с чего вдруг это создаст огромнейшие лаги ? 1 раз при создании снаряда повесить на него событие Unit Comes Within Range и двигать его к цели + можно еще сделать чтобы снаряд сталкивался с другими юнитами или просто наносил им урон, достаточно 1 условие добавить

Отредактировано Zanozus, 01.05.2011 в 14:40.
Старый 01.05.2011, 14:35
Doc

offline
Опыт: 63,163
Активность:
Zanozus, это баг вара, серьезно. много юнитов с таким событием -> один входит в радиус -> лаг на секунду. я просто тоже думал, что это лучше чем периодики, а в итоге вышла фигня.
Старый 01.05.2011, 14:57
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
лаг на сеунду
это в сетевой игре ? просто в одиночном тесте такого не было даже на моем старом полуживом компе с 50 снарядами на карте.

Отредактировано Zanozus, 01.05.2011 в 15:27.
Старый 01.05.2011, 15:17
Doc

offline
Опыт: 63,163
Активность:
Zanozus, в одиночной. ну у меня не 50 было, около сотни.
Старый 01.05.2011, 15:28
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
около 100 ?!
скачал свой старый гейзер из библиотеки, запустил, понатыкал гейзеров, где-то после 100 сбился со счета. Протащил крипов по гейзерам, разницы совершенно никакой что 1 что >100.
Может дело не в событии ? а то что передвигается больше 100 снарядов ? Возможно дело в спец. эффекте который появляется в событии, было такое пару раз. Или утечка.
Можешь скинуть пример в личку ?

Отредактировано Zanozus, 01.05.2011 в 15:58.
Старый 01.05.2011, 15:49
Doc

offline
Опыт: 63,163
Активность:
нет примера нету к сожалению.
Старый 01.05.2011, 17:04
ARHUI

offline
Опыт: 3,341
Активность:
Тоесть совет такой: изменить функцию взрыва - передавать в ExplosionActions из InitExplosionWave ещё и группу единожды взятых в конечном радиусе крипов, а в ф-ии ExplosionActions перебирать уже взятую группу и смотреть расстояние крипа от центра и если:
CurrentRadius > GetUnitX(enemy) + ( CosBJ(AngleBetweenPoints(Location(EpicenterX, EpicenterY), GetUnitLoc(enemy))) * MoveDistance )
то работать с этим крипом?
Таким образом убрать многократный GroupEnumUnitsInRange.
По поводу спецэффектов - у даммика нестандартная модель весом 20 кбайт, но разве это не "железная" проблема?
Кстати ForGroup быстрее чем loop-ом перебирать?
ARHUI добавил:
Есть причины чтобы группа не передавалась через hashtable ?
ARHUI добавил:
с группой разобрался
Старый 01.05.2011, 18:55
ARHUI

offline
Опыт: 3,341
Активность:
Решил проблему - тормоза были из-за движения прожектилов... ПОставил у башни снарядом нужную модель, а взрыв в позицию цели, все тормозов нет... Можно закрыть.
Старый 01.05.2011, 22:17
Закрытая тема

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 02:16.