SA-MP Forums

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

Reply
 
Thread Tools Display Modes
Old 19/01/2015, 12:17 PM   #1
CalvinC
High-roller
 
CalvinC's Avatar
 
Join Date: Nov 2014
Location: Denmark
Posts: 1,831
Reputation: 114
Default Custom Playerdamage system

When i ******d this, i found no-one having a real tutorial of this, only some vague attempts that doesn't work properly, so i decided to make my first tutorial here about my own script.
Quote:
Table of Contents

Includes
Description
OnPlayerTakeDamage VS OnPlayerGiveDamage
Part 1 - Setting Teams
Part 2 - Get Players Health and Armour
Part 3 - Setting up the Switches
Part 4 - Applying the Custom Damages & Detecting Bodyparts
Includes

You only need the basic a_samp include.

Description

This tutorial will learn you how to create an efficient system that gives custom damages to players, depending where you shoot on their body, and more factors you can choose yourself.

This includes custom armour damage, i saw alot of tutorials that only gave custom damages to health, not armour.

This removes the old damage, so you can make completely new damages. I saw alot of tutorials that only added more damage to the old damage.

To do this, we use either the OnPlayerTakeDamage callback or the OnPlayerGiveDamage callback.
They have some pre-made parameters i will show you:
Code:
public OnPlayerTakeDamage(playerid, issuerid, Float: amount, weaponid, bodypart)
// playerid = The player that got damaged.
// issuerid = The player or thing that gave the damage.
// Float: amount = The amount of damage given.
// weaponid = The weapon ID that dealt the damage, may also be other reasons which can be seen on the wiki.
// bodypart = The bodypart that was hit.

public OnPlayerGiveDamage(playerid, damagedid, Float: amount, weaponid, bodypart)
// playerid = The person that gave the damage.
// damagedid = The player that got damaged.
// Float: amount = The amount of damage given.
// weaponid = The weapon ID that dealt the damage.
// bodypart = The bodypart that was hit.
For the sake of this tutorial we will be using OnPlayerTakeDamage.

OnPlayerTakeDamage VS OnPlayerGiveDamage

OnPlayerTakeDamage is called when a player takes damage on their screen, while OnPlayerGiveDamage is called when an attacker deals damage to another player on the attackers screen.

The upside with OnPlayerTakeDamage is that the damage always looks fair on both clients screens.
Although the aggressor may shoot the player where the callback isn't called because the bullet or punch doesn't hit the victim on their screen.
This also leads to the weird SAMP sync during melee fights where sometimes nobody takes damage when hitting eachother.

OnPlayerGiveDamage gives a much more accurate feel for the attacking player, although the bullets or punches doesn't always hit on the victim's screen the callback will still be called, as long as they hit on the aggressors screen.
This is arguable a way to fix the SAMP sync during melee fights, since the player always deals damage when punching the other player.
The other player doesn't necessarily see it on their screen though, and both players can end up continuously damaging eachother at the same time.

Part 1 - Setting Teams

First off, we need to assign the player to the same teams, which makes them unable to damage eachother, then we can use our own damages instead.
We do this with the SetPlayerTeam function when the player connects.
Code:
public OnPlayerConnect(playerid)
{
    SetPlayerTeam(playerid, 0);
    return 1;
}
Part 2 - Get Players Health and Armour

Before adding weapon damages, we need to get the players health and armour, then store it in 2 different floats, floats are tagged variables you can store different information in, like health, armour, coordinates and such. If you need more info, you can read more about it on the wiki.

So we declare the variables, but we need to declare them as floats, so we put "Float:variablename".
You can name the floats whatever you want, it doesn't matter.

I called them "health" and "armour", so now our OnPlayerTakeDamage callback should look like underneath.
Code:
public OnPlayerTakeDamage(playerid, issuerid, Float:amount, weaponid, bodypart)
{
    new
        Float: health,
        Float: armour
    ; // Declares the variables, and defines them as floats.
    return 1;
}
But we have to store the health and armour of the player in these floats, as of now we just created them.
To store the players health and armour in these floats, use GetPlayerHealth(playerid, Float:variablename) and GetPlayerArmour(playerid, Float:variablename)

