Всем привет! Мой вопрос собственно заключается в том, что правильно ли я сделал, если допустим есть способность кровотечение, которая вызывает кровотечение на юнитах. Суть в том, что допустим 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

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

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

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
8
5 лет назад
0
BleedBitch
BleedBitch хорошее название функции! Типа адресовано мне я так понял!
2
24
5 лет назад
2
Адресовано юниту который будет истекать кровью, я не кидаюсь необоснованными оскорблениями в собеседников.
2
8
5 лет назад
2
prog:
Адресовано юниту который будет истекать кровью, я не кидаюсь необоснованными оскорблениями в собеседников.
Ну вообще то я воспринял это как шутку! Ладно спасибо что подсказал как лучше!+
1
24
5 лет назад
Отредактирован prog
1
Castiel, если что, пример выше это только очень простой пример того как можно записать данные. Его нужно дополнять и расширять для практического использования.
Есть альтернативный способ - вместо записи последовательно, записывать по хендлу кастера и перебирать потом через pairs.
function BleedBitch(caster,target,duration,basedamage)
	-- добавляем новое кровотечение к юниту по хендлу кастера
	local data = bleeding_data[GetHandleId(target)]
	data[GetHandleId(caster)] = {caster=caster, duration=duration, damage=GetHeroStr(caster,true)*basedamage}
	GroupAddUnit(BleedGroup,target)
end

function BleedTickUnit (target)
	local data = bleeding_data[GetHandleId(target)]
	for cid, bdat in pairs(data)
		Damage(bdat.caster, target, bdat.damage)
	end
end
Перебор через pairs медленней перебора по индексам, но и мороки с ним меньше, плюс проверка на то есть ли на цели кровотечение от кастера проще. Но есть нюанс - тогда в перебираемой таблице не должно быть лишних записей, чтобы не париться проверками нужная ли это запись или что-то левое.
0
8
5 лет назад
Отредактирован Castiel
0
prog:
Castiel, если что, пример выше это только очень простой пример того как можно записать данные. Его нужно дополнять и расширять для практического использования.
Есть альтернативный способ - вместо записи последовательно, записывать по хендлу кастера и перебирать потом через pairs.
function BleedBitch(caster,target,duration,basedamage)
	-- добавляем новое кровотечение к юниту по хендлу кастера
	local data = bleeding_data[GetHandleId(target)]
	data[GetHandleId(caster)] = {caster=caster, duration=duration, damage=GetHeroStr(caster,true)*basedamage}
	GroupAddUnit(BleedGroup,target)
end

function BleedTickUnit (target)
	local data = bleeding_data[GetHandleId(target)]
	for cid, bdat in pairs(data)
		Damage(bdat.caster, target, bdat.damage)
	end
end
Перебор через pairs медленней перебора по индексам, но и мороки с ним меньше, плюс проверка на то есть ли на цели кровотечение от кастера проще. Но есть нюанс - тогда в перебираемой таблице не должно быть лишних записей, чтобы не париться проверками нужная ли это запись или что-то левое.
А если добавлять одного и того же юнита в группу ? Не получится ли, что один и тот же юнит в группе несколько раз состоит ? Может стоит сделать проверку ?
2
28
5 лет назад
Отредактирован PT153
2
А если добавлять одного и того же юнита в группу ? Не получится ли, что один и тот же юнит в группе несколько раз состоит ? Может стоит сделать проверку ?
Проверка уже делается внутри. В 1.31 функции добавления и удаления в\из группу\ы возвращают правду, если юнит был действительно добавлен или удалён. Ложь, если не был.
1
24
5 лет назад
Отредактирован prog
1
Castiel, еще раз повторюсь - это не более чем пример. Для практического использования, естественно, нужны дополнительные проверки.

Для группы проверка это не более чем экономия одного вызова нативки т.к. вар не дает два раза добавить одного юнита в группу, а вот проверка на то есть ли уже кровотечение от этого кастера имеет смысл, чтобы модифицировать данные о кровотечении, а не добавлять еще одно.
0
8
5 лет назад
Отредактирован Castiel
0
PT153:
А если добавлять одного и того же юнита в группу ? Не получится ли, что один и тот же юнит в группе несколько раз состоит ? Может стоит сделать проверку ?
Проверка уже делается внутри. В 1.31 функции добавления и удаления в\из группу\ы возвращают правду, если юнит был действительно добавлен или удалён. Ложь, если не был.
Если я правильно понял, то если добавлять одного и того же, то ничего не произойдет более 1 раза ?И проверку на наличие можно не делать ?
2
28
5 лет назад
2
И проверку на наличие можно не делать ?
Не нужно делать, ибо это бессмысленно.
1
28
5 лет назад
1
prog, Castiel, а зачем вам хэндл юнита вообще?
можно просто хранить всех юнитов и данные в массиве и в таймере пробегать циклом по массиву
1
24
5 лет назад
1
nvc123, можно, конечно. Но, например, у себя в картах я обычно храню намного больше информации привязаной к юнитам - если бы каждая система хранила свои данные в массиве, то удаление этих данных превратилось бы в ад, как и доступ к этим данным вне перебора. Вот когда удаление и доступ к данным просходит только внутри одной системы и только внутри перебора, то можно и в массив без хендлов сложить, конечно.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.