Тестирую свою карту (которая еще, конечно, не закончена), и вот иногда, чтобы проверить на утечность и другие траблы времени, оставляю ее на произвол и ухожу по делам. Но дважды, что я оставлял на ночь. Она переставала работать нормально ровно через 6000 сек (по таймеру времени карты). Второй раз я лично сам это наблюдал. То есть вначале юниты начинали бегать на месте, через 10 сек они телепортировались, а еще через 2-3 минуты экран в игре зависал, и даже не откликается. В диспетчере задач игра работает и отвечает, ресурсы не жрет чрезмерно. Утечек за все 6000 сек нет, но что не так, я не понимаю. Триггеров и таймеров или чего-то другого именно на 6000 сек - нет.
Есть идеи в чем проблема?

Принятый ответ

Возможно какой-либо переодический таймер на +- 0.7 сек, заполняющий массивы.
Массив в 8192 закончился, и при подборе свободных ячеек каждый раз уходит в бесконечный луп, который выдаёт лаг в 3 сек и обрывается на оп лимите.
Единственная идея, ибо сам сталкивался с этим
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
29
5 лет назад
0
Можно, конечно, написать уже заранее триггер без события и добавлять событие во время замаха. Тогда количество триггеров не изменится, но будут плодиться события, которые нельзя удалить.
Самым попсовым вариантом было и является попадание юнита на карту и добавление ему события "получает урон"
0
8
5 лет назад
Отредактирован pAxsIs
0
Msey:
Самым попсовым вариантом было и является попадание юнита на карту и добавление ему события "получает урон"
Пробовал этот вариант, но это в этом случае будет постоянный рост событий в триггере, как я уже писал. Неужели динамические триггеры могут быть проблемой? И вызывать подобный баг.

Clamp:
Разве у Msey не такие же трудозатраты по количеству событий в итоге? Ведь из комментариев под твоей наработкой:
ScorpioT1000:
это просто штука которая регает "юнит получил урон" на всех юнитов на карте.
0
29
5 лет назад
0
Поподробнее пожалуйста. Что за баги?
В подробностях уже не помню, а гугл нашёл только xgm.guru/p/wc3/165628?postid=313095
для отлова урона можно использовать system-physical-damage-detection , там можно модифицировать урон.
0
26
5 лет назад
0
pAxsIs, чтобы обнулить события, есть действие, которое приводит триггер в первоначальное состояние. Можно заносить юнитов в виде событий и в группу, триггер на смерть будет удалять из группы, потом, например, каждые 5 минут обновлять триггер до первоначального состояния и сразу добавлять туда события на членов группы.

Запамятовал упомянуть, что игра зависла, когда попытался выйти из неё после 6000-секундного бага.
0
8
5 лет назад
0
Всех услышал, пойду тестить каждый кейс, отпишусь как найду в чем (хотя бы примерно) причина.

8gabriel8:
pAxsIs, чтобы обнулить события, есть действие, которое приводит триггер в первоначальное состояние. Можно заносить юнитов в виде событий и в группу, триггер на смерть будет удалять из группы, потом, например, каждые 5 минут обновлять триггер до первоначального состояния и сразу добавлять туда события на членов группы.

Запамятовал упомянуть, что игра зависла, когда попытался выйти из неё после 6000-секундного бага.
Спасибо за идею, попробую.
0
29
5 лет назад
0
Та же дота написана на JASS и у нее каждая способность создает временный триггер. Попробую во всяком случае.
JASS автоматически не делает весь код хорошим, а популярность карты не залог оптимального решения.
Порылся я в вашем коде и это ужасно. Копирование триггера, чтобы сделать теже действия, но с другими параметрами повеселило.
Лучше переделать всё пока не позно, а то потом в этой каше ничего не разберёте.
0
8
5 лет назад
Отредактирован pAxsIs
0
NazarPunk:
JASS автоматически не делает весь код хорошим, а популярность карты не залог оптимального решения.
Речь была о другом, не о популярности или о JASS, а о том, что там есть подобные конструкции почти везде и это не вызывает проблем, что следовательно не должно быть проблемой у меня.

