Путем отладки мне удалось найти функцию из-за которой мои герои внезапно удаляются. Ниже приведен код функции в которой это происходит - DummyDealExtraDamage и на всякий случай сверху вставлю функцию отложенного удаления юнита.
Отладка показывает что именно эта функция пытается удалить героя на месте вызова DelayedUnitRemove, хотя туда отчетливо подается dummy и только, причем дамми который был создан пару строчек назад. Как туда мог попасть герой - не понятно.
Баг проявляется отнюдь не всегда, в 1 из 15 случаев примерно. И не у всех персонажей, использующих DummyDealExtraDamage.
Есть какие-то предположения?
	void DelayedUnitRemove(unit u, float time, string fname, string moduleName)
	{
		if (time == 0.00)
		{
			RemoveUnit_s(u, fname, moduleName);
			u = null;
			return;
		}
		timer t = CreateTimer();
		SaveUnitHandle(g_Hashtable, GetHandleId(t), T_UNIT, u);
		SaveStr(g_Hashtable, GetHandleId(t), T_UNIT+1, fname);
		SaveStr(g_Hashtable, GetHandleId(t), T_UNIT+2, moduleName);
		TimerStart(t, time, false, lambda void ()
		{
			timer t = GetExpiredTimer();
			unit u = LoadUnitHandle(g_Hashtable, GetHandleId(t), T_UNIT);
			string fname = LoadStr(g_Hashtable, GetHandleId(t), T_UNIT+1);
			string moduleName = LoadStr(g_Hashtable, GetHandleId(t), T_UNIT+2);
			RemoveUnit_s(u, fname, moduleName);
			DestroyTimer(t);
			u = null;
			t = null;
		});
		t = null;
		u = null;
	}
	
	
	void DummyDealExtraDamage(unit src, unit target, float dmg, int school, bool canBeReturned)
	{
		if (IsUnitDummy(src))
		{
			src = GetDummyOwningUnit(src);
			DummyDealExtraDamage(src, target, dmg, school, canBeReturned);
			src = null;
			target = null;
			return;
		}
		location loc = GetUnitLoc(src);
		unit dummy = CreateDummy(GetOwningPlayer(src), src, loc);
		SetDummyExtraDamage(dummy);
		if (!canBeReturned)
		{
			SetDummyReturnDamage(dummy);
		}
		DummyDealDamage(dummy, target, dmg, school);
		DelayedUnitRemove(dummy, 0.2, "DummyDealExtraDamage", "Dummy");
		RemoveLocation(loc);
		loc = null;
		dummy = null;
		src = null;
		target = null;
	}

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

