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

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

Ответ
 
ninjakaka

offline
Опыт: 39
Активность:
[Решено] Кусок кода по непонятным причинам блокирует функцию.
О великие джассеры и духи варкрафта, взываю к вашей помощи! Помогите пожалуйста, ситуация на мой взгляд из ряда вон!
В общем есть у меня в карте системка общения жителей в деревне. Состоит из триггера продвижения сообщений на экране (он ещё потом и удаляет сообщение когда оно продвинулось достаточно высоко), массива структур с информацией о сообщениях (само сообщение, его текущее положение, юнит который сказал это сообщение и т.п.), функции добавления нового сообщения в структуру, большого массива с диалогами, функции Dialog, которая принимает номер диалога, людишек и просто по очереди над ними показывает сообщения из массива, ну и функция поиска людишек, которые не заняты общением.
В функции dialog есть загадочное место. Если туда пихнуть простенький код с if'ами и else'ами, то она продолжает выполняться, если же этот код закомментировать, то функции которые идут после этих if'ов и else'ов не выполняются, функция будто зависает. Это противоречит моей человеческой логике и я скоро ежа рожу пока не пойму в чём проблема.
Вот код Dialog. Функция не выполняется после закомментированного куска кода, если его раскомментировать, то всё работает.
((кат Код Dialog
function Chance takes real chance returns boolean
    local real roll = GetRandomReal(0, 100)
    
    BJDebugMsg("Рулетка - "+R2S(roll)+".")
    return (roll < chance)
endfunction

function Dialog takes unit u1, unit u2, unit u3, integer dlgtype, integer dlgnum returns integer 
//принимает 3 юнитов которые будут общаться, тип диалога (есть версии для 2-х и для 3-х юнитов), номер диалога.
    local unit array u
    local string s = "1"
    local real wait
    local integer i = 0
    local integer whoscue = 0
    local integer towho
    local real array tempangle
    local boolean array headturned
    local integer totalmessages = 0
    
    set u[1] = u1
    set u[2] = u2
    set u[3] = u3
    
    BJDebugMsg("Запуск диалога: "+I2S(dlgtype)+", "+I2S(dlgnum)+".")
    loop
        if (s != null) then
            set s = DAItem(1, dlgtype, dlgnum, i, null) //DAItem выбирает по особому алгоритму сообщения из большууущего массива.
        endif
        exitwhen (s == null) //Пустая строка = завершение текущего диалога
        set whoscue = S2I(SubString(s, 0, 1)) //Вначале сообщения стоит номер юнита который будет говорить.
        set s = SubString(s, 1, StringLength(s))

        BJDebugMsg("Очередь - "+I2S(whoscue)+", строка - "+s+".")
        /*if Chance(100) then //Повороты головы и туловища, шанс 100%, на самом деле 60%, но с 60 процентами здесь появляется загадочное место номер 2
            if Chance(100) then //Если туловище
                if (tempangle[whoscue] == 0) then //Если не повёрнуто то поворачиваем
                    set tempangle[whoscue] = GetRandomReal(-70, 70)
                    SetUnitFacing(u[whoscue], GetUnitFacing(u[whoscue])+tempangle[whoscue])
                else //Иначе, возвращаем обратно
                    SetUnitFacing(u[whoscue], GetUnitFacing(u[whoscue])-tempangle[whoscue])
                    set tempangle[whoscue] = 0
                endif
            endif
            if Chance(100) then //Если голова, то
                if headturned[whoscue] then //Если повёрнута, то
                    ResetUnitLookAt(u[whoscue])
                    set headturned[whoscue] = false
                else //Если ещё нет, то
                    if ((dlgtype == 3) or (dlgtype == 4))
                        loop
                            set towho = GetRandomInt(1, 3)
                            exitwhen (towho != whoscue)
                        endloop
                    else
                        set towho = 2 - (whoscue - 1)
                    endif                        
                    SetUnitLookAt(u[whoscue], "bone_head", u[towho], 0, 0, 90)
                    set headturned[whoscue] = true
                endif
            endif
        endif*/
        
        BJDebugMsg("Источник - "+GetUnitName(u[whoscue])+", приёмник - "+GetUnitName(u[towho])+".")
        if IsUnitAliveBJ(u[whoscue]) and IsUnitAliveBJ(u[towho]) then
            BJDebugMsg("Оба юнита живы, отображаю текст.")
            set wait = DisplayDlgText(s, u[whoscue])*0.9
            BJDebugMsg("Отображение завершено, время ожидания - "+R2S(wait)+".")
            set totalmessages = totalmessages + 1

            if (wait<1) then 
                set wait = 1 
            endif
            TriggerSleepAction(wait)
        else
            set s = null //Если кто-то мёртв, то s станет null'ом и при проверке диалог завершится
        endif
        set i = i + 1
    endloop
    
    //Сброс поворотов туловища и головы
    if (tempangle[1] != 0) and IsUnitAliveBJ(u[1]) then 
        SetUnitFacing(u[1], GetUnitFacing(u[1])-tempangle[1])
    endif
    if (tempangle[2] != 0) and IsUnitAliveBJ(u[2])  then 
        SetUnitFacing(u[2], GetUnitFacing(u[2])-tempangle[2])
    endif
    if ((dlgtype==3)or(dlgtype==4))and(tempangle[3] != 0) and IsUnitAliveBJ(u[3])  then
        SetUnitFacing(u[3], GetUnitFacing(u[3])-tempangle[3])
    endif

    if headturned[1] and IsUnitAliveBJ(u[1])  then
        ResetUnitLookAt(u[1])
    endif
    if headturned[2] and IsUnitAliveBJ(u[2])  then
        ResetUnitLookAt(u[2])
    endif
    if ((dlgtype==3)or(dlgtype==4)) and headturned[3] and IsUnitAliveBJ(u[3])  then
        ResetUnitLookAt(u[3])
    endif
    
    set u[1] = null
    set u[2] = null
    set u[3] = null
    
    return totalmessages
endfunction
))
Помогите пожалуйста! В чём проблема? Где я мог ошибиться? По вашим запросам предоставлю дополнительную информацию если чего то не хватает.
Добавлено (12:07, 30.01.2013):
Немного подправил код.
Добавлено (14:48, 30.01.2013):
Решение:
Нашёл ошибку. Обращение по неинициализированной переменной, наверняка варик скрыл от меня Access Violation.
Заметьте, есть объявление переменной towho
    local integer towho
