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

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

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

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

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

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

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

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

Возможность передачи массива в функцию очень бы улучшило код, ведь для многих функций полиморфизм бы не помешал. (Знаю про vJass и cJass, но хочу работать только с нативными инструментами)
30
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);
}

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

По поводу двумерных массивов полностью согласен, что так можно решить проблему. Но я пока писал только на ГУИ, где таковых нет (за исключением хэш таблиц, которыми я начал пользоваться только недавно, когда начал использовать JASS). В глобальных переменных объявить двумерный массив нельзя. А если пытаться объявить глобальные в своем коде, то пишет ошибку, что глобальные должны быть объявлены в самом начале. Поэтому я пока обходился одномерными массивами, что вызвало подобное. Так что тут я с тобой полностью солидарен.
В идеале вообще создавать объект со своим набором полей и методов. Но я пока вначале пути JASS, так что пользуюсь только им. А вообще пишу на С++
Спасибо за рекомендации
30
"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 добавляют синтаксический сахар и используют одномерные.
поскольку нужно передавать массив, либо писать дикий костыль на определение массивов, что я не люблю делать.
Можно и двумерным справиться без костылей.
30
Пробовал этот вариант, но это в этом случае будет постоянный рост событий в триггере, как я уже писал.
И что? У тебя вряд ли на карте больше пары тысяч юнитов будет, вычислительная нагрузка просто смешная.

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

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

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

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

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

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

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

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