TakeDamage - GiveDamage

[RU-original] Имеется функция по корректному нанесению повреждений гуманоиду - Humanoid:TakeDamage, которая обычно вызывается из Touched. И так же, обычно, используется “creator” для идентификации источника нанесения повреждения.

Но я так и не смог найти обратную функцию/событие, через которую можно было бы понять - нужно ли данному гуманоиду принять на себя посланные повреждения до того, как будет изменено значение его здоровья и сработает Humanoid:HealthChanged?

Humanoid:TakeDamage - нанести повреждения
Humanoid:GiveDamage - получить повреждения

Соответственно с получаемыми параметрами (сколько, кто/что) нанесло повреждения?

Или есть вариант, как это организовать, имея в качестве источников повреждений массу игроков и множество объектов принадлежащим к разным категориям? Т.е. нужно как-то отфильтровать на этапе получения повреждения от TakeDamage в каком размере и от кого дойдут до гуманоида эти повреждения.

[EN-google] There is a function for correctly damaging a humanoid - Humanoid: TakeDamage, which is usually called from Touched. And also, usually, creator is used to identify the source of damage.

But I could not find the inverse function / event through which I could understand - does this humanoid need to take the damage done before its health value changes and Humanoid: HealthChanged works?

Humanoid: TakeDamage - deal damage
Humanoid: GiveDamage - Get Damaged

Accordingly, with the received parameters (how much, who / what) did the damage?

Or is there an option how to organize this, having as a source of damage a lot of players and many objects belonging to different categories? Those. somehow it is necessary to filter out at the stage of taking damage from TakeDamage in what size and from whom these damage will reach the humanoid.

1 Like

Roblox does not provide built-in functionality to track which player / which objects damages a Humanoid. The TakeDamage() method is used exclusively to damage the Humanoid with the provided damage, which then reduces the Humanoid.Health property with the given amount.

If you are looking for any logic that will store who/what damaged the Humanoid, that is something you’d need to write yourself. There is no ‘inverse function’ for TakeDamage

8 Likes

In extension to @Wsly’s post:

A good strategy to finding who or what damaged the player would be adding an ObjectValue to a Humanoid when they join the game or activate an event, etc. When they are damaged, you could set what damaged them as the ObjectValue.Value. This is just an example to get you on the right track.

The reason you would use an ObjectValue would be so you can reroute the function to track players, and weapons, etc. Of course, this is entirely up to you on how you wish to write your script.

2 Likes

[Ru]Именно, нет обратной функции.

Как следствие надо писать собственные функции по нанесению урона и кучу проверок о поиске того, кто нанёс урон гуманоиду, применять ли этот урон, пересчитать ли его размер или просто игнорировать.

Яркий пример - сила повреждения превышает здоровье гуманоида. В итоге гуманоид становится мёртвым. Всё, тут ему уже не восстановить здоровье до предыдущего уровня, если нужно источник урона игнорировать.

Здоровье=30, Повреждение=100 = Итог - мёртв.
HealthChanged - становится бесполезной вещью. Потому что откат изменения не возможен.

Поэтому и хочется событие, которое будет срабатывать до того, как будет применён урон от TakeDamage().

[En-google] Namely, there is no inverse function.

As a result, you need to write your own functions for dealing damage and a bunch of checks about finding whoever damaged the humanoid, whether to apply this damage, whether to recalculate its size, or simply ignore it.

A striking example is the damage force exceeds the humanoid’s health. As a result, the humanoid becomes dead. That’s it, he can no longer restore health to the previous level, if you need to ignore the source of damage.

Health = 30, Damage = 100 = The result is dead.
HealthChanged - becomes a useless thing. Because rollback changes are not possible.

Therefore, I want an event that will fire before the damage from TakeDamage () is applied.

1 Like

I’m not entirely use if this is what you want to do, but

