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

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

Закрытая тема
 
KPOKODIL
В разработке
offline
Опыт: 10,262
Активность:
Проблема с работаспособностью спела
Всем хай
Дело в том, что я решил поучить хеш - таблицы, и поэтому создаю спелл - пассивку (15% при атаке по противнику создать гравитационное поле, попав в которое юнит зависает в возхдухе на 2 секунды, время жизни поля - 5 секунд)
Проблема в том, что при появления поля, все юниты в радиусе действия беспробудно паузятся, а подлетает в воздух ток 1. Помогите разобраться, а :)
» кодэ
function Trig_NullGravity_Conditions takes nothing returns boolean // Проверка для запуска спела
    if ( not ( GetUnitAbilityLevelSwapped('A001', GetAttacker()) > 0 ) ) then
        return false
    endif
    if ( not ( GetRandomReal(0, 100.00) <= 15.00 ) ) then
        return false
    endif
    return true
endfunction
function bct takes unit  cas, unit trg returns boolean // Проверка для запуска юнита в воздух
    if ( not ( IsUnitType(trg, UNIT_TYPE_STRUCTURE) == false ) ) then
        return false
    endif
    if ( not ( GetOwningPlayer(trg) != GetOwningPlayer(cas) ) ) then
        return false
    endif
    if ( not ( IsUnitAliveBJ(trg) == true ) ) then
        return false
    endif
    return true

endfunction
function NG_Fly takes nothing returns nothing // Фун-ция , в которой реализован полет.
    local timer TFly = GetExpiredTimer() // Таймер, который отвечает за время полета юнита
    local unit flyer = LoadUnitHandle (udg_hash, GetHandleId(TFly), 2) // Загружаем юнита из хеш - таблицы
    local real Hight = LoadReal (udg_hash, GetHandleId(flyer), 1) // Загружаем значение высоты полета
    if Hight < 300 then  // Поднимаем до 300-х
        set Hight = Hight + 10
        call SetUnitFlyHeightBJ(flyer, Hight, 100 )
        call SaveReal(udg_hash, GetHandleId(flyer), 1, Hight)
    else // Тут опускаем, и уничтожаем все что связанно с этим юнитом
        call DestroyTimer (TFly)
        call FlushChildHashtable(udg_hash, GetHandleId(TFly))
        call FlushChildHashtable(udg_hash, GetHandleId(flyer))
        call SetUnitFlyHeightBJ( flyer, 0.00, 0.00 )
        call UnitRemoveAbilityBJ( 'Aave', flyer )
        call PauseUnitBJ( false, flyer )
        call SetUnitPathing( flyer, true )

    endif
    set TFly = null
    set flyer = null
    set Hight = 0.00
endfunction



function NG_SpellRun takes nothing returns nothing
    local timer TSpell = GetExpiredTimer () // Отвечает за отлов юнитов для полета
    local integer count = LoadInteger (udg_hash, GetHandleId(TSpell), 6) // Счетчик для окончания спела
    local unit Effect = LoadUnitHandle (udg_hash, GetHandleId(TSpell), 2) // Спецэффект (юнит)
    local unit twr = LoadUnitHandle (udg_hash, GetHandleId(TSpell), 1) // Кастер
    local real X = LoadReal (udg_hash, GetHandleId(TSpell), 3) // Точка создания спецэффекта
    local real Y = LoadReal (udg_hash, GetHandleId(TSpell), 4)
    local group InFly = LoadGroupHandle (udg_hash, GetHandleId(TSpell), 5) // Тут юниты которые летают, либо отлетались
    local group Check = CreateGroup() // Группа для отлова новых "птичек"
    local unit Pop
    local timer TFly = CreateTimer() // Таймер полета юнита
    if count > 0 then // Пока действует спел, запускам цикл для поиска летчиков
        call SaveInteger (udg_hash, GetHandleId(TSpell), 6, count - 1)
        set Check = GetUnitsInRangeOfLocAll(150.00, Location(X, Y)) // Отлавливаем летчиков
        set Pop = FirstOfGroup (Check) // Дальше пробегаемся по группе, если там есть незарегистрированные, то отправляем их в группу пилотов
        loop
            exitwhen (Pop == null)
           if bct (twr,Pop) then
            if IsUnitInGroup(Pop, InFly) == false then
                call GroupAddUnitSimple (Pop, InFly)
                call UnitAddAbilityBJ( 'Aave', Pop )
                call PauseUnitBJ( true, Pop )
                call SetUnitPathing( Pop, false )
                call TimerStart (TFly, 0.05, true, function NG_Fly) // Создаем таймер для полета юнита
                call SaveUnitHandle(udg_hash, GetHandleId(TFly), 2, Pop) // Сохраняем нашего летчика для полета
                call SaveReal(udg_hash, GetHandleId(Pop), 1, GetUnitFlyHeight(Pop)) // Тут сохраняем стартовое значение высоты
             endif
            endif
            call GroupRemoveUnitSimple( Pop, Check )
            set Pop = FirstOfGroup (Check )
            call SaveGroupHandle (udg_hash,GetHandleId(TSpell),7,InFly) // Сохраняем группу для дальнейшей проверки
        endloop
    else
        call DestroyTimer (TSpell)
        call KillUnit (Effect)
        call FlushChildHashtable(udg_hash, GetHandleId(TSpell))
        call DestroyGroup (InFly)
        call DestroyTimer (TSpell)
    endif
    call DestroyGroup (Check)
    set X = 0.00
    set Y = 0.00
    set twr = null
    set Effect = null
    set count = 0
    set TFly = null
    set TSpell = null