Code:
public OnPlayerTakeDamage(playerid, issuerid, Float:amount, weaponid, bodypart)
{
    new
        Float: health,
        Float:armour
    ; // Declares the variables, and defines them as floats.
    GetPlayerHealth(playerid, health); // Gets the health of the player that took damage, and stores it in the float "health".
    GetPlayerArmour(playerid, armour); // Gets the armour of the player that took damage, and stores it in the float "armour".
    return 1;
}
Now we have the players health and armour, which we will need later.

Part 3 - Setting up the Switches

Now we need the weapon ID that the "issuer" attacked the player with.
Quite handy, it's already declared in the variable as "weaponid".

So to set up different damages for each weapon, we use a switch to detect which system to use.
I see alot of people using this method:
Code:
if(weaponid == 24) // If the weapon is an Desert Eagle (id 24)
{
    // Codes
}
else if(weaponid == 31) // If the weapon is an M4 (id 31)
{
    // Codes
}
else if(weaponid == 34) // If the weapon is an Sniper (id 34)
{
    // Codes
}
You can do this, but this method is very inefficient and slow.
It is both easier, more efficient, and faster to use switches, as the wiki also states, this counts for everything where you would use an "else" or "else if", if it's possible, use a switch instead.
To create a switch, we set it up like this:
Code:
public OnPlayerTakeDamage(playerid, issuerid, Float: amount, weaponid, bodypart)
{
    new
        Float: health,
        Float:armour
    ; // Declares the variables, and defines them as floats.
    GetPlayerHealth(playerid, health); // Gets the health of the player that took damage, and stores it in the float "health".
    GetPlayerArmour(playerid, armour); // Gets the armour of the player that took damage, and stores it in the float "armour".

    switch(weaponid) // Starts the switch, and switches through the variable "weaponid". (declared in callback)
    {
        case 24: // If the variable is set to 24 (Desert Eagle weaponid), it activates the codes below.
        {
            // Codes
        }
        case 31: // If the variable is set to 31 (M4 weaponid), it activates the codes below.
        {
            // Codes
        }
        case 34: // If the variable is set to 34 (Sniper weaponid), it activates the codes below.
        {
            // Codes
        }
    }
    return 1;
}
NOTE: All weapon ID's can be found here.

So now we'll work with the Desert Eagle weapon. And i already showed you how to set up a switch to detect it. (And other weapons.)
If you want more weapons, just put more "Case id:", and replace "id" with the weaponid ofcourse.

But now we need to check if the player has armour, or if he doesn't, and then deal damage to his armour, or health.
We use a switch again, to check if his armour is 0, then we deal damage to his health. And we use "default" which replaces the "else", so if his armour isn't 0, it will activate the "default" code.
We create the switch inside the case 24: (Desert Eagle weapon), like this:
Code:
case 24: // Desert Eagle weapon ID
{
    switch(armour) // Creates a switch that switches through the armour float, and checks the value.
    {
        case 0: // If the value is 0, the codes underneath will activate.
        {
            // Codes
        }
        default: // Otherwise the codes underneath will activate.
        {
            // Codes
        }
    }
}
Those are the basic switches done, in part 4 i explain how to give damage according to which bodypart was hit.

Part 4 - Applying the Custom Damages & Detecting Bodyparts

Now we need to get the bodyparts, and deal damage accordingly to which bodypart was hit.
Quote:
Originally Posted by SA-MP Wiki

