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

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

Закрытая тема
 
Enein
Silenced by ZlaYa1000
offline
Опыт: 43,453
Активность:
Спелл вызывает фатал
вот функция, которая, вероятней всего, вызывает фатал:
» code
Код:
function Groundwater_Move_Timer_Actions takes nothing returns nothing
    local timer   t = GetExpiredTimer()
    local real    tfh    = get_object_rparam(t, "Groundwater_Target_FlyHeight")
    local real    tdfh   = get_object_rparam(t, "Groundwater_Target_Default_FlyHeight")
    local real    thu    = get_object_rparam(t, "Groundwater_Target_Speed")
    local real    tsxy   = get_object_rparam(t, "Groundwater_Target_Speed_XY")
    local unit    target = get_object_uparam(t, "Groundwater_Target")
    local unit    caster = get_object_uparam(t, "Groundwater_Caster")
    local real    ang    = get_object_rparam(t, "Groundwater_Angle")
    local real    x      = GetUnitX(target)
    local real    y      = GetUnitY(target)
    local integer i      = 0

    if (tfh >= tdfh) then
        call set_object_rparam(t, "Groundwater_Target_FlyHeight", tfh + thu)
        call set_object_rparam(t, "Groundwater_Target_Speed", thu - 0.098)
        call SetUnitFlyHeight(target, tfh, 0)
    else
        if (get_object_iparam(t, "Groundwater_Damage_Taken") == 0) then
            call UnitDamageTarget(caster, target, 60 / 2 * GetUnitAbilityLevel(caster, 'A06D'), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            call set_object_iparam(t, "Groundwater_Damage_Taken", 1)
        endif
    endif
    if (tsxy > 0) then
        if (get_object_iparam(t, "Groundwater_SpellTarget") == 0) then
            call SetUnitX(target, x + tsxy * Cos(ang * 0.017))
            call SetUnitY(target, y + tsxy * Sin(ang * 0.017))
        endif
        call set_object_rparam(t, "Groundwater_Target_Speed_XY", tsxy - 0.024)
    else
        call SetUnitFlyHeight(target, 0, 0)
        if (IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) then
            loop
                exitwhen not(IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))
                set x = x - i * Cos(ang * 0.017)
                set y = y - i * Sin(ang * 0.017)
                set i = i + 1
            endloop
        endif
        call SetUnitX(target, x)
        call SetUnitY(target, y)
        call PauseUnit(target, false)
        call flush_object(t)
        call DestroyTimer(t)
    endif
    if ((get_object_iparam(t, "Groundwater_SpellTarget") == 1) and (tfh < tdfh)) then
        call SetUnitFlyHeight(target, 0, 0)
        if (IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) then
            loop
                exitwhen not(IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))
                set x = x - 10 * i * Cos(ang * 0.017)
                set y = y - 10 * i * Sin(ang * 0.017)
                set i = i + 1
            endloop
        endif
        call SetUnitX(target, x)
        call SetUnitY(target, y)
        call PauseUnit(target, false)
        call flush_object(t)
        call DestroyTimer(t)
    endif

    set t      = null
    set target = null
    set caster = null
endfunction

вопрос: почему он вылетает? т.е. что здесь не так?
и на всякий случай, вот весь код спелла
Старый 06.05.2009, 11:17
J
expert
offline
Опыт: 48,447
Активность:
первое что нужно сделать избавится от функций вида ###_object_###()
второе - с минимизировать обращение к кешу к одному, т.е. помещай всю инфу в массив на определенную ячейку, а номер этой ячейки уже атачи к таймеру
если к тому времени ошибка сама не рассосется (в чем я сомневаюсь), то продебажи записи в кеш(массивы) и посмотри существуют ли они, и то вдруг ты некоторые не записываешь там где спел запускается

J добавил:
в третьих, у тебя в двух ифах вызывается очищение кеша и уничтожение таймера, или в первом после всего поставь return, или добейся максимальной уверенности что вызовется что-либо одно через elseif
Старый 06.05.2009, 11:38
Enein
Silenced by ZlaYa1000
offline
Опыт: 43,453
Активность:
Цитата:
у тебя в двух ифах вызывается очищение кеша и уничтожение таймера, или в первом после всего поставь return, или добейся максимальной уверенности что вызовется что-либо одно через elseif

немного послаживал, пока что все еще фаталит... работаю дальше
Цитата:
с минимизировать обращение к кешу к одному, т.е. помещай всю инфу в массив на определенную ячейку, а номер этой ячейки уже атачи к таймеру

я конечно понимаю, что кеш зло, но я еще ненастолько крут, чтобы работать с массивами
...
вот первая попытка, естественно, неудачная:
» code
Код:
globals
    real array wtfh
    real array wtdfh
    real array wthu
    real array wtsxy
    real array wang
    unit array wgwc
    unit array wgwt
    boolean array wdt
    boolean array wst
    integer gwi = 0
endglobals