endfunction

function Trig_NullGravity_Actions takes nothing returns nothing
    local unit twr = GetAttacker() 
    local real X = GetUnitX(GetAttackedUnitBJ())
    local real Y = GetUnitY(GetAttackedUnitBJ())
    local unit Effect = CreateUnit( GetOwningPlayer(twr) , 'e000', X, Y, bj_UNIT_FACING )
    local timer TSpell = CreateTimer()
    local group InFly = CreateGroup()
    call SaveUnitHandle (udg_hash, GetHandleId(TSpell), 1, twr)
    call SaveUnitHandle (udg_hash, GetHandleId(TSpell), 2, Effect)
    call SaveReal (udg_hash, GetHandleId(TSpell), 3, X)
    call SaveReal (udg_hash, GetHandleId(TSpell), 4, Y)
    call TimerStart (TSpell, 0.01, true, function NG_SpellRun)
    call SaveGroupHandle (udg_hash, GetHandleId(TSpell), 5, InFly)
    call SaveInteger (udg_hash, GetHandleId(TSpell), 6, 500)
    set twr = null
    set Effect = null
    set X = 0.00
    set Y = 0.00
    set TSpell = null
endfunction

//===========================================================================
function InitTrig_NullGravity takes nothing returns nothing
    set gg_trg_NullGravity = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_NullGravity, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_NullGravity, Condition( function Trig_NullGravity_Conditions ) )
    call TriggerAddAction( gg_trg_NullGravity, function Trig_NullGravity_Actions )
endfunction
P.S
Вот еще и карта

Отредактировано KPOKODIL, 07.10.2012 в 12:23.
Старый 06.10.2012, 19:55
Hate
конь вакуумный
offline
Опыт: 43,033
Активность:
пока не продебажите, не пишите
к этому всему рекомендую делать отступы в коде, почитать статьи по оптимизации кода, и еще раз прочитать статьи о жассе
Старый 06.10.2012, 20:00
Hanabishi
COOL STATUS
offline
Опыт: отключен
Mission impossibru
Инчае даже разбирать нет желания.
Старый 06.10.2012, 20:10
KPOKODIL
В разработке
offline
Опыт: 10,262
Активность:
Умгу, завтра тогда пробегусь по коду с дебаг сообщением , и выложу сюда протабулированный код
Старый 06.10.2012, 20:52
adic3x

