Всем привет! Мой вопрос собственно заключается в том, что правильно ли я сделал, если допустим есть способность кровотечение, которая вызывает кровотечение на юнитах. Суть в том, что допустим 10 юнитов получили кровотечение и получают урон, на 5 из них допустим через 2 секунды опять оказало действие кровотечение, а на тех, что не получили изначально получат через 1 секунду. Собственно сделать через один таймер кровотечение на группу юнитов с разными таймера их действия, чтоб кровотечение обновлялось, а не тупо стакалось на 100500 таймеров... Я понимаю, что нужно через переменную проверять и собсвтенно это сделал..Но вопрос в том, пойдет ли данная схема, если допустим несколько игроков запустят таймеры для себя, не будут ли сбиваться переменные передаваемые через функцию и вообще рабочая ли эта схема ? У меня вроде все работает...но хотелось бы узнать мнение экспертов )))
	local PS_DMG_PERC=.25

	local PS_GROUP={}
	local PS_TIMER_BLEED={}
	local PS_TIME_UNIT={}
	
PS_Opgh_FUNC=function(caster,caster_uid,target,target_uid)

		if PS_GROUP[caster_uid]==nil then

			local size
			local fg
			local id
			local damage

			PS_GROUP[caster_uid]=CreateGroup()
			PS_TIMER_BLEED[caster_uid]=CreateTimer()
			PS_TIME_UNIT[caster_uid]={}

			TimerStart(PS_TIMER_BLEED[caster_uid],1,true,function()

				damage=GetHeroStr(caster,true)*PS_DMG_PERC

				size=BlzGroupGetSize(PS_GROUP[caster_uid])

				print("7")
				if size==0 then
					DestroyGroup(PS_GROUP[caster_uid])
					PS_GROUP[caster_uid]=nil
					DestroyTimer(PS_TIMER_BLEED[caster_uid])
					PS_TIMER_BLEED[caster_uid]=nil
					PS_TIME_UNIT[caster_uid]=nil
					return
				elseif size>=1 then
					for i=size-1,0,-1 do

						fg=BlzGroupUnitAt(PS_GROUP[caster_uid],i)
						id=GetHandleId(fg)
						if UnitAlive(fg) and not BlzIsUnitInvulnerable(fg) then

							UnitDamageTarget(caster,fg,damage,false,false,ATTACK_PHYSICAL,DAMAGE_PHYSICAL,nil)

							PS_TIME_UNIT[caster_uid][id]=PS_TIME_UNIT[caster_uid][id]-1

							if PS_TIME_UNIT[caster_uid][id]==0 then
								GroupRemoveUnit(PS_GROUP[caster_uid],fg)
								PS_TIME_UNIT[caster_uid][id]=nil
							end
						else
							GroupRemoveUnit(PS_GROUP[caster_uid],fg)
							PS_TIME_UNIT[caster_uid][id]=nil
						end
					end
				end

				size=BlzGroupGetSize(PS_GROUP[caster_uid])
				if size==0 then
					DestroyGroup(PS_GROUP[caster_uid])
					PS_GROUP[caster_uid]=nil
					DestroyTimer(PS_TIMER_BLEED[caster_uid])
					PS_TIMER_BLEED[caster_uid]=nil
					PS_TIME_UNIT[caster_uid]=nil
				end
			end)
		end

		if PS_GROUP[caster_uid]~=nil then
			if not IsUnitInGroup(target,PS_GROUP[caster_uid])then
				GroupAddUnit(PS_GROUP[caster_uid],target)
				PS_TIME_UNIT[caster_uid][target_uid]=3
			else
				PS_TIME_UNIT[caster_uid][target_uid]=3
			end
		end
	end

Прежде всего, зачем по таймеру для каждого игрока, а тем более на каждого кастера, если можно обойтись одним таймером на всех?
Группы я бы тоже не хранил для каждого игрока, а вместо этого хранил бы по хендлу цели сколько осталось тактов кровотечения и от чьего имени наносить урон, а всех юнитов с кровотечением складывал бы в одну группу для всех.
Постоянное создание-удаление групп, в принципе, тоже не лучшая идея, лучше их чистить и повторно использовать.
Ну и я бы не стал использовать анонимную функцию в таймере - она тут не нужна, все отлично передается глобалками.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
28
prog, Castiel, а зачем вам хэндл юнита вообще?
можно просто хранить всех юнитов и данные в массиве и в таймере пробегать циклом по массиву
24
nvc123, можно, конечно. Но, например, у себя в картах я обычно храню намного больше информации привязаной к юнитам - если бы каждая система хранила свои данные в массиве, то удаление этих данных превратилось бы в ад, как и доступ к этим данным вне перебора. Вот когда удаление и доступ к данным просходит только внутри одной системы и только внутри перебора, то можно и в массив без хендлов сложить, конечно.
8
nvc123:
prog, Castiel, а зачем вам хэндл юнита вообще?
можно просто хранить всех юнитов и данные в массиве и в таймере пробегать циклом по массиву
не бро, тут не получиться просто так все сделать. По большому счету, нужно кровотечение не складывать,а обновлять от одного и того же источника. Я уже пробовал много разных вариантов и все равно самый удобный получился мой первый вариант, о котором я спрашивал, но немного переработанный и без лишних телодвижений. Через один таймер как советовали, то получается один таймер обрабатывает 1 и ту же группу по несколько раз за секунду. Там при одном таймере слишком много проверок получается при добавлении или обновлении. И перебор через паирс мне не понравился. Сделал таймер для несколих групп для каждого источника, и удалять их когда нет целей, и с таймерами точно так же...Через именную функцию для таймера и сохранением таймер и хендл таймера на кастера и кастера с целями на хендл таймера, короче все получилось нормально и рабочее. Хотя не читаемо для того кто это увидит )))
24
Castiel, создание-удаление таймеров и групп намного дороже обходится чем pairs, если что...
Ну и еще один нюанс - что ты будеш делать когда захочеш снимать кровотечение с цели каким-нибудь бинтом или очищением или рассеиванием или еще чем-нибудь, до истечения длительности кровотечения? В моей реализации данные о кровотечении хранятся по хендлу цели поэтому до них очень легко добраться зная только цель, в твоей же реализации тебе надо обязательно знать кастера прежде чем ты сможеш добраться до данных о кровотечении на цели.
8
prog:
Castiel, создание-удаление таймеров и групп намного дороже обходится чем pairs, если что...
Ну и еще один нюанс - что ты будеш делать когда захочеш снимать кровотечение с цели каким-нибудь бинтом или очищением или рассеиванием или еще чем-нибудь, до истечения длительности кровотечения? В моей реализации данные о кровотечении хранятся по хендлу цели поэтому до них очень легко добраться зная только цель, в твоей же реализации тебе надо обязательно знать кастера прежде чем ты сможеш добраться до данных о кровотечении на цели.
Хмммм....Я думал, что паирс слишком уж тугой) попробую все переделать, но я вчера бился над этой проблемой 4 часа ))так и не сделал вернулся к своему старому способу, видать я тугой в этом деле! Просто когда начинал делать всплывало много нюансов по реализации данной системы, по этому я способа 4 перебрал и ниодин не то, что не подходил, и даже не был рабочим, а то что получается цикл перебора через паирс в цикле перебора группы....Хотя попробую..Кстати вот, как я сделал, код не очень то и читаем но рабочий !
	local PS_TIME=4
	local PS_DMG_PERC=.25
	local PS_TIMER_ID={}
	local PS_TIMER={}
	local PS_UNIT_BLEED={}

local PS_Opgh_TIMER_FUNC=function()

		local t=GetExpiredTimer()
		local id=GetHandleId(t)

		local fg
		local fg_uid
		local group=PS_TIMER[id].group

		local size=BlzGroupGetSize(group)

		for i=size-1,0,-1 do

			fg=BlzGroupUnitAt(group,i)
			fg_uid=GetHandleId(fg)
	
			if UnitAlive(fg) and not BlzIsUnitInvulnerable(fg) then

				UnitDamageTarget(PS_TIMER[id].caster,fg,PS_UNIT_BLEED[id][fg_uid].damage,false,false,ATTACK_PHYSICAL,DAMAGE_PHYSICAL,nil)

				PS_UNIT_BLEED[id][fg_uid].duration=PS_UNIT_BLEED[id][fg_uid].duration-1

				if PS_UNIT_BLEED[id][fg_uid].duration==0 then
					PS_UNIT_BLEED[id][fg_uid]=nil
					GroupRemoveUnit(group,fg)
				end
			else
				PS_UNIT_BLEED[id][fg_uid]=nil
				GroupRemoveUnit(group,fg)
			end

		end

		if BlzGroupGetSize(group)==0 then
			PauseTimer(t)
		end
	end


	PS_Opgh_FUNC=function(caster,caster_uid,target,target_uid)

		local id
		
		if PS_TIMER_ID[caster_uid]==nil then
		
			local timer=CreateTimer()
			PS_TIMER_ID[caster_uid]={timer=timer,id=GetHandleId(timer)}
			PS_TIMER[PS_TIMER_ID[caster_uid].id]={caster=caster,caster_uid=caster_uid,group=CreateGroup()}
			PS_UNIT_BLEED[PS_TIMER_ID[caster_uid].id]={}
			
		end
		
		PS_UNIT_BLEED[PS_TIMER_ID[caster_uid].id][target_uid]={duration=PS_TIME,damage=GetHeroStr(caster,true)*PS_DMG_PERC}
		GroupAddUnit(PS_TIMER[PS_TIMER_ID[caster_uid].id].group,target)
		
		if BlzGroupGetSize(PS_TIMER[PS_TIMER_ID[caster_uid].id].group)==1  then
			TimerStart(PS_TIMER_ID[caster_uid].timer,1,true,PS_Opgh_TIMER_FUNC)
		end
		
	end
24
Castiel, цикл в цикле это нормально, когда оправдано. И уж намного лучше, чем когда одного юнита дергает по несколько таймеров, если на нем больше одного кровотечения.
А что касается pairs - он определенно дешевле создания-удаления групп и таймеров. Плюс у тебя же не сотни кровотечений от разных кастеров на одной цели будут, на таком кол-ве не особо важно как перебор реализован.
8
prog:
Castiel, цикл в цикле это нормально, когда оправдано. И уж намного лучше, чем когда одного юнита дергает по несколько таймеров, если на нем больше одного кровотечения.
А что касается pairs - он определенно дешевле создания-удаления групп и таймеров. Плюс у тебя же не сотни кровотечений от разных кастеров на одной цели будут, на таком кол-ве не особо важно как перебор реализован.
спасибо бро! )))
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.