В закомментированном коде есть
if ((dlgtype == 3) or (dlgtype == 4))
  loop
    set towho = GetRandomInt(1, 3)
    exitwhen (towho != whoscue)
  endloop
  else
    set towho = 2 - (whoscue - 1)
endif
Как раз в нём и происходила инициализация, а дальше идёт
BJDebugMsg("Источник - "+GetUnitName(u[whoscue])+", приёмник - "+GetUnitName(u[towho])+".")
Ключевое слово GetUnitName(u[towho]) - обращение по неинициализированной переменной towho.
Не забывайте инициализировать ваши локальные переменные перед обращением к ним!!! =)

Отредактировано ninjakaka, 30.01.2013 в 16:04.
Старый 30.01.2013, 00:08
Киря

offline
Опыт: 769
Активность:
  1. Некрасивый код.)
if Chance(100) then //Повороты головы и туловища, шанс 100%, на самом деле 60%, но с 60 процентами здесь появляется загадочное место номер 2
if Chance(100) then //Если туловище
к чему вообще?
  1. BJ функции замени.)
if IsUnitAliveBJ(u[whoscue]) and IsUnitAliveBJ(u[towho]) then
либо они мертвы, либо
5.
if (wait<1) then 
set wait = 1 
endif
TriggerSleepAction(wait)
очень-очень плохо, если стоит в циклах
Старый 30.01.2013, 01:36
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,279
Активность:
ninjakaka, цикл похоже убивает поток, поскольку когд он выолняется чертову кучу раз....
куча бж функций, массивы локального типа тоже не лучшее решение...
Старый 30.01.2013, 07:01
ninjakaka

offline
Опыт: 39
Активность:
  1. Возможно в некоторых местах действительно на ваш взгляд некрасивый, я ещё не аз в Jass, укажи пожалуйста мне где он не красивый и как бы ты его исправил, я это учту! =)
  1. С BJ функциями здесь всё в порядке, я их использую потому что они нормально написаны, эти в данном случае не вызывают утечек памяти или проблем.
Проблема не в том что цикл убивает поток. Цикл выполняется максимум 15 раз, т.к. нулевая строка попадается где-то на 15 сообщении, в итоге срабатывает s == null и цикл завершается. Ты немного не понял проблему, ведь если я раскомментирую закомментированный кусок, всё снова начнёт выполняться. Проблема где-то глубже.
Старый 30.01.2013, 10:42
DioD

offline
Опыт: 45,134
Активность:
отладку нормальную напишите
Старый 30.01.2013, 11:28
Ответ

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

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

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

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



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