Точно больше 100500 утечек нет? Эт хз как же надо было забить хт чтобы такое приключилось?
`
ОЖИДАНИЕ РЕКЛАМЫ...
2
19
5 лет назад
2
Похожие вопросы:

ответ
Группы юнитов + хэш или структуры. При касте спелла берешь кастера, берешь его ID, проверяешь не записана ли группа в какой-либо из ячеек. Если нет - создаешь группу и записываешь её в ячейку. При смерти юнита делаешь проверку не записана ли по его ID группа юнитов - если записана - удаляешь его и проверяешь количество юнитов в группе и если оно равно 0 - удаляешь группу. Естественно хэш тоже чистишь всюду где нужно.

Это звучит как "Сделайте мне пожалуйста систему формаций". Чтобы научить тебя как это сделать придётся потратить несколько десятков часов. И тут 2 варианта: либо ты будешь читать статьи и выучишь всё сам, либо обращайся к отдельным пользователям и проси о приватных, платных, уроках в частном порядке.
Вопрос вообще ни о чём. То, о чём ты спрашиваешь делается за 20-30 минут + несколько часов на всякие плюшки и дебаг (в худшем случае).
Конкретно тебе стоит почитать о Локальных переменных, Хэше или Структурах.
ответ
Юзай XT + структуры.
Лично я ХТ использую только для связи инстанции структуры и таймера.

0
28
5 лет назад
0
IsUnitDummy(src)
GetDummyOwningUnit(src)
CreateDummy(GetOwningPlayer(src), src, loc)
Что внутри этих функций?

Тут используются дефайны?
0
16
5 лет назад
0
PT153:
IsUnitDummy(src)
GetDummyOwningUnit(src)
CreateDummy(GetOwningPlayer(src), src, loc)
Что внутри этих функций?
bool IsUnitDummy(unit u)
	{
		if (u == null || IsUnitType(u, UNIT_TYPE_HERO))
		{
			if (IsUnitType(u, UNIT_TYPE_HERO))
			{
				GroupRemoveUnit(g_Dummies, u);
			}
			return false;
		}
		return IsUnitInGroup(u, g_Dummies);
	}
	
	unit GetDummyOwningUnit(unit dummy)
	{
		if (dummy == null)
		{
			return null;
		}
		return LoadUnitHandle(g_Hashtable, GetHandleId(dummy), DUMMY_OWNER);
	}

unit CreateDummy(player owner, unit uOwner, location loc)
	{
		unit dummy = CreateUnitAtLoc(owner, 'n001', loc, GetUnitFacing(uOwner));
		SaveUnitHandle(g_Hashtable, GetHandleId(dummy), DUMMY_OWNER, uOwner);
		SaveBoolean(g_Hashtable, GetHandleId(dummy), DUMMY_RETURN_DMG, false);
		SaveBoolean(g_Hashtable, GetHandleId(dummy), DUMMY_EXTRA_DMG, false);
		SaveBoolean(g_Hashtable, GetHandleId(dummy), DUMMY_DO_PERIODIC, false);
		SaveReal(g_Hashtable, GetHandleId(dummy), DUMMY_DMG_PERIOD, 0);
		SetDummySpellId(dummy, 0);
		SetDummySchool(dummy, SCHOOL_NONE);
		SetUnitPathing(dummy, false);
		GroupAddUnit(g_Dummies, dummy);
		owner = null;
		uOwner = null;
		loc = null;
		return dummy;
	}

PT153:
Тут используются дефайны?
Все что сплошным капсом - это дефайны.
0
28
5 лет назад
Отредактирован PT153
0
У DUMMY_OWNER и T_UNIT разные значения?

Я тут пока смотрел, заметил, что ты вообще не чистишь хеш. Ни для таймера уделения, ни для самого даммика. Стоит исправить это.
Аргументы функций обнулять не нужно.

Я не вижу ни одной причины, почему тут может удалятся герой. Думал на отсутствие очистки хеша, но ведь после создания таймера ячейка перезаписывается, то есть там хранится уже даммик. Может ты скопипастил, а потому в действительно ошибочной функции стоит название этой функции?
0
16
5 лет назад
Отредактирован Drulia_san
0
PT153:
У DUMMY_OWNER и T_UNIT разные значения?

Я тут пока смотрел, заметил, что ты вообще не чистишь хеш. Ни для таймера уделения, ни для самого даммика. Стоит пока исправить это.
Аргументы функций обнулять не нужно.

Я не вижу ни одной причины, почему тут может удалятся герой. Думал на отсутствие очистки хеша, но ведь после создания таймера ячейка перезаписывается, то есть там хранится уже даммик. Может ты скопипастил и где-то ввёл неверное название функции?
DUMMY_OWNER = 150
T_UNIT = 159
Упс, а хеш-таблицы надо чистить? Не ну это уже совсем дичь. Код захламится на треть очисткой хеш-таблицы. У меня сотни мест где я её использую и не чищу вообще. Ну потому что это уже через чур, и переменные обнулять, и ладно ресурсы удалять, но хеш чистить эт перебор, ненене, работает так и норм. Пусть он в памяти будет толстенный, как-нибудь переживу. Размер на логичность поведения влиять не должен, не 4 гб же там в памяти. Все равно пишет в одни и те же ячейки, перезаписывая.
Я проверил, нигде нет этого названия. Я не копипастил лишнее, баг именно в этой функции.
2
28
5 лет назад
2
Упс, а хеш-таблицы надо чистить?
Надо. Благо есть такая функция.
native FlushChildHashtable takes hashtable table, integer parentKey returns nothing
Скармливаешь хендл таймера или даммика, и все записанные поля обнуляются.
0
16
5 лет назад
0
PT153:
Упс, а хеш-таблицы надо чистить?
Надо. Благо есть такая функция.
native FlushChildHashtable takes hashtable table, integer parentKey returns nothing
Скармливаешь хендл таймера или даммика, и все записанные поля обнуляются.
Тогда это всё упрощает, очистку хештейбла запихну в функцию безопасного удаления юнита, и сделаю такую же функцию для таймеров, и можно считать что таблица очищена от лишнего.
2
28
5 лет назад
2
Было бы неплохо глянуть на тру JASS (то есть уже после обработки cJass) функций, что в шапке.
0
16
5 лет назад
0
PT153:
Было бы неплохо глянуть на тру JASS (то есть уже после обработки cJass) функций, что в шапке.
Странно, но когда я добавил очистку очистку хеш-таблицы к удалению таймеров и юнитов этот баг перестал появляться)
2
32
5 лет назад
2
Точно больше 100500 утечек нет? Эт хз как же надо было забить хт чтобы такое приключилось?
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.