[Tutorial] How to prevent damage
#1

Intro

So, lately I have seen many people going about this whole damage prevention thing all wrong which is why I'm writing this little tutorial on how to actually achieve damage prevention to a certain degree. I'll explain the options you have for handling damage in general and I'll make you aware of the differences between all available options so you can decide on your own which method suits your needs the best. Without any further ado, let's get right into it.

And let me make one thing very clear in the beginning: The only way to make a player invulnerable to all damage is to set his health very high. There is no other reliable (natively implemented) way to bypass the OnPlayerDeath event. Additionally, keep in mind that there are death events hardcoded into the game such as when you die in an exploding car or take fall damage while having an unopened parachute.

OnPlayerTakeDamage

Of course, when it comes to damage prevention, this callback falls under people's first association. But does it actually serve the purpose? The answer is no. Using OnPlayerTakeDamage for damage prevention is one of the most common errors people do. There are a couple of things you need to understand about this callback.
  • Returning 0 will NOT prevent any damage at all. The callback will only not be called for other scripts.
  • The callback can't actually prevent damage, even if it looks like that ingame. It actually reverses the damage. Same holds true for OnPlayerGiveDamage.
Let me elaborate a little bit more on the latter. Let's assume a player A with 30.0HP gets hit by another player B using a sniper rifle which does about 41.0 damage. In the case of OnPlayerTakeDamage, player A would die. Why? Because the damage is applied first, resulting in -11.0HP, and immediately after added back to the player's health pool, so back to 30.0. However, adding it back is of no use since the player has already reached a health pool below 0, calling OnPlayerDeath.

In which cases is it useful?
If you want to script a custom weapon damage system, this callback is a good way to go.
BUT: Only if you intend to increase weapon damage! Making a weapon deal less damage than defined in the weapon.dat file will result in the scenario described above.

OnPlayerWeaponShot

Now, with this callback we're getting somewhere since it can really prevent damage, but not all damage. OnPlayerWeaponShot revolves all around bullet data which means that it can only prevent bullet data from being sent. There are, however, weapons that do not send bullet data, e.g. grenades or rocket launchers. These damage types will not be detected by this callback. Something that is also nice to know is that a player doesn't see that he is being hit by bullets while the callback returns 0, so it is really unfitting for a custom damage system.

In which cases is it useful?
If you want to make systems that include damaging not only players, but also vehicles and objects, then this is a semi-safe way to go, as it only covers weapons that send bullet data.

SetPlayerTeam

This is by far the best way to prevent damage since it does not care about any damage types in particular. Setting two players to the same team will prevent all damage between these two entities, both bullet data and explosions caused by the other player. This provides you with a solid foundation for your own damage system and also for a anti health and armor hack. Combined with EnableVehicleFriendlyFire(), this method is the safest way to go.
However, be aware of the fact that self-inflicted damage is not prevented which will result in OnPlayerDeath being called.
Reply
#2

Couldnt you just OnPlayerGiveDamage just set all the weapon values to give 0 damage? lol
Reply
#3

Quote:
Originally Posted by Wolfe
Посмотреть сообщение
Couldnt you just OnPlayerGiveDamage just set all the weapon values to give 0 damage? lol
No, there's no way to do that.
You can only reverse the damage by putting his health back when he's hit, but apart from OnPlayerWeaponShot the callbacks are only called afterwards as mentioned.
Quote:

player A with 30.0HP gets hit by another player B using a sniper rifle which does about 49.0 damage. In the case of OnPlayerTakeDamage, player A would die. Why? Because the damage is applied first, resulting in -19.0HP

Reply
#4

Very well thanks for the clarification, nice tutorial for those who're unsure.
Reply
#5

Quote:
Originally Posted by CalvinC
Посмотреть сообщение
No, there's no way to do that.
You can only reverse the damage by putting his health back when he's hit, but apart from OnPlayerWeaponShot the callbacks are only called afterwards as mentioned.
Basically this:
Код:
public OnPlayerGiveDamage(playerid, damagedid, Float: amount, weaponid, bodypart)
{
        new Float:Health;
	
	GetPlayerHealth(damagedid, Health);
	
	if(playerid != INVALID_PLAYER_ID)
	{
		SetPlayerHealth(damagedid, Health);
	}
    
    return 1;
}
Reply
#6

Quote:
Originally Posted by F1N4L
Посмотреть сообщение
Basically this:
Код:
public OnPlayerGiveDamage(playerid, damagedid, Float: amount, weaponid, bodypart)
{
        new Float:Health;
	
	GetPlayerHealth(damagedid, Health);
	
	if(playerid != INVALID_PLAYER_ID)
	{
		SetPlayerHealth(damagedid, Health);
	}
    
    return 1;
}
That code just reverses the damage, and it doesn't work, look at this example:
Say the player that got hit has 30 HP.
The damage dealt was 40, killing the player.
Then the callback is called with your code which sets his health back to 30, but he's already dead because the callback is called after the damage is already done.
Reply
#7

Quote:
Originally Posted by CalvinC
Посмотреть сообщение
That code just reverses the damage, and it doesn't work, look at this example:
Say the player that got hit has 30 HP.
The damage dealt was 40, killing the player.
Then the callback is called with your code which sets his health back to 30, but he's already dead because the callback is called after the damage is already done.
Time ago I had made an anti-tk system OnPlayerTakeDamage and happened just that! The player received a greater harm than his life and ended up dying.

So I used OnPlayerGiveDamage and it did not happen, the player did not die with a greater harm than life itself!
Of course I used conditional to check the team and still worked.

Verification of the callback seems to be much faster.
Reply
#8

we can use onplayerupdate for this purpose i think
Reply
#9

As already stated by CalcinC, OnPlayerGiveDamage is no different than OnPlayerTakeDamage when it comes to damage prevention. The only difference is that OnPlayerGiveDamage handles damage clientside whereas OnPlayerTakeDamage does it serverside. Generally, I would never recommend letting the client handle damage. As far as I recall, OnPlayerGiveDamage is also called if you shoot someone who is actually out of shot range.

And no, OnPlayerUpdate is the absolute worst way of doing it. Again, it behaves just like the other callbacks. You'd only have to implement an if-clause that checks for incoming damage. The if-clause would be called 30-50 times per second though, so you definitely don't want to be using that.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)