Порылся я в вашем коде и это ужасно. Копирование триггера, чтобы сделать теже действия, но с другими параметрами повеселило.
Лучше переделать всё пока не позно, а то потом в этой каше ничего не разберёте.
Изначально писал все на триггерах, можно увидеть везде аналоги, еще до сих пор не переписал все на JASS, как раз недавно писал о том сабж, что перехожу с ГУИ на JASS. Конструкции, где используется копирование триггера сведены к минимуму.

Сейчас просмотрел беглым взглядом, не совмещены только Триггеры: SpawnLine* в один триггер и CompSpellBack* в один триггер, больше копированных конструкций нет. А про эти 2 момента знаю, но как уже писал еще не закончил переход с ГУИ на JASS. Если видите что-то еще "ужасное" - поделитесь, я приму во внимание.

Возможность передачи массива в функцию очень бы улучшило код, ведь для многих функций полиморфизм бы не помешал. (Знаю про vJass и cJass, но хочу работать только с нативными инструментами)
0
29
5 лет назад
Отредактирован nazarpunk
0
OrderBackToLineB, OrderBackToLineR
ForceLineBlue1, ForceLineBlue2, ForceLineBlue3
ForceLineRed1, ForceLineRed2, ForceLineRed3
Line1, Line2, Line3
Триггеры Types * где в каждом событие Map Initalization что-бы задать несколько переменных.
Притом, что я карту даже сохранить не смог ибо JGNP ругается
local are only supported at the top function
но хочу работать только с нативными инструментами
если нативные инструменты замедляют разработку, то почему бы не использовать нормальные, где такую кашу можно написать проще
раскрыть
if ( ( GetUnitUserData(pickedUnit) / 10 ) == 1 ) then
            local location orderLoc = Location(GetRectCenterX(udg_arrRRegions_WayP1[modulus]), GetRectCenterY(udg_arrRRegions_WayP1[modulus]))
            call IssuePointOrderLoc( pickedUnit, "attack", orderLoc )
            call RemoveLocation( orderLoc )
        
        elseif ( ( GetUnitUserData(pickedUnit) / 10 ) == 2 ) then
            local location orderLoc = Location(GetRectCenterX(udg_arrRRegions_WayP2[modulus]), GetRectCenterY(udg_arrRRegions_WayP2[modulus]))
            call IssuePointOrderLoc( pickedUnit, "attack", orderLoc )
            call RemoveLocation( orderLoc )
            
        elseif ( ( GetUnitUserData(pickedUnit) / 10 ) == 3 ) then
            local location orderLoc = Location(GetRectCenterX(udg_arrRRegions_WayP3[modulus]), GetRectCenterY(udg_arrRRegions_WayP3[modulus]))
            call IssuePointOrderLoc( pickedUnit, "attack", orderLoc )
            call RemoveLocation( orderLoc )
// Гдето в при инициализации
real SpawnRectR[][];
real SpawnRectB[][];

SpawnRectB[0][0] = udg_rct_SpawnRectB_0_0;
SpawnRectB[0][1] = udg_rct_SpawnRectB_0_1;
SpawnRectR[1][0] = udg_rct_SpawnRectR_1_0;
SpawnRectR[1][1] = udg_rct_SpawnRectR_1_1;

// и.т.д
function SpawnRectGet(boolean isB, integer r1, integer r2){
 	if (isB) {
		return SpawnRectB[r1][r2];
	}
	return SpawnRectR[r1][r2];
}

function SpawnOrder(unit u, boolean isB, integer r1, integer r2) {
	rect rct = SpawnRectGet(isB, r1, r2);

	IssuePointOrder( pickedUnit, "attack", GetRectCenterX(rct), GetRectCenterY(rct) );
	rct = null;
}

// где-то в событиях

integer data = GetUnitUserData(pickedUnit) ;
integer modulus = data - (data / 10) * 10
integer data10 = data / 10;