function Groundwater_Move_Timer_Actions takes nothing returns nothing
    local timer   t      = GetExpiredTimer()
    local integer a      = get_object_iparam(t,"index")
    local real    tfh    = wtfh[a]
    local real    tdfh   = wtdfh[a]
    local real    thu    = wthu[a]
    local real    tsxy   = wtsxy[a]
    local unit    target = wgwt[a]
    local unit    caster = wgwc[a]
    local real    ang    = wang[a]
    local real    x      = GetUnitX(target)
    local real    y      = GetUnitY(target)
    local integer i      = 0

    if (tfh >= tdfh) then
        set wtfh[a] = tfh + thu
        set wthu[a] = thu - 0.098
        call SetUnitFlyHeight(target,tfh, 0)
    elseif not(wdt[a]) then
        call UnitDamageTarget(caster, target, 60 / 2 * GetUnitAbilityLevel(caster, 'A06D'), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
        set wdt[a] = true
    endif
    if (tsxy > 0) then
        if not(wst[a]) then
            call SetUnitX(target, x + tsxy * Cos(ang * 0.017))
            call SetUnitY(target, y + tsxy * Sin(ang * 0.017))
        endif
        set wtsxy[a] = wtsxy[a] - 0.024
    endif
    if ((wst[a]) and (wtfh[a] < tdfh)) or (wtsxy[a] <= 0) then
        call SetUnitFlyHeight(target, 0, 0)
        if (IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) then
            loop
                exitwhen not(IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))
                set x = x - i * Cos(ang * 0.017)
                set y = y - i * Sin(ang * 0.017)
                set i = i + 1
            endloop
        endif
        call SetUnitX(target, x)
        call SetUnitY(target, y)
        call PauseUnit(target, false)
        call flush_object(t)
        call DestroyTimer(t)
        set wgwc[a] = null
        set wgwt[a] = null
    endif
    set t      = null
    set target = null
    set caster = null
endfunction

опять фатал Т_Т (в момент, когда юниты почти приземлились)
Старый 06.05.2009, 13:41
J
expert
offline
Опыт: 48,447
Активность:
ну, детектор фатальных конструкций молчит, возможно ошибка и не сдесь, хотя какойто понапутаный код, какое именно движение должно происходить?
Старый 06.05.2009, 14:01
Enein
Silenced by ZlaYa1000
offline
Опыт: 43,453
Активность:
Цитата:
какое именно движение должно происходить

в зависимости от расстояния между юнитом, и целью заклинания: чем оно меньше, тем выше подбрасывание, и меньше дистанция, которую должен пролететь юнит. если расстояние между целью и юнитом максимальное (500), то юнит просто проскользит по земле, почти не поднимаясь в воздух
вот короче зарисовочка и, если че, полный код спелла (с глобалками который)

Отредактировано Enein, 06.05.2009 в 15:15.
Старый 06.05.2009, 14:57
Hellfim
Новичок
offline
Опыт: 79,707
Активность:
Enein, у меня зарисовку не грузит... Могу посоветовать следующее: поставь в таймере отсчет его повторений (т.е. сколько раз запускается Groundwater_Move_Timer_Actions). Запомни число на котором вылетает фатал и сделай ограничение на количество повторений(до полученного числа). Далее выводи данные по каждому юниту и подставляй в свою функцию. Процесс конечно муторный, но если "руки не из жопы", то все получится.
Старый 06.05.2009, 15:08
J
expert
offline
Опыт: 48,447
Активность:
через чур запутанный код для такой простой задачи
метод должен быть прост
передаешь в таймер первоначальный вектор скорости, и все, и в таймере от вектора отнимаешь вектор притяжения и перемещаешь юнита на этот вектор, и так пока высота юнита не будет меньше нуля, код тут простейший
а в функции где создается таймер, уже рассчитываем углы, первый угол это в противоположную сторону от кастера, второй вертикальный угол считаешь исходя из расстояния между ними
находишь единичный вектор по этим углам, умножаешь его на начальную скорость и передаешь в таймер

Отредактировано J, 06.05.2009 в 15:26.
Старый 06.05.2009, 15:17
Enein
Silenced by ZlaYa1000
offline
Опыт: 43,453
Активность:
Hellfim, фаталит в момент приземления, так что считать нет смысла, да и не получится, т.к. для каждого юнита таймер будет срабатывать разное количество раз

Enein добавил:
причина фатала детектед ^^
Код:
if (IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) then
    loop
    exitwhen not(IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))
        set x = x - i * Cos(ang * 0.017)
        set y = y - i * Sin(ang * 0.017)
    set i = i + 1
    endloop
endif


Enein добавил:
только вот интересно, почему этот кусок кода вызывает фатал...
если бы точка, в которую падала основная цель, была бы действительно непроходима, тогда ясно, т.к. она (цель) перемещается только по вертикали
хотя тогда скорее было бы повисание игры, а не фатал...
Старый 06.05.2009, 15:47
J
expert
offline
Опыт: 48,447
Активность:
советую юзать для таких целей SetUnitPosition(), X/Y это для прожектилов и подобного тока
Старый 06.05.2009, 16:04
Enein
Silenced by ZlaYa1000
offline
Опыт: 43,453
Активность:
J, но в куске кода, который делает фатал, нет ни SetUnitPosition(), ни SetUnitX/Y
Старый 06.05.2009, 16:08
J
expert
offline
Опыт: 48,447
Активность:
Enein я имею виду проверку путей заменить на автоматическую
Старый 06.05.2009, 16:09
Enein
Silenced by ZlaYa1000
offline
Опыт: 43,453
Активность:
аа, ок. сейчас проверю...
бадабум, опять фатал

Enein добавил:
всё, тему можно закрывать
прикол был в том, что на тест-мапе юниты находились достаточно близко к границе карты, что означало фатал при их вылете за ее пределы

Отредактировано Enein, 06.05.2009 в 17:46.
Старый 06.05.2009, 17:14
adic3x

offline
Опыт: 108,439
Активность:
перед перемещением лучше проверять не выходят ли они за карту...
Старый 07.05.2009, 17:58
Закрытая тема

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

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

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

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



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