wc3 1.31 и lua
Собственно такой вопрос. Если сделать
GroupEnumUnitsInRange(group,500,500,500,Condition(function() )
то Condition удаляется или создает утечку ? или все таки лучше делать
b=Condition(function() )
GroupEnumUnitsInRange(group,500,500,500,b)
DestroyBoolexpr(b)
просто заметил, что внутри condition можно из первого примера использовать все локалки в триггере и это очень круто, что не скажешь про второй вариант, пытался давать функции обьекты и они не передавались а сама функция работала
b=Condition(function(object) )
GroupEnumUnitsInRange(group,500,500,500,b(object))
Или все таки лучше использовать глобалки и без них никак ? Просто волнует вопрос по поводу, что если одну глобалку использовать на группу для множества игроков, То не будет ли глобалка перебиваться вечно разными игроками и в конце концов будет ссылаться на других игроков, или там какая то шляпа, что такого не будет ? Вот что то типа этого. Просто хотелось бы создать кондишн 1 раз занести его в глобалку и использовать постоянно, но не будет ли вечено перебивать игроков ? Просто если даже создать локально то уже все локалки не могут быть использованы в групенум....
B=Condition(function())
	P=GetFilter()
	if P==PLAYER then
	
	end 
end)

function()
	PLAYER=GetTriggerPlayer()
	GroupEnumUnitsInRange(group,500,500,500,B)
end
Надеюсь понятно.

Без ответа.


Просмотров: 222

» Лучшие комментарии


NazarPunk #1 - 1 месяц назад (отредактировано ) 1
Чтоб не мучиться, обойдитесь вообще без фильтров:
GROUP = CreateGroup() -- Глобальная группа, чтоб не создавать каждый раз.

-- в самом триггере
GroupEnumUnitsInRange(GROUP, x, y, range, nil)
local target ---@type unit
while true do
	target = FirstOfGroup(GROUP)
	if target == nil then break end -- выходим из цикла при пустой группе
	
	if UnitAlive(target) then -- условия для перебора
		KillUnit(target) -- действия для перебора
	end
	
	GroupRemoveUnit(GROUP, target)
end
Hate #2 - 1 месяц назад (отредактировано ) 1
NazarPunk:
Чтоб не мучиться, обойдитесь вообще без фильтров:
GROUP = CreateGroup() -- Глобальная группа, чтоб не создавать каждый раз.

-- в самом триггере
GroupEnumUnitsInRange(GROUP, x, y, range, nil)
local target ---@type unit
while true do
	target = FirstOfGroup(GROUP)
	if target == nil then break end -- выходим из цикла при пустой группе
	
	if UnitAlive(target) then -- условия для перебора
		KillUnit(target) -- действия для перебора
	end
	
	GroupRemoveUnit(GROUP, target)
end
это мнение, а не ответ на вопрос, и многим было бы полезно узнать его
DracoL1ch #3 - 1 месяц назад 4
фильтры не текут
NazarPunk #4 - 1 месяц назад 0
это мнение, а не ответ на вопрос, и многим было бы полезно узнать его
Можно подумать логически и заглянуть в common.j.
---@class agent:handle -- all reference counted objects
---@class boolexpr:agent

---@class conditionfunc:boolexpr
---@class filterfunc:boolexpr

---@param func code
---@return filterfunc
function Filter(func) end

---@param func code
---@return conditionfunc
function Condition(func) end
Как видно Filter и Condition создают и возвращают boolexpr и вродибы раньше Condition кэшировалось, а как реализовали в lua хз, но поидее должен прийти сборщик мусора и всё подчистить.
prog #5 - 1 месяц назад (отредактировано ) 0
DracoL1ch, при использовании в луа с анонимными функциями - очень даже текут потому как не удаляются, насколько я знаю, а анонимная функция при каждом вызове новая создается и передается в создание фильтра.

поидее должен прийти сборщик мусора и всё подчистить
Сборщик мусора Lua не подчищает нативные обьекты, к которым относятся и фильтры.