if (data10 >= 1 || data10 <=3){
	SpawnOrder(pickedUnit, data10, modulus);
}

0
8
5 лет назад
0
NazarPunk:
OrderBackToLineB, OrderBackToLineR
ForceLineBlue1, ForceLineBlue2, ForceLineBlue3
ForceLineRed1, ForceLineRed2, ForceLineRed3
Line1, Line2, Line3
Знал, что возможно об этом упомянешь,
но соль в том, что для
  • "OrderBackToLine*" желательно передавать структуру, чтобы он нормально все обрабатывал, что тут невозможно сделать.
  • "ForceLine*" есть 2 варианта развития, один это сделать поиск необходимого региона по которому он будет выбирать как реагировать на то или иное событие, либо сделать 6 триггеров, каждый из которых отдельно вызывается. Конечно, если бы я понимал, что у меня возможно будет какое-то изменение в будущем в плане количество спаунов, то лучше было бы сделать один триггер обрабатывающий все, тут согласен.
  • "Line*" однозначно нужно разделить на 3 части, поскольку нужно передавать массив, либо писать дикий костыль на определение массивов, что я не люблю делать. Если писать, то сразу основательно. Там логика может отличаться. Поэтому нужно сохранить 3 линии для удобства изменения условий для каждой линии.

По поводу двумерных массивов полностью согласен, что так можно решить проблему. Но я пока писал только на ГУИ, где таковых нет (за исключением хэш таблиц, которыми я начал пользоваться только недавно, когда начал использовать JASS). В глобальных переменных объявить двумерный массив нельзя. А если пытаться объявить глобальные в своем коде, то пишет ошибку, что глобальные должны быть объявлены в самом начале. Поэтому я пока обходился одномерными массивами, что вызвало подобное. Так что тут я с тобой полностью солидарен.
В идеале вообще создавать объект со своим набором полей и методов. Но я пока вначале пути JASS, так что пользуюсь только им. А вообще пишу на С++
Спасибо за рекомендации
0
29
5 лет назад
Отредактирован nazarpunk
0
"OrderBackToLine*" желательно передавать структуру, чтобы он нормально все обрабатывал, что тут невозможно сделать.
Зачем так сложно, можно просто использовать двумерные массивы. Вот вам библиотека Spawn, которая совместима с вашим кодом и не создаёт Location. По необходимости методов можно добавить
zinc
//! zinc
library Spawn {
    rect SpawnRect[2][10];

    public {
        function IsUnitAlive(unit u) -> boolean {
            return GetUnitState(u, UNIT_STATE_LIFE) > 0.45; // именно при этом значении наступает смерть
        }
        
        function OrderBackToLine(unit u, integer diff) {
            integer data = GetUnitUserData(u);
            integer data10 = data / 10;
            integer modulus = data - (data / 10) * 10;
            rect rct;
            
            if (IsUnitAlive(u)){
                if (data10 >=1 && data10 <= 3){
                    rct = SpawnRect[data10+diff][modulus];
                } else {
                    if (udg_isTurnedOnDebug){
                        rct = SpawnRect[data10+diff][2];
                        // MakeTextTagAboveUnit нужно объявить до библиотеки Spawn
                        //MakeTextTagAboveUnit( u, "|c000000FFBack to Home!|r", 1.0, 1.0, 2.0, 0.5, 255, 255, 255, 255);
                        BJDebugMsg("Юнит побежал домой!");
                    }
                    
                }
                IssuePointOrder(u, "attack", GetRectCenterX(rct), GetRectCenterY(rct));
            }
            rct = null;
        }
        
        function OrderBackToLineB(unit u) { OrderBackToLine(u, 0); }
        function OrderBackToLineR(unit u) { OrderBackToLine(u, 3); }
    }

    function onInit(){
        //B - Линия 1
        SpawnRect[0][1] = gg_rct_WayP_1x1;
        SpawnRect[0][2] = gg_rct_WayP_1x2;
        SpawnRect[0][3] = gg_rct_WayP_1x3;
        SpawnRect[0][4] = gg_rct_WayP_1x4;
        SpawnRect[0][5] = gg_rct_WayP_1x5;
        SpawnRect[0][6] = gg_rct_WayP_1x6;
        SpawnRect[0][7] = gg_rct_RedMainBase;
        //B - Линия 2
        SpawnRect[1][1] = gg_rct_WayP_2x1;
        SpawnRect[1][2] = gg_rct_WayP_2x2;
        SpawnRect[1][3] = gg_rct_WayP_2x3;
        SpawnRect[1][4] = gg_rct_WayP_2x4;
        SpawnRect[1][5] = gg_rct_RedMainBase;
        //B - Линия 3
        SpawnRect[2][1] = gg_rct_WayP_3x1;
        SpawnRect[2][2] = gg_rct_WayP_3x2;
        SpawnRect[2][3] = gg_rct_WayP_3x3;
        SpawnRect[2][4] = gg_rct_WayP_3x4;
        SpawnRect[2][5] = gg_rct_WayP_3x5;
        SpawnRect[2][6] = gg_rct_WayP_3x6;
        SpawnRect[2][7] = gg_rct_RedMainBase;
    
         //R - Линия 1
        SpawnRect[3][1] = gg_rct_WayP_1x6;
        SpawnRect[3][2] = gg_rct_WayP_1x5;
        SpawnRect[3][3] = gg_rct_WayP_1x4;
        SpawnRect[3][4] = gg_rct_WayP_1x3;
        SpawnRect[3][5] = gg_rct_WayP_1x2;
        SpawnRect[3][6] = gg_rct_WayP_1x1;
        SpawnRect[3][7] = gg_rct_BlueMainBase;
        //R - Линия 2
        SpawnRect[4][1] = gg_rct_WayP_2x4;
        SpawnRect[4][2] = gg_rct_WayP_2x3;
        SpawnRect[4][3] = gg_rct_WayP_2x2;
        SpawnRect[4][4] = gg_rct_WayP_2x1;
        SpawnRect[4][5] = gg_rct_BlueMainBase;
        //R - Линия 3
        SpawnRect[5][1] = gg_rct_WayP_3x6;
        SpawnRect[5][2] = gg_rct_WayP_3x5;
        SpawnRect[5][3] = gg_rct_WayP_3x4;
        SpawnRect[5][4] = gg_rct_WayP_3x3;
        SpawnRect[5][5] = gg_rct_WayP_3x2;
        SpawnRect[5][6] = gg_rct_WayP_3x1;
        SpawnRect[5][7] = gg_rct_BlueMainBase;
    }
}