offline
Опыт: 108,439
Активность:
У меня возникла бессмысленная идея:
Повесить где то в правилах jass раздела, или прикрепить важной темой, что помощь по отладке алгоритмов не оказывается, если в исходном коде нет debug сообщений. Хотя читать это никто все-равно не будет.
P. S. Статью про отладку писал только для опыта, и оценивал ее актуальность как крайне низкую. Оказалось наоборот ;)
Старый 06.10.2012, 22:40
asesmo
Я I Jag Ich Jeg Ja Minä!
offline
Опыт: 8,073
Активность:
KPOKODIL, если дебаг не подписал, то хотя бы комменты расставь. Спасибо.
Старый 06.10.2012, 22:48
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
ADOLF:
Повесить где то в правилах jass раздела...
никто и соседние темы\правила\статьи даже не читает,что уж говорить об этом =( и поиск никто не юзает,мб даже не знает где он
Старый 06.10.2012, 22:54
DioD

offline
Опыт: 45,134
Активность:
есть идея лучше, банить сразу за пост кода без отладки.
по коду - логика не ясна, зачем 3 таймера, зачем всё сохранять в хештаблицу.
рейт 100-15 создаём юнита с временем жизни в 5 секунд
другим таймером энумерируем все поля и цепляем юнитов, при смерти поля выкидываем всех из поля, пишется в 10 строк.
Старый 07.10.2012, 09:01
KPOKODIL
В разработке
offline
Опыт: 10,262
Активность:
DioD, дело в том , что поле живет 5 сек, и юнит в нем должен "левитировать" только 2 секунды после попадания, а потом передвигаться дальше.
Старый 07.10.2012, 11:28
quq_CCCP
Я белый и пушистый!
online
Опыт: 93,279
Активность:
KPOKODIL, неумееш писать сам такое, попроси кого нить сделать тебе в барахолке, то напишут чепухи а потом спрашивают - А что у меня не работает? ( ответ - МОЗГ)
Старый 07.10.2012, 11:31
KPOKODIL
В разработке
offline
Опыт: 10,262
Активность:
quq_CCCP, ну да , я смотрю тут все такие крутые , вместо того чтобы помочь, могут только оскорблять.
И как же по твоему можно научится писать такие спелы, если просить кого нибудь сделать их за тебя?
KPOKODIL добавил:
DioD, Таймера 2 (TSpell, TFly)
Первый отвечает за отлов юнитов для полета, второй же отвечает за полет юнита
KPOKODIL добавил:
P.S пропустил код через SLA и добавил коментов
И в принципе я догадываюсь в чем проблема.
Когда находят летчиков в теле данной функции:
function NG_SpellRun takes nothing returns nothing
То каждого найденного летчика записывают в хеш-таблицу по Id таймера
call SaveUnitHandle(udg_hash, GetHandleId(TFly), 2, Pop)
А так как юнитов может быть много, то видимо идет перезапись. В функции , отвечающий за полет , загружается только самый последний записанный юнит.
Щас попробую это исправить
Старый 07.10.2012, 12:35
quq_CCCP
Я белый и пушистый!
online
Опыт: 93,279
Активность:
KPOKODIL, ну изучая чужой код учись делать скиллы, то я смотрю статьи не для вас, или вы их не понимаете, учителей или лучших друзей которые будут тут вас учить всем азам программирования, нету, так что пытаемся разобраться сами...
KPOKODIL:
Первый отвечает за отлов юнитов для полета, второй же отвечает за полет юнита
Да ты что, нафиг нам таймер для отлова? кога есть триггер, это раз, 2 можно испотльзовать 1 и тот же таймер для всех а не плодить их по 10 штук...
Старый 07.10.2012, 12:38
KPOKODIL
В разработке
offline
Опыт: 10,262
Активность:
quq_CCCP, это только придирки по качеству исполнения спела, но при ээто твое сообщение мне никак не помогло разобраться с моей проблемой.
KPOKODIL добавил:
quq_CCCP,
P.S
Глянь ка на свою подпись заодно.
Старый 07.10.2012, 12:44
DioD

offline
Опыт: 45,134
Активность:
почитайте про OOP.
создаёт класс поля, статика которого ловил левитирует и отпускает, всё что требуется хранить, ЮНИТ+ШТАМП ВРЕМЕНИ КОГДА ОН ПОЙМАН,грубо говоря одна запись.
таймер который ловит - статика - один на всю игру
таймер жизни полей - встроенное свойство юнита.
пишите нормально, уже давно не 2005 год когда писалось тяп ляп и это обсасывали.
Старый 07.10.2012, 12:44
quq_CCCP
Я белый и пушистый!
online
Опыт: 93,279
Активность:
KPOKODIL, придирки это твое тап ляп, не хочу учится, хочу карты делать...
Кроме тебя это некому не нужно и никому не интересно, статьи написали много лет назад....
quq_CCCP добавил:
KPOKODIL, правда там у тебя не тока в таймерах беда, сам килл нужно делать заново, так будет проще, ибо написан он совершенно неправильно... (бегом читать статью про оптимизацию)
Старый 07.10.2012, 12:57
KPOKODIL
В разработке
offline
Опыт: 10,262
Активность:
Переписал спел с 0
Результат : Полное приостановление жизни компьютера после 6-7 запуска спела + воины не летают :(
Причина: Да хрен его знает
Вот собстевенно новый
» код
function ToTheSky takes nothing returns nothing
local timer t = GetExpiredTimer ()
local unit Ef = LoadUnitHandle(udg_hash,GetHandleId(t),1)
local group g = CreateGroup()
local unit Chk
set g = GetUnitsInRangeOfLocAll (200,GetUnitLoc(Ef))
 set Chk = FirstOfGroup (g) 
        loop
            exitwhen Chk == null
             if IsUnitAliveBJ (Ef) then
               if IsUnitType(Chk, UNIT_TYPE_STRUCTURE) == false and GetOwningPlayer(Chk) != GetOwningPlayer(Ef) and IsUnitAliveBJ(Chk) == true then
                    if GetUnitFlyHeight(Chk) < (GetUnitDefaultFlyHeight (Chk) + 300) then
                        call PauseUnitBJ(true,Chk)
                        call SetUnitFlyHeight(Chk,GetUnitFlyHeight(Chk) + 75,100)
                        call SaveBoolean (udg_hash,GetHandleId(Ef),GetHandleId(Chk),true)
                    else
                        call SetUnitFlyHeight(Chk,GetUnitDefaultFlyHeight(Chk),1000)
                        call PauseUnitBJ(false,Chk)
                    endif
                 call GroupRemoveUnitSimple (Chk,g)  
               endif
             set Chk = FirstOfGroup (g) 
             else
                if LoadBoolean(udg_hash,GetHandleId(Ef),GetHandleId(Chk)) then
                call PauseUnitBJ(false,Chk)
                endif
             endif
        endloop
if IsUnitAliveBJ (Ef) == false then
    call DestroyTimer(t)
    call FlushChildHashtable(udg_hash,GetHandleId(t))
    call FlushChildHashtable(udg_hash,GetHandleId(Ef))
endif
call DestroyGroup(g)
set t = null
set Ef = null
set Chk = null
set g = null
endfunction

function Trig_NullGrav_Actions takes nothing returns nothing
local real X = GetUnitX(GetAttackedUnitBJ())
local real Y = GetUnitY(GetAttackedUnitBJ())
local unit Ef 
local timer t = CreateTimer()
 if GetUnitAbilityLevelSwapped('A001', GetAttacker()) > 0 and GetRandomReal(0, 100.00) <= 15.00 then
    set Ef = CreateUnit (GetOwningPlayer(GetAttacker()),'e000',X,Y, bj_UNIT_FACING)
    call UnitApplyTimedLifeBJ( 5, 'BTLF', Ef )
    call TimerStart (t,0.50,true,function ToTheSky)
    call SaveUnitHandle (udg_hash,GetHandleId(t),1,Ef)
 endif
set t = null
set Ef = null
endfunction

//===========================================================================
function InitTrig_NullGrav takes nothing returns nothing
    set gg_trg_NullGrav = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_NullGrav, EVENT_PLAYER_UNIT_ATTACKED )
        call TriggerAddAction( gg_trg_NullGrav, function Trig_NullGrav_Actions )
endfunction
Я бы и сам проверил что вызывает такие утечки , но к сожалению мне надо постоянно перезагружать комп, чтобы продолжить работу.

Отредактировано KPOKODIL, 07.10.2012 в 19:33.
Старый 07.10.2012, 19:15
biridius

offline
Опыт: 18,935
Активность:
KPOKODIL, первый цикл помойму корявый, именно он вызывает зависание
set Chk = FirstOfGroup (g) наверное должно быть в теле цикла?
Старый 07.10.2012, 19:27
KPOKODIL
В разработке
offline
Опыт: 10,262
Активность:
infS8Noyabrsk, да спасибо, это уже поправил.
Теперь уже виснет с 6-7 запуска, так же воины с удовольствием паузтся , но при этом не летают
Старый 07.10.2012, 19:30
Hate
конь вакуумный
offline
Опыт: 43,033
Активность:
у вас каждые 0.5 сек запускается цикл который вертится пока не истечет лимит операций, офк это вызывает повисание.
рекомендую обратиться в барахолку в соответствующую тему, ибо у вас пока что нету понимания jass'а
Hate добавил:
юзайте дебаг в конце концов
Старый 07.10.2012, 19:33
biridius

offline
Опыт: 18,935
Активность:
call GroupRemoveUnitSimple (Chk,g) тоже не всегда работает неплохо бы сделать чтобы оно выполнялось после set Chk = FirstOfGroup (g) безусловно
Старый 07.10.2012, 19:37
Закрытая тема

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

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

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

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



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