Important
Note
These IDs are not 100% confirmed, and are not defined in any SA-MP includes - they must be defined by the scripter. It is unknown if IDs 0, 1 and 2 have any use.
So therefore we need to define the bodyparts ourselves, by putting this at the top of our script.
Code:
#define BODY_PART_TORSO 3
#define BODY_PART_GROIN 4
#define BODY_PART_LEFT_ARM 5
#define BODY_PART_RIGHT_ARM 6
#define BODY_PART_LEFT_LEG 7
#define BODY_PART_RIGHT_LEG 8
#define BODY_PART_HEAD 9
There's no body part 0, 1 or 2 as of now.
So the case 0 is called when the player doesn't have armour, therefore we deal damage to the players health, according to which bodypart was hit.
So we create a switch, that switches through the value of "bodypart", which is created in the callback, and we defined.
Code:
switch(bodypart) // Under case 0.
{
    case 3: SetPlayerHealth(playerid, health - 30); // Torso.
    case 4: SetPlayerHealth(playerid, health - 20); // Groin.
    case 5: SetPlayerHealth(playerid, health - 5);  // Left Arm.
    case 6: SetPlayerHealth(playerid, health - 10); // Right Arm.
    case 7: SetPlayerHealth(playerid, health - 7);  // Left Leg.
    case 8: SetPlayerHealth(playerid, health - 12); // Right Leg.
    case 9: SetPlayerHealth(playerid, health - 50); // Head.
}
These values obviously aren't realistic, but i can use them to describe, so this will check if the case is etc. 4, (BODY_PART_GROIN) and SetPlayerHealth to his current health, minussed with 20.
It will do accordingly with the other cases, such as 9, (BODY_PART_HEAD) it will set his health to his current health, minussed with 50.
Ofc. you can change the damages it will minus the health with.
And then you do the same under "default", just change SetPlayerHealth to SetPlayerArmour, and health - (value) to armour - (value).