К сожалению, на данный момент на нативное кеширование фильтров и кондишнов при использовании луа полагаться нельзя, оно то ли не работает полностью то ли работает только в очень ограниченном наборе ситуаций, что и не удивительно, учитывая динамическую природу Lua. Нужно либо самостоятельно выполнять кеширование либо максимально обходиться без фильтров.
Решение которым пользуюсь я когда мне нужно передавать какие-то данные в фильтр из вызывающей функции выглядит примерно так:

local FilterData ={} -- локальная для кода карты глобалка для передачи данных в фильтры

local function FilterThemAll() --функция фильтра, использующая данные из глобалки
	local data = FilterData
	local p = data.player
	local target = data.target
	return false
end

local SomeFilter = Filter(FilterThemAll) -- создание фильтра для функции FilterThemAll - "ручное кеширование"

function GroupEnumUnitsInRangeCustom (g,r,x,y,f,data) -- функция инкапсулирующая передачу данных чрез глобалку и вызов GroupEnumUnitsInRange с фильтром
	local dataBack = FilterData
	FilterData = data
	GroupEnumUnitsInRange(g,r,x,y,f)
	FilterData = dataBack
end
Код примерный и писался сейчас из головы по памяти - для использования в реальных условиях могут быть нужны доработки и исправления ошибок.
NazarPunk #6 - 1 месяц назад 0
К сожалению, на данный момент на нативное кеширование фильтров и кондишнов при использовании луа полагаться нельзя
Тогда нужно отказываться от фильтров и не гадать, что там близы намудрили.
prog #7 - 1 месяц назад (отредактировано ) 2
NazarPunk, отказываться есть смысл тольо от использования анонимных функций в фильтрах - один раз записать фильтр в переменную и использовать никто не мешает.
quq_CCCP #8 - 1 месяц назад 1
NazarPunk, нужно отказыватся от луа и 1.31 до рефорджа и устранения всех проблем, то завтра близзарды сделают патч на котором будет утекать все и фаталить мили карты через 15 минут игры, будем как в том анекдоте, плакать, колоться и есть кактус?
PT153 #9 - 1 месяц назад (отредактировано ) 0
фильтры не текут
В Lua текут, в JASS нет, выясняли уже.
И лучше заносить фильтры в глобалки, тогда они доступны везде, даже до место определения фильтра. А вместо Condition советую использовать Filter, букв меньше.
Castiel #10 - 1 месяц назад (отредактировано ) 0
PT153:
фильтры не текут
В Lua текут, в JASS нет, выясняли уже.
И лучше заносить фильтры в глобалки, тогда они доступны везде, даже до место определения фильтра. А вместо Condition советую использовать Filter, букв меньше.
Все конечно хорошо, но если Filter(function()) будет занесена глобалку,вне триггера, то использовать локалки триггера в фильтре уже не возможно и нужно нужное заносить в глобалки. А если допустим таймер каждые 0.05 сек вызывает группу, то если все локалки будут заменены глобалками и использованы в глобальном фильтре, не будет ли фарша, когда глобалка перебивается другим игроком вызвавшим таймер, вот к примеру
P=nil

F=Filter(function())
	local f=GetFilterUnit()
	if IsUnitAlly(f,P) then
		какой то код
	end
end)

function TRG()
	local ab=GetSpellAbilityId()
	local u=GetTriggerUnit()

	if ab==A000 then
		local t=CreateTimer()
		SavePlayerHandle(hash,GetHandleId(t),0,GetOwningPlayer(u))
		TimerStart(,0.05,true,function()
			local t=GetExpiredTimer()
			local p=LoadPH(hash,GetHandleId(t),0)
			local g=CreateGroup()
			P=p
			GroupEnumUnitsInRange(group,500,500,500,F)
			DestroyGroup(g)
			if какое то условие then
				DestroyTimer(t)
				Flush....
			end
	end)
	
end
PT153 #11 - 1 месяц назад (отредактировано ) 0
не будет ли фарша, когда глобалка перебивается другим игроком вызвавшим таймер, вот к примеру
Не будет, на этом построен vJass.
А так да, при занесении в глобалку фильтр пне может быть кложуром.
Можно так, но тут снова каждый раз будет создаваться новый объект.
function u (p, id)
    B = Condition(function()
	    if p == GetOwningPlayer(GetFilterUnit()) and id == GetUnitId(GetFilterUnit()) then

	    end
    end)

	GroupEnumUnitsInRange(group, 500, 500, 500, B)