//! endzinc
В глобальных переменных объявить двумерный массив нельзя.
В JASS нет двумерных массивов, просто препроцессоры zinc,vJass,cJass добавляют синтаксический сахар и используют одномерные.
поскольку нужно передавать массив, либо писать дикий костыль на определение массивов, что я не люблю делать.
Можно и двумерным справиться без костылей.
0
30
5 лет назад
Отредактирован Clamp
0
Пробовал этот вариант, но это в этом случае будет постоянный рост событий в триггере, как я уже писал.
И что? У тебя вряд ли на карте больше пары тысяч юнитов будет, вычислительная нагрузка просто смешная.

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

Самым попсовым вариантом было и является попадание юнита на карту и добавление ему события "получает урон"
Мне это льстит, кстати. На тот момент моё решение было единственным известным мне, использующим такой подход. =Р

Короче свой метод я испытывал и даже когда-то сравнивал по эффективности (втч вычислительной) со всеми альтернативами, что тогда нашёл. В общем случае это лучшее решение без лишних сущностей. Бывают кейсы, когда более уместным решением будет какое-нибудь специфичное, но на практике создание этого специфичного решения потратит куда как больше сил и времени, чем просто использование готового.

Погугли про преждевременную оптимизацию например. Карта должна работать, насколько эффективно она это делает - вопрос вторичной важности.
1
29
5 лет назад
1
Пробовал этот вариант, но это в этом случае будет постоянный рост событий в триггере
Уже на сайте не раз обсуждалось, если юнит удалён из карты, триггером или после смерти->разложения, то и событие удаляется.
0
30
5 лет назад
0
NazarPunk, это я считал само собой разумеющимся, собственно.
0
16
5 лет назад
0
Если что-то тупо, но работает, это не тупо. Да, в доте далеко не лучший код, местами ужасный, но он работает, большего от него не надо. Там нет сложных тяжеленных систем и все свободные ресурсы идут на обработку говнокода, это норма. Вот если у тебя, кроме копипасты доты, еще и свои системы тяжелые идут, тогда да, есть смысл париться и выбивать каждую операцию. В остальных случаях - не стоит.
0
30
5 лет назад
0
DracoL1ch, ну тут в целом у автора проблема как раз в том, что с какого-то момента работать перестаёт, ятп. А так да, выше тоже самое написал по сути.
0
8
5 лет назад
0
NazarPunk:
В JASS нет двумерных массивов, просто препроцессоры zinc,vJass,cJass добавляют синтаксический сахар и используют одномерные.
Нужно почитать будет про то, как встраиваются zinc, vJass, cJass. Потом обязательно посмотрю это, спасибо за совет.
Я скорее вернулся в варик делать карту из ностальгических побуждений и из-за новости о выходе Refordged версии. А так когда-то помню начинал с него.

