Всем привет я вот не давно нашел код скила оригинальной доты, и вот что я вижу в доте используется одна глобальная переменная GlobalUnit на всех способностях героев и предметов для того чтобы ловить условие и ForGroup. Оказывается глобальная переменная тоже может использоваться как локальная если грамотно сделать способности. А вот loop endloop. Мне кажется что ForGroup с глобалкой работает быстрее чем loop. В общем стоить ли использовать систему дота для своей способности или без разницы?
function C takes nothing returns nothing
local unit c=GetEnumUnit()
call UnitDamageTarget(GlobalUnit,c,200,false,true,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
set c = null
endfunction
function B takes nothing returns boolean
return IsUnitEnemy(GlobalUnit,GetOwningPlayer(GetFilterUnit())) and (GetUnitAbilityLevel(GetFilterUnit(),'A000')==0 and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false and (IsUnitType(GetFilterUnit(),UNIT_TYPE_DEATH)==false
endfunction
function A takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = LoadUnitHandle(H,GetHandleId(t),0)
local group g = CreateGroup()
set GlobalUnit=u
call GroupEnumUnitsInRange(g,GetUnitX(u),GetUnitY(u),1200,Condition(function B))
call ForGroup(g,function C)
call DestroyGroup(g)
if TIMER == 5 then
set TIMER = 0
call FlushChildHashtable(H,GetHandleId(t))
call PauseTimer(t)
call DestroyTimer(t)
else
set TIMER = TIMER + 1
endif
set u = null
set g = null
set t = null
endfunction

20 раз кидаю
вся разница что есть - околонулевая...
"Заметно медленнее" вы тролите? на сколько медленнее? прям замечали, прям глазом, как задержки идут при переборе 30 юнитов в лупе и 30 юнитов в ForGroup.. Прям Fps в нули просаживается. В картах типа доты, может быть перебор либо пачки юнитов ну реально в глубоком лейте 30 штук, когда Ember Spirit кастует что-то раз в 10 сек или когда зевс ультует идёт перебор всех героев + клонов + иллюзий раз в 2 минуты. И ту начинается раздуемье, а как же перебрать, может по массиву пройтись и заранее всех занести...
Рили это рофл? что за байтодрочерсво?
DracoL1ch, У тебя есть бенчмарк вызова функций в мемхаке верно? (ну или что-то типа этого)
Давай результаты: 30 юнитов в LOOP и 30 юнитов через ForGroup иначе это всё бесполезнейшее 3,14здабольство и байтодрочерство, я не спорю что быстрее, но эта разница на столько мала, что тема не требует обсуждения.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
14
DracoL1ch:
FirstOfGroup берет-то первый элемент, но тебе его удалять, а после этого итерация всех элементов, чтобы упорядочить их
ну не веришь - не верь, делов-то. перегрев на создании отдельных потоков идет, очевидно, что это тяжелее, чем продолжение работы в том же потоке, как цикл делает
группы как раз в доте небольшие, поэтому цикл выгоднее в 99.9% случаев.
что ты подразумеваешь под словом "небольшие"? если для доты группы небольшие то сколько должно быть юнитов что бы группа была большой?
38
Ну затестите, возьмите 1к юнитов, таймер есть вроде как
16
function SpeedRun takes nothing returns nothing

local group g=GetAvailableGroup()
local unit u2
local player p
call GroupEnumUnitsInRange(g,0,0,10000,null)
call echo("unit count="+I2S(CountUnitsInGroupNative(g)))
call fStartTimer()
loop
set u2=FirstOfGroup(g)
exitwhen u2==null
call GroupRemoveUnit(g,u2)
call DoNothing()
endloop
call BJDebugMsg("Variant 1: "+I2S(fStopTimer()))
call ExecuteFunc("SpeedRunX")
endfunction
function SpeedRunX takes nothing returns nothing

local group g=GetAvailableGroup()
local unit u2
local player p
call GroupEnumUnitsInRange(g,0,0,10000,null)
call echo("unit count="+I2S(CountUnitsInGroupNative(g)))
call fStartTimer()
call ForGroup(g,function DoNothing)
call BJDebugMsg("Variant 2: "+I2S(fStopTimer()))
endfunction

function SpeedRun2 takes nothing returns nothing
	local integer i=0
	loop
		call ExecuteFunc("SpeedRun")
		set i=i+1
		exitwhen i>=10
	endloop
endfunction
Загруженные файлы
14
DracoL1ch:
function SpeedRun takes nothing returns nothing

local group g=GetAvailableGroup()
local unit u2
local player p
call GroupEnumUnitsInRange(g,0,0,10000,null)
call echo("unit count="+I2S(CountUnitsInGroupNative(g)))
call fStartTimer()
loop
set u2=FirstOfGroup(g)
exitwhen u2==null
call GroupRemoveUnit(g,u2)
call DoNothing()
endloop
call BJDebugMsg("Variant 1: "+I2S(fStopTimer()))
call ExecuteFunc("SpeedRunX")
endfunction
function SpeedRunX takes nothing returns nothing

local group g=GetAvailableGroup()
local unit u2
local player p
call GroupEnumUnitsInRange(g,0,0,10000,null)
call echo("unit count="+I2S(CountUnitsInGroupNative(g)))
call fStartTimer()
call ForGroup(g,function DoNothing)
call BJDebugMsg("Variant 2: "+I2S(fStopTimer()))
endfunction

function SpeedRun2 takes nothing returns nothing
	local integer i=0
	loop
		call ExecuteFunc("SpeedRun")
		set i=i+1
		exitwhen i>=10
	endloop
endfunction
это про большую группу??

какой чел станет абилку с радиусом в 10000ед.? кроме того если Дебагом выдавать кол-во юнитов хз что будет мб игра вылетит только подумай за 0.000000001 сек. 20 раз выбрать юнитов радиусе 10000 ед. и выдать столько же раз их значение
28
Быстрее форгрупа и лупа будет булекспр

Да и учитывая как криво группами пользуешься (ради одного действия в форгруп инициализируешь локалку, нет темповой глобалки группы, не переменишь фильтрующего юнита в глобалку) лучше и вправду юзать цикл (искл если юнитов больше оп лимита)
14
rsfghd:
Быстрее форгрупа и лупа будет булекспр

Да и учитывая как криво группами пользуешься (ради одного действия в форгруп инициализируешь локалку, нет темповой глобалки группы, не переменишь фильтрующего юнита в глобалку) лучше и вправду юзать цикл (искл если юнитов больше оп лимита)
не думаю что одна глобалка хороший вариант
представим что на карте 4 триггерной волны силы
если приказать героям скастовать их одновременно то представь с какой скорость будет использована глобалка я например узаю тик тайма 0.01 и дальность волны 1000 а скорость 25 это 1000/25 = 40; 40 * 4 = 160 значит за 4 каста будет использована 160 раз лишь 1 глобалка хз может я себя накручиваю но не износ ли это? по этому я всегда делаю так
set bj_lastCreatedGroup = CreateGroup()
и дальше все что нужно незачем пользоваться 1 глобалкой потому что такой вариант за 0.01 секунду создастся и удалится без всякой нагрузки но это все лишь мои догадки и может быть я не прав

плюс к всему этому даже Handle Counter не реагирует на это а только на 2 вещи это созданный дамми и созданная группа для того что бы урон наносился лишь раз
18
Быстрее форгрупа и лупа будет булекспр
Пожалуйста пруфы
Гуванч:
но не износ ли это?
Правильно ли я понял, что вы считаете, что у переменных есть "износ" записи или чтения?
25
но не износ ли это?
Нет никакого износа, и нет никакой разницы сколько раз в секунду используется переменная.
Наложения в использовании тоже не будет. В варкрафте все действия происходят строго последовательно, и пока текущая цепочка выполнения не закончится, следующая не начнется.

Пожалуйста пруфы
Ну я так понимаю тут суть в том, что при пике через булэкспр в группу вообще не заносятся юниты. То есть связный список вообще не задействуется, и заниматься очисткой тоже потом не надо.
Хотя в реалиях варкрафта конечно все надо проверять на практике, так как разрабы были очень кривые.
8
Наложения в использовании тоже не будет.
Если быть достаточно неаккуратным - будет. Например вот такой вот код, при использовании глобалок сработает совсем не так, как ожидалось:
globals
    unit u1
    unit u2
    unit u3
endglobals
function Trig_REVENGE_Actions takes nothing returns nothing
    set u1 = GetTriggerUnit()
    set u2 = GetEventDamageSource()
    set u3 = CreateUnit(GetOwningPlayer(u1),'h000',GetUnitX(u2),GetUnitY(u2),0)
    call UnitAddAbility(u3,'A000')
    call IssueTargetOrder(u3,"thunderbolt",u2)
    call RemoveUnit(u3)
endfunction
И все это, о ужас! будет зависить от внешних условий, так что использование глобалок - способ получить обидную и неприятную ошибку.
Загруженные файлы
28
goodlyhero, что этот код вообще должен делать непонятно, ведь юнит даже не сможет кастануть абилку, сразу удалившись
Vlod:
Пожалуйста пруфы
Помимо слов Ханабиши, quq_CCCP говорил, что булекспры вообще другая машина обрабатывает
Гуванч:
по этому я всегда делаю так
set bj_lastCreatedGroup = CreateGroup()
Я тебе говорил юзай спокойно одну глобалку, не нужно создавать и уничтожать, и не только я один, помню Берги ещё писал. Но ты никого не слушаешь как всегда. У тебя происходит 3 действия вместо 1 (если делать действия в булекспре): создание, перебор, удаление

То есть таким образом ты делаешь куда большую нагрузку, чем использование одной глобалки. Бенчмарк в помощь
25
Если быть достаточно неаккуратным - будет. Например вот такой вот код, при использовании глобалок сработает совсем не так, как ожидалось:
Можешь сделать эти переменные локальными - ничего не поменяется. Этот код всегда будет работать так, как ты его написал. Никаких зависимостей от внешних условий тут нет.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.