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

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

Закрытая тема
 
Drulia_san
Великий Дрюля жив.
offline
Опыт: 8,529
Активность:
Очень странная ошибка, которую не могу выявить
В общем есть такой триггер (код всего триггера ниже). Назначение триггера: Создает нового крипа спустя некоторое время после его смерти, к каждому юниту всегда привязана одна и та же позиция по хештаблице, с этим проблем нет, не в этом суть. Чтобы реснуть юнита мне нужно записать его в хештаблицу, ассоциировав с таймером, чтобы по его истечению реснуть юнита. Но такой ошибки я еще никогда не видел, может даже вас это удивит. Внизу под таймером есть цикл, который дебажит этот процесс. Ошибка: При загрузке юнита из хештаблице в таймере выдает нулл! Если время где-то до 5 секунд, то выдает того самого юнита. Я сначала думал, что юнита что-то удаляет, я проверял в цикле, но нет. Сам юнит продолжает существовать, к нему можно обращаться, получать его тип, игрока, хендл-айди и тд. С этим 100% проблем нет, юнит - существует. Но если в цикле каждый тик снова считывать юнита с хештаблицы где-то через 5 секунд он будет считывать нулл О_о. Я решил записывать юнита в отдельную хештаблицу, с вообще левыми асоциациями. Всё равно выдает нулл. Тогда я делаю так: Записываю юнита после этих 4х секунд еще раз каждый шаг цикла в хештаблицу и следующим действием сразу его считываю, ведь всё ок. Существует юнит? Существует, 100%. Значит его можно записать в таблицу? Можно. Считается ли он оттуда если его считать мгновенно после записи? Да, обязан. Но он опять после считывания выдает нулл. Я отрубал уже все триггеры, кроме этого в карте, всё равно выдает гребаный нулл! Но хештаблица со всеми остальными случаями в игре работает нормально, только тут появляется эта странная ошибка. Почему именно через 4-5 сек наступает мертвое время для этого юнита, когда он существует, но его невозможно считать ни из одной хеш-таблицы?!
Код:
//Trigger conditions
bool CreepDiesConditions ()
{
    local unit u = GetTriggerUnit();
    return ((IsUnitDummy(u) == false) && ((u == LoadUnitHandle(DataExchange, GetHandleId(u), HT_CREEPS)) && LoadOver == true));
}

//Trigger actions
void CreepDiesActions ()
{
    local timer t = CreateTimer();
    local float time;
    local unit u = GetTriggerUnit();
    local int p_id = GetPlayerId(GetOwningPlayer(u));
    local int ut = GetUnitTypeId(u);
    SaveUnitHandle(DataExchange, GetHandleId(t), OLD_CREEP, u);
    time = CREEP_RESP_DELAY;
    TimerStart(t, time, false, lambda void() 
    {
        local timer t = GetExpiredTimer();
        local unit u = LoadUnitHandle(DataExchange, GetHandleId(t), OLD_CREEP); //Больше 5 секунд и возвращает нулл
        local location loc = LoadLocationHandle(DataExchange, GetHandleId(u), HT_CREEPS_LOC);
        local player p = GetOwningPlayer(u);
        local int ut = GetUnitTypeId(u);
        RemoveUnit(u);
        u = CreateUnit(p, ut, GetLocationX(loc), GetLocationY(loc), DEFAULT_FACING);
        SaveUnitHandle(DataExchange, GetHandleId(u), HT_CREEPS, u);
        SaveLocationHandle(DataExchange, GetHandleId(u), HT_CREEPS_LOC, loc);
        DestroyTimer(t);
    });


//Дебаг цикл, после 4го тика где-то выдает нулл.
    local unit test = null;
    while(true)
    {
        test = LoadUnitHandle(DataExchange, GetHandleId(t), OLD_CREEP); //Спустя пару шагов цикла возвращает нулл
        debugmsg(R2S(TimerGetElapsed(t)));
        local int utt, idd;
        if(test == null)
        {
            debugmsg("u - null");
            debugmsg(I2S(GetHandleId(t)));
        }
        else
        {
            debugmsg("u - exists");
            debugmsg(I2S(GetHandleId(t)));
        }
        test = null;
        TriggerSleepAction(1.00);
    }
    
}

//Main trigger function
void InitTrig_CreepDies ()
{
    gg_trg_CreepDies = CreateTrigger();
    TriggerRegisterAnyUnitEventBJ(gg_trg_CreepDies, EVENT_PLAYER_UNIT_DEATH);
    TriggerAddCondition(gg_trg_CreepDies, Condition(function CreepDiesConditions));
    TriggerAddAction(gg_trg_CreepDies, function CreepDiesActions);
}
Старый 30.04.2014, 19:09
Msey
????
offline
Опыт: 67,346
Активность:
Время разложения юнита в константах указано какое?
Старый 30.04.2014, 20:51
ZLOY5

offline
Опыт: 912
Активность:
после разложения юниты удаляются из игры
Старый 30.04.2014, 20:53
Drulia_san
Великий Дрюля жив.
offline
Опыт: 8,529
Активность:
Я понимаю, что разложение, но я кажется писал, что если обращаться к юниту напрямую, без хештаблиц он спокойно себе существует, к тому же там стоит в настройках "Не разлагается".
Старый 30.04.2014, 21:10
ScorpioT1000
Работаем
online
Опыт: отключен
потому что таблица хендлов не следит за жизнью юнитов, т.е. она какбы более низкоуровневая, а в юзерской хештаблице есть сборщик мусора, просто он так криво работает, "предостерегает" от утечек. это просто бага такая =) не ресай юнита, пересоздавай его, либо сделай героем
Старый 30.04.2014, 21:20
Drulia_san
Великий Дрюля жив.
offline
Опыт: 8,529
Активность:
ScorpioT1000, а, то есть моя проблема это не мой косяк, а косяк самой скриптовой системы?)
Старый 30.04.2014, 21:23
adic3x