end
А ещё в фильтрах групп работает всякие GetTriggerUnit и так далее, их даже передавать не надо.
prog #12 - 1 месяц назад 0
Castiel, выбор стоит или глобалки или утечки. Если грамотно все сделать - проблем с передачей данных через глобалки не будет, пример выше в комментариях... И, кстати, варовские хештаблицы не нужны в Lua.
Castiel #13 - 1 месяц назад 0
кложуром
Я так понял единственный по ходу способ это через цикл...Что же лучше и быстрее перебирать через фильтр или через цикл ?
Просто мне очень понравилось, что GroupEnumUnitsInRange(group,500,500,500,Condition(function() ) может использовать все локалки триггера, это очень круто и удобно, другими способами заносить лишь в глобалки игроков и другие нужные данные, которые будут использоваться на группе...
prog:
Castiel, выбор стоит или глобалки или утечки. Если грамотно все сделать - проблем с передачей данных через глобалки не будет, пример выше в комментариях... И, кстати, варовские хештаблицы не нужны в Lua.
По подробней про ненадобность хеш таблицы ? Можно глобалку сделать GLOBAL[GetHanldeId(T)] ? А если там номер ключ 5782857? ничего страшного ?
PT153 #14 - 1 месяц назад 1
Castiel, как я уже сказал, можно даже ничего не передавать, а использовать GetTriggerUnit и прочее в самом фильтре. Можно передавать глобалками (или через таблицы Lua), тоже будет верно.
Циклом будет быстрее, удобнее и порой надёжнее, если операции внутри цикла короткие. Лично я фильтр использую там, где операции долгие, так как фильтр создаёт поток на каждого юнита.
Castiel #15 - 1 месяц назад 0
PT153:
Castiel, как я уже сказал, можно даже ничего не передавать, а использовать GetTriggerUnit и прочее в самом фильтре. Можно передавать глобалками (или через таблицы Lua), тоже будет верно.
Циклом будет быстрее, удобнее и порой надёжнее, если операции внутри цикла короткие. Лично я фильтр использую там, где операции долгие, так как фильтр создаёт поток на каждого юнита.
Спасибо бро!
PT153 #16 - 1 месяц назад 0
или утечки
По идее, уничтожение булэкспры должно помогать.
prog #17 - 1 месяц назад (отредактировано ) 0
Castiel, Рекомендую найти и по читать про основные принципы работы Lua. Например, в луа нет массивов как таковых - их роль выполняют таблицы, которые в зависимости от использования могут работать и как массивы и как ассоциативные массивы и как классы и как структуры. Соответственно, запись чего-то в "массив" по хендлу отлично работает, в отличии от джасса. Более того, в качестве ключей могут быть не только числа, но и строки и даже объекты, правда с объектами в качестве ключей надо осторожно обходиться и лучше не связываться без понимания происходящего. За это все приходится платить скоростью доступа к элементам - быстрее всего доступ когда все элементы строго нумерованы по порядку и только на числовых ключах, но даже в худшем случае это работает быстрее хештаблиц.

По идее, уничтожение булэкспры должно помогать.
И давно их можно уничтожать? o_O Вот это внезапная новость для меня. Всегда был уверен что нет возможности их уничтожить и в итоге даже не искал нативки для этого...

Окей, уточнение ситуации - нативки для уничтожения фильтров и кондишнов существуют. Соответственно - действительно, если очень хочется, то можно и фильтры с кложурами делать, а потом уничтожать их, теоретически течь не должно. Сперва объявляются все локалки которые должен видеть кложур, потом в локалку пишется фильтр, потом локалка с фильтром передается в Enum и потом фильтр удаляется. Правда через глобалки всеравно эффективнее должно быть т.к. создание дополнительных объектов и удаление их дороже обходится чем доступ к глобалкам.
PT153 #18 - 1 месяц назад 0
И давно их можно уничтожать? o_O Вот это внезапная новость для меня. Всегда был уверен что нет возможности их уничтожить и в итоге даже не искал нативки для этого...
В blizzard.j их всегда уничтожают.