SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help > Tutorials

Reply
 
Thread Tools Display Modes
Old 04/05/2016, 10:47 AM   #1
Manyula
Huge Clucker
 
Join Date: Jan 2012
Location: Germany
Posts: 282
Reputation: 43
Default How to prevent damage

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.
__________________

Last edited by Manyula; 02/02/2017 at 02:39 PM.
Manyula is offline   Reply With Quote
Old 04/05/2016, 11:54 AM   #2
Wolfe
Big Clucker
 
Join Date: Feb 2015
Posts: 163
Reputation: 55
Default Re: How to prevent damage

Couldnt you just OnPlayerGiveDamage just set all the weapon values to give 0 damage? lol
Wolfe is offline   Reply With Quote
Old 04/05/2016, 12:14 PM   #3
CalvinC
High-roller
 
CalvinC's Avatar
 
Join Date: Nov 2014
Location: Denmark
Posts: 1,852
Reputation: 114
Default Re: How to prevent damage

Quote:
Originally Posted by Wolfe View Post
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
__________________
[Tutorial] Custom Playerdamage system
Desert Eagle's dealing too much damage, you want one-hit sniper kills, or damage based on body parts? Check this out.
CalvinC is offline   Reply With Quote
Old 04/05/2016, 12:17 PM   #4
Wolfe
Big Clucker
 
Join Date: Feb 2015
Posts: 163
Reputation: 55
Default Re: How to prevent damage

Very well thanks for the clarification, nice tutorial for those who're unsure.
Wolfe is offline   Reply With Quote
Old 04/05/2016, 12:25 PM   #5
F1N4L
High-roller
 
F1N4L's Avatar
 
Join Date: Jun 2013
Location: Brazil
Posts: 2,705
Reputation: 246
Default Re: How to prevent damage

Quote:
Originally Posted by CalvinC View Post
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:
Code:
public OnPlayerGiveDamage(playerid, damagedid, Float: amount, weaponid, bodypart)
{
        new Float:Health;
	
	GetPlayerHealth(damagedid, Health);
	
	if(playerid != INVALID_PLAYER_ID)
	{
		SetPlayerHealth(damagedid, Health);
	}
    
    return 1;
}
F1N4L is offline   Reply With Quote
Old 04/05/2016, 12:33 PM   #6
CalvinC
High-roller
 
CalvinC's Avatar
 
Join Date: Nov 2014
Location: Denmark
Posts: 1,852
Reputation: 114
Default Re: How to prevent damage

Quote:
Originally Posted by F1N4L View Post
Basically this:
Code:
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.
__________________
[Tutorial] Custom Playerdamage system
Desert Eagle's dealing too much damage, you want one-hit sniper kills, or damage based on body parts? Check this out.
CalvinC is offline   Reply With Quote
Old 04/05/2016, 12:45 PM   #7
F1N4L
High-roller
 
F1N4L's Avatar
 
Join Date: Jun 2013
Location: Brazil
Posts: 2,705
Reputation: 246
Default Re: How to prevent damage

Quote:
Originally Posted by CalvinC View Post
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.
F1N4L is offline   Reply With Quote
Old 04/05/2016, 02:45 PM   #8
SyS
High-roller
 
SyS's Avatar
 
Join Date: Oct 2015
Posts: 2,003
Reputation: 473
Default Re: How to prevent damage

we can use onplayerupdate for this purpose i think
SyS is offline   Reply With Quote
Old 04/05/2016, 04:19 PM   #9
Manyula
Huge Clucker
 
Join Date: Jan 2012
Location: Germany
Posts: 282
Reputation: 43
Default Re: How to prevent damage

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.
__________________
Manyula is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[FilterScript] Easy custom damage + damage sound Voxel Filterscripts 14 30/09/2013 04:07 PM
How to detect vehicle damage, and get damage taken? Micius Scripting Help 4 31/07/2013 04:08 PM
How to prevent? Fernado Samuel Scripting Help 2 27/03/2013 08:03 AM
[Include] Car damage system - Damage a car without a driver! The_Moddler Includes 68 30/03/2012 01:38 AM
[Help]Player damage when vehicle damage jujuv Help Archive 6 28/12/2010 12:25 AM


All times are GMT. The time now is 03:43 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.