offline
Опыт: 107,539
Активность:
Пару заметок:
IsUnitDummy(u) == false -> ! IsUnitDummy(u)
LoadOver == true -> LoadOver
Если cJass - тол локалс не нужен:
local timer t = CreateTimer(); -> timer t = CreateTimer ();
Можно также использовать callback:
callback onUnitDeath () {
    unit u = GetTriggerUnit ();
    if (!IsUnitDummy(u)) {
        // ...
    }
}
Старый 30.04.2014, 23:06
Drulia_san
Великий Дрюля жив.
offline
Опыт: 8,529
Активность:
Всем спасибо, пришлось изобретать велосипед. Вместо самого юнита, я сохраняю его хендл-айди и сохраняю юнита и все необходимые для него данные в специальный стек структур, в таймере получаю по загруженному айди я нахожу нужную мне структуру и извлекаю из неё все нужные мне данные. Забавно, юнит существует и выдает хендл айди, но возвращает нулл если спросить его type-id и или игрока-владельца. Проблема решена, дело было в забагованном варкрафте.
Старый 01.05.2014, 00:35
DioD

offline
Опыт: 45,184
Активность:
RemoveUnit(u);
днище...
Старый 01.05.2014, 08:51
Hate
конь вакуумный
offline
Опыт: 43,124
Активность:
 while(true)
    {
          ......
          TriggerSleepAction(1.00);
    }
о\
Старый 01.05.2014, 11:21
Drulia_san
Великий Дрюля жив.
offline
Опыт: 8,529
Активность:
DioD, кто еще тут днище, ты чем код читал? Юнит удаляется только после всех манипуляуций считывания, по твоему если сначала считать, потом удалить он не считается? Не позорься и читай код внимательно, если беглым взгядом увидел RemoveUnit это еще не значит, что ты самый умный. Ты даже мою тему не читал, просто беглым взглядом посмотрел на проблему, увидел ремув юнит и о, всё, я нашел проблему! Какой же автор глупый, сейчас я-то раскрою этому днищу глаза, вот же он, ремув юнит!!! Как же бесит такой подход к делу, когда стараешься и расписываешь проблему, чтоб не докопались по мелочам, но найдется такой умник который обязательно посчитает себя умнее других, ничего не читая и решит всю проблему 1 постом!

Hate, разве нужно делать оптимизированным и продуманным дебаг код который я запускаю 1 раз для проверки и удаляю? Не понимаю придирок к таким вещам, этот вариант удобнее любого существующего, пускай не оптимизированный, но кому это надо если этот код я уберу когда проблема решится?
Старый 01.05.2014, 12:20
Hate
конь вакуумный
offline
Опыт: 43,124
Активность:
вы знаете что существует лимит операций? это во первых, и во вторых как вейт работает
Старый 01.05.2014, 12:27
Drulia_san
Великий Дрюля жив.
offline
Опыт: 8,529
Активность:
Hate, несомненно знаю. И вейт работает с низкой точностью, я им пользуюсь только в таких случаях, я его поставил чтобы просто замедлить цикл. Еще раз напоминаю, что этот код мне нужен на пару секунд, я посмотрю что он выводит, разбираюсь что к чему и удаляю его.
Старый 01.05.2014, 12:29
DioD

offline
Опыт: 45,184
Активность:
так как видимо это слишком тяжело для неокрепшего детского ума проверить\догадатся что пишут, посоветую посмотреть компилированный результат когда и сделать еще раз выводы.
многопоточность, пусть даже мнимая, это достаточно сложное для понимания явление, так как человеческий мозг работает в один поток, лично я увидел 3 возможных источника проблем просто взглянув на код ничего не выполняя и не отлаживая, очень жаль что вы так не можете и вообще отладка не для вас.
Старый 01.05.2014, 12:51
Drulia_san
Великий Дрюля жив.
offline
Опыт: 8,529
Активность:
DioD,
ко-ко-ко, пок-пок-пок, я тут самый умный
Спасибо. Это, безусловно, очень интересно!
» Спойлер
Пора бы темку закрыть.

Отредактировано Drulia_san, 01.05.2014 в 13:09.
Старый 01.05.2014, 13:03
nvc123
new status
offline
Опыт: 59,284
Активность:
DioD, скорость распространения импульса в мозге 3 метра в секунду
если бы мозг работал в 1 поток то ты бы был растением
количество потоков в мозге = количеству нейронов во входном слое(в начале обработки)
поэтому последовательные действия(например перемножить 6-значные числа)мы выполняем долго, а параллельные(распознание образов методом обработки каждого нейрона памяти) довольно быстро
а вот сознание да
работает в 1 поток
nvc123 добавил:

на счёт кода
юзай стек структур с периодическим таймером и будет тебе счастье(в структуре храни равкод юнита и координаты)
Старый 02.05.2014, 22:24
Закрытая тема

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

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

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

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



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