Уже на сайте не раз обсуждалось, если юнит удалён из карты, триггером или после смерти->разложения, то и событие удаляется.
Честно сказать, не знал. Это упрощает некоторые моменты. На сайте всего месяц от силы.

DracoL1ch:
Вот если у тебя, кроме копипасты доты
Не симпатизирует дота, так что не копирую ее, суть карты в другом. Но в целом мысль понял.

Clamp:
Все верно. Твой метод вполне имеет место быть. Спасибо за наработку.

После целого дня тестов, эмпирическим путем понял, что баг находится в ИИ компа (не в спауне, и не в движении юнитов по точкам)
Буду дальше тестить, позже отпишусь где он находится.
1
30
5 лет назад
1
Честно сказать, не знал.
Считай, что событие, связанное с юнитом, является его частью, это будет очень близко к истине.
0
29
5 лет назад
Отредактирован nazarpunk
0
"ForceLine*" есть 2 варианта развития, один это сделать поиск необходимого региона по которому он будет выбирать как реагировать на то или иное событие, либо сделать 6 триггеров, каждый из которых отдельно вызывается. Конечно, если бы я понимал, что у меня возможно будет какое-то изменение в будущем в плане количество спаунов, то лучше было бы сделать один триггер обрабатывающий все, тут согласен.
"Line*" однозначно нужно разделить на 3 части, поскольку нужно передавать массив, либо писать дикий костыль на определение массивов, что я не люблю делать. Если писать, то сразу основательно. Там логика может отличаться. Поэтому нужно сохранить 3 линии для удобства изменения условий для каждой линии.
Держите, убрал лишние триггеры, чтоб не мешались, и прикрутил нормальную наработку для путей. Притом без всяких динамических триггеров, костылей и на одномерных массивах.
Загруженные файлы
0
17
5 лет назад
0
Clamp, DestroyDialog() тоже отвязывает от диалога событие, недавно споткнулся об это и долго не мог понять в чём дело. Если при инициализации создать и объявить диалог переменной, на эту переменную завязать диалог, то при уничтожении диалога от него отвязывается событие. Даже если тутже заменить диалог новым.
Пришлось решать путём 3х массивов диалогов...
0
29
5 лет назад
Отредактирован nazarpunk
0
на эту переменную завязать диалог, то при уничтожении диалога от него отвязывается событие
По логике в переменной лежит только ссылка на диалог, и при уничтожении диалога логично уничтожаются его события, а в переменной остаётся null, у уоторого событий в принципе быть не может.
может и не null остаться, а ссылка намертво повиснуть в памяти
Чтобы оставить комментарий, пожалуйста, войдите на сайт.