And you're done!
By now you should hopefully have a fully working custom damage system for your servers, if you have any questions, feel free to ask about it below.
__________________
[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.

Last edited by CalvinC; 29/04/2016 at 02:51 PM. Reason: Updated - More accurate, more info
CalvinC is offline   Reply With Quote
Old 19/01/2015, 01:24 PM   #2
Rudy_
High-roller
 
Rudy_'s Avatar
 
Join Date: Nov 2011
Location: Pakistan
Posts: 1,355
Reputation: 230
Default Re: Custom Playerdamage system

Not bad, Good job.
__________________
And now my Watch has Ended.


[Tutorial]
[TuT]How to create a car shooting Neon

[Filterscript]
Neon Vehicle Laser


__________________________________________________
Rudy_ is offline   Reply With Quote
Old 19/01/2015, 01:29 PM   #3
nezo2001
Gangsta
 
Join Date: Nov 2014
Location: Cairo, Egypt
Posts: 680
Reputation: 26
Default Re: Custom Playerdamage system

Simple, easy good job
__________________
Quote:
Originally Posted by Human
When im met u, u were nub at scripting xD.

But now, i'm impressed. Good job.
Don't look at my history. Everyone started somewhere
nezo2001 is offline   Reply With Quote
Old 20/01/2015, 05:06 AM   #4
PaulDinam
Gangsta
 
Join Date: Jun 2011
Posts: 887
Reputation: 45
Default Re: Custom Playerdamage system

Good job on the effort.
PaulDinam is offline   Reply With Quote
Old 22/01/2015, 08:47 AM   #5
CalvinC
High-roller
 
CalvinC's Avatar
 
Join Date: Nov 2014
Location: Denmark
Posts: 1,831
Reputation: 114
Default Re: Custom Playerdamage system

Thanks guys! Took a long time to make this.
__________________
[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 11/02/2015, 02:20 PM   #6
JaydenJason
Gangsta
 
JaydenJason's Avatar
 
Join Date: Oct 2014
Location: Netherlands
Posts: 684
Reputation: 51
Default Re: Custom Playerdamage system

Amazing tutorial you got here.

Just a quick question, lets say I want the player who got shot in the leg unable to run, how do I stop them from sprinting?
JaydenJason is offline   Reply With Quote
Old 11/02/2015, 02:26 PM   #7
Lordzy
High-roller
 
Lordzy's Avatar
 
Join Date: Mar 2012
Location: NetherRealm
Posts: 2,702
Reputation: 1176
Default Re: Custom Playerdamage system

Quote:
Originally Posted by JaydenJason View Post
Amazing tutorial you got here.

Just a quick question, lets say I want the player who got shot in the leg unable to run, how do I stop them from sprinting?
Check for running animation or detect keys while they're on foot. So in case if the player has got a shot on leg, you can detect and avoid it by setting some other animation like using walk or fall.
__________________
Currently inactive - I don't play at any SA-MP servers nor work on anything in PAWN for now. The projects that I've done so far in PAWN, which requires updates will be taking some time.
Lordzy is offline   Reply With Quote
Old 12/02/2015, 07:29 PM   #8
CalvinC
High-roller
 
CalvinC's Avatar
 
Join Date: Nov 2014
Location: Denmark
Posts: 1,831
Reputation: 114
Default Re: Custom Playerdamage system

Quote:
Originally Posted by JaydenJason View Post
Amazing tutorial you got here.

Just a quick question, lets say I want the player who got shot in the leg unable to run, how do I stop them from sprinting?
Thanks Jayden.

For the leg function, start off by creating a variable called etc. "Injured[MAX_PLAYERS]".
Then under OnPlayerTakeDamage, check if the bodypart hit was one of his legs, if so, set the variable to 1.
pawn Code:
Injured[playerid] = 1; // Sets the players variable to 1.

For the holding/releasing key-codes just use these 2 defines to make it less confusing
pawn Code:
#define HOLDING(%0) \
        ((newkeys & (%0)) == (%0))

#define RELEASED(%0) \
        (((newkeys & (%0)) != (%0)) && ((oldkeys & (%0)) == (%0)))

Then under OnPlayerKeyStateChange, check if he's holding a direction key (WASD by default) and the sprint key at the same time.
pawn Code:
if(HOLDING(KEY_UP) || HOLDING(KEY_LEFT) || HOLDING(KEY_RIGHT) || HOLDING(KEY_DOWN) && HOLDING(KEY_SPRINT))

Then check if that Injured variable is set to 1, and that he's not in a vehicle, if so, set his animation to a running animation.
pawn Code:
if(Injured[playerid] = 1 && !IsPlayerInAnyVehicle(playerid)) ApplyAnimation(...);

Then finally, stop the running animation when he releases KEY_SPRINT.
pawn Code:
if(RELEASED(KEY_SPRINT)) ApplyAnimation(playerid, "CARRY", "crry_prtial", 4.0, 0, 0, 0, 0, 0);
That animation cancels other animations, but not his running/speed i don't think.
You could also use "ClearAnimations(playerid);", but that would ruin his running speed.
__________________
[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 17/02/2015, 04:18 PM   #9
JaydenJason
Gangsta
 
JaydenJason's Avatar
 
Join Date: Oct 2014
Location: Netherlands
Posts: 684
Reputation: 51
Default Re: Custom Playerdamage system

Much appreciated Calvin, thanks for the tut on the running thingy!
JaydenJason is offline   Reply With Quote
Old 17/02/2015, 04:51 PM   #10
ZombieNest
Huge Clucker
 
ZombieNest's Avatar
 
Join Date: Oct 2013
Location: Neverland
Posts: 261
Reputation: 40
Default Re: Custom Playerdamage system

FK FK FK

FFS WRONG THREAD,
I'm addicted to it
__________________
?((._. uwotmate? ._.))؟

Quote:
Originally Posted by SA-MP Forums Bot View Post
So--
Quote:
Originally Posted by ZombieNest View Post
Pro.
Quote:
Originally Posted by :o View Post
Quote:
Originally Posted by vBulletin Error View Post
vBulletin Message
No Thread specified. If you followed a valid link, please notify the administrator.
Is that a excuse?
Yeah, maybe
ZombieNest 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
[GameMode] ---Basic Deathmatch Script - Custom classes - Score System - Full Admin System - [0.3z]--- Irektyou11 Gamemode Scripts 14 02/01/2015 11:14 PM
[FilterScript] Radio System Custom San1 Filterscripts 5 03/01/2013 04:27 AM
Playerdamage? Chrillzen Scripting Help 3 10/02/2012 08:52 PM
XML custom menu system. aralmo Filterscripts 6 27/06/2009 08:35 AM


All times are GMT. The time now is 04:32 PM.


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