Try using this :

 humanoid.HealthChanged:Connect(function(health)
 local newHealth = health
         if newHealth <= N -- a set value

that event fires every time the Humanoid’s Health changes

Using Humanoid:TakeDamage() only a specific value is decreased from the Humanoid’s Health, there is no way to detect when this happens, other than using the HealthChanged Event AFAIK.

1 Like

[RU]Вот пример.
Размер повреждения расчитывается исходя из экипировки, уровня и прокачки персонажа.
Скажем: 40 от оружия, 30 от уровня персонажа, 40 от одежды, 20 от применения навыка. Итого: 130 урона.
Т.е. я отправляю - TakeDamage(130)

При получении урона, я должен расчитать какое у меня ему сопротивление - опять же от уровня 20, экипировки 50, текущей стойки 40. Итого - 110.

Результирующий урон который получит персонаж равен 130-110=20. Но для меня, в текущем варианте, это бесполезно. Так как персонаж умрёт сразу как только выполнится TakeDamage(130).

[EN-google] Here is an example.
The amount of damage is calculated based on the equipment, level and leveling of the character.
Say: 40 from a weapon, 30 from a character level, 40 from clothes, 20 from applying a skill. Total: 130 damage.
Those. I submit - TakeDamage (130)

When taking damage, I must calculate what resistance I have to him - again from level 20, equipment 50, current rack 40. Total - 110.

The resulting damage that the character takes is 130-110 = 20. But for me, in the current version, it is useless. Since the character will die as soon as TakeDamage (130) is executed.

1 Like

Then why don’t you also calculate the resistance before damaging? (That’s what you should do anyways).
What I mean is after you do all the damage calculations, you check who’s the player you’re damaging and then check how much resistance the player has to you and apply damage accordingly.

Рисунок будет наглядней.
The picture will be more visual.

[RU] Много букв далее.
Потому что это может быть (для примера):

  • игрок
  • NPC
  • постройка
  • оружие игрока,
  • оружие NPC
  • запущенный игроком снаряд,
  • запущенный NPC снаряд,
  • запущенный постройкой снаряд,
  • воздействие среды окружения

Имеется ввиду воздействие не только на игрока, но и на NPC и окружающий мир (постройки).

По факту, это может быть воздействие постоянное (одетое снаряжение), переменное (влияние окружающей среды), временное (полученный от чего либо урон).

То есть источник урона - Part, Model, Tool, Function

То есть реализация всего задуманного сейчас приводит к тому, что использовать функцию TakeDamage() сейчас просто не возможно.
Либо в каждый объект имеющий функцию нанесения урона необходимо встраивать множество проверок на касание проверяя с чем именно мы соприкоснулись, какие у него имеются сопротивления к наносимому урону и только после этого уже сам объект касания будет применять на себя результирующий урон.

[EN-google]Many letters further.
Because it could be (for example):

  • player
  • NPC
  • building
  • player’s weapon
  • NPC weapons
  • a projectile launched by a player,
  • launched NPC projectile,
  • a projectile launched by the construction,
  • environmental impact

This means the impact not only on the player, but also on the NPC and the surrounding world (buildings).

In fact, this can be a constant effect (dressed equipment), variable (environmental impact), temporary (damage taken from something).

That is, the source of damage - Part, Model, Tool, Function

That is, the implementation of everything conceived now leads to the fact that it is simply not possible to use the TakeDamage () function now.
Or, in every object that has the function of causing damage, it is necessary to embed a lot of touch checks to check what exactly we touched with, what resistance it has to the damage done, and only after that the touch object itself will apply the resulting damage.

I don’t exactly know the order of HealthChanged in relation to when damage is actually dealt, but I know that what you’re trying to do should still work. Here’s an example:

I made a part that hurts the player when the player sets on it. It also creates a HealthChanged connection that will try to keep the player alive. It works fine.

https://streamable.com/41x1tw#

Here is the code inside the part:

local part = script.Parent

local alreadyConnected = {}
local debounce = {}

function hurtPlayer(partTouched)
	local character = partTouched.Parent
	local hum = character:FindFirstChild("Humanoid")
	
	if not hum then return end
	if debounce[hum] then return end

	debounce[hum] = true
	preventDeath(hum)
	
	local damage = 35
	hum:TakeDamage(damage)
	print("Tried to hurt "..hum.Parent.Name.." by "..damage)
	
	spawn(function()
		wait(3)
		debounce[hum] = false
	end)
end


function preventDeath(hum)
	if alreadyConnected[hum] then return end
	hum.HealthChanged:Connect(function(newHealth)
		if newHealth <= 0 then 
			hum.Health = 1
			print(hum.Parent.Name .. " saved from death!")
		end
	end)
	alreadyConnected[hum] = true
end

part.Touched:Connect(hurtPlayer)

Is this not what you’re trying to achieve?

Quote from the documentation:

When Humanoid.Health reaches zero, the Humanoid will die and the Humanoid.Died event will fire. This event will fire with a value of zero.

That is, Humanoid.Died will work as soon as we get a health of less than 1.

That is, in your case, the Humanoid.Died() event will occur for players.
P.S. But to be honest, I considered a similar option …

You could create a NumberValue that reflects your current health
then run your code that checks if health < 0

Yes. I have seen that.
But here the same problem - it works after the fact.

For the sake of interest, I threw a piece of your script on an empty project with minimal revision.
As you can see, the minimum delay in the HealthChange event and the character is dead.

wait(5)
print("Start")
hum = game.Workspace.GAVsi115.Humanoid

hum.HealthChanged:Connect(function(newHealth)
	if newHealth <= 0 then
		wait() -- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		hum.Health = 1
		print(hum.Parent.Name .. " saved from death!")
	end
end)

hum.Died:Connect(function()
	print("!!!!!!!!! Die !!!!!!!!!!!")
end)

while true do
	hum:TakeDamage(11)
	print("Health=",hum.Health)
	wait(0.3)
end

image

So your goal is to save players from being killed by preventing their health depleting.

TakeDamage() exists to deal the given amount of damage to the Humanoid. The method rightfully assumes that you want to decrease the health with the given amount, and will therefore kill the Humanoid when depleted.

The correct way to go about implementing this mechanic is to write your own (Module)Script to layer on top of TakeDamage() that all your damage-inflicting game items connect to. This script layer would calculate the health needed to kill the player and, if the provided number of damage will kill the player AND the player has a ‘Second chance’ to save them from death, it would actually heal them to their ‘Second chance’ health instead of killing.

function GiveDamage(Humanoid,NumDamage,BoolHasSecondChance)
	if Humanoid ~= nil and Humanoid.Health > 0 and NumDamage ~= nil and type(NumDamage) == "number" then
		if Humanoid.Health - NumDamage <= 0 then
			--> This damage would kill the Humanoid
			if BoolHasSecondChance then
				print(Humanoid.Parent.Name.." saved from death!")
				Humanoid.Health = 100
			else
				Humanoid:TakeDamage(NumDamage)
				print(Humanoid.Parent.Name.." was killed - new health is "..Humanoid.Health)
			end
		else
			--> Not enough to kill the Humanoid, apply the damage
			Humanoid:TakeDamage(NumDamage)
			print(Humanoid.Parent.Name.." was damaged - new health is "..Humanoid.Health)
		end
	end
end

Instead of providing BoolHasSecondChance as a method variable, you would probably want to connect to your Item system to see if the players owns an item that would save them from death.

4 Likes

[RU] На текущее время, я именно этим и занимаюсь. Пытаюсь заменить стандартную функцию TakeDamage на собственную с добавлением GiveDamage.

Но пока что споткнулся на проблеме, как именно заменить базовую функцию TakeDamage на собственную так, чтобы вызов из любого, стороннего, предмета/оружия переходил на мою функцию, а не на встроенную?

[EN-google] At the current time, I’m doing just that. I’m trying to replace the standard TakeDamage function with my own with the addition of GiveDamage.

But so far I’ve stumbled upon a problem, how exactly can I replace the basic TakeDamage function with my own so that the call from any third-party item / weapon goes to my function, and not to the built-in?

Simply call your function instead of TakeDamage() from any third-party item or weapon. You will need to adjust these items to use your method.

:frowning_face:
Именно такое сейчас решение.
Это как ходить на костылях, когда ноги не сломаны.

This is exactly the solution now.
It’s like walking on crutches when your legs are not broken.

Guided by your idea about the module, I sketched it in haste:
-------------------------- ModuleScript “Damage” --------------------------

local Damage = {}

function Damage:Take(hum,damage)
	damage=damage*1.5	-- All Attack
	print("Humanoid:",hum.Parent.Name," Take:",damage)	
	Damage:Give(hum,damage)
end

function Damage:Give(hum,damage)
	damage=damage/2		-- All Block
	print("Humanoid:",hum.Parent.Name," Give:",damage)
	hum:TakeDamage(damage)
end

return Damage

--------------------------------------- Script ---------------------------------------

local Damage=require(script.Parent.Damage)

wait(5)
print("Start")
hum = game.Workspace.GAVsi115.Humanoid

hum.HealthChanged:Connect(function(newHealth)
	if newHealth <= 0 then
		wait() -- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		hum.Health = 1
		print(hum.Parent.Name .. " saved from death!") -- not interested for me
	end
end)

hum.Died:Connect(function()
	print("!!!!!!!!! Die !!!!!!!!!!!")
end)

while true do
	wait(0.3)
	-- hum:TakeDamage(11)
	Damage:Take(hum,11)
	print("Health=",hum.Health)
end

Maybe someone will come in handy such a crutch…

Of course, this is just an example of how it might look.
For example, in Take, it can take from hum variables with elemental damage / resistance or process purchased bonuses to them. I hope my idea is clear.

I repeat once again: this topic was instituted so that there was a tool and it was not necessary to create separate modules and do many other body movements using the basic functionality.