[Tutorial] HeadShot System [Explained]
#1

Tutorial - HeadShot System


Intro
Nothing special, just a small tutorial explaining about how to make a "HeadShot" system, i do not claim this as effort, since its pretty easy & quick... But since i could not find any decent tutorial i thought... lets do dis.


Content

  • Explaining OnPlayerTakeDamage, since we're going to need it.
  • HeadShot system mini-script.
  • Team Protection (cant hit same team).
  • Enable/Disable HeadShot system.
  • Anti-HeadShot spam(looks weired?)



Let's Get Started

For this tutorial we're going to base on callback OnPlayerTakeDamage.

Description according to wiki page:
Quote:

This callback is called when a player takes damage.

That one explains pretty much everything... but lets look at it deeply with its parameters:
PHP код:
public OnPlayerTakeDamage(playerid, issuerid, Float:amount, weaponid, bodypart) 
  • playerid - player who took damage.
  • issuerid - Player who gave damage(The Shooter), can be INVALID_PLAYER_ID if the damage was caused by self.
  • Float:amount - Amount in Float, of much damage did player took (not needed in our case actually, but you could use it for other things... such as labels on head "Damage -amount")
  • weaponid - ID of the weapon that was used while giving damage.
  • bodypart - The bodypart where player got hit (0.3z+)



Code
We will need a global variable called "HeadShotSystem", so lets define it, anywhere outside a callback/function (near includes?)

PHP код:
boolean, server variable not player variable
new bool:HeadShotSystem; 
Main Code

PHP код:
public OnPlayerTakeDamage(playerid, issuerid, Float:amount, weaponid, bodypart)
{    
    
// check if there was a shooter, weaponID was 34(Sniper) and bodypart was 9(Head)
    
if(issuerid != INVALID_PLAYER_ID && weaponid == 34 && bodypart == 9)
    {
        
//checking if headshot system is ON.
        
if(HeadShotSystem == true)
        {
            
// checks if both players have same team, except NO_TEAM. if not procced, otherwise send error message
//*A edit by our genius friend sickattack
            
if(GetPlayerTeam(issuerid) | GetPlayerTeam(playerid) == NO_TEAM || GetPlayerTeam(issuerid) != GetPlayerTeam(playerid)) 
            {    
//check if player is dead... if not proceed(by Gammix)
                
if (GetPlayerState(playerid) != PLAYER_STATE_WASTED)
                {
                    
//variables, first one to format the message, second and third contain player names.
                    
new headmsg[128], dead[24], killer[24];
                    
//on player's screen we show him a message for 3 seconds "HeadShot"
                    
GameTextForPlayer(playerid, "~r~Head Shot",3000,4);
                    
// same to issuer's screen
                    
GameTextForPlayer(issuerid, "~r~Head Shot!",3000,4);
                    
// we get the victims name with this function and store it into our previously made variable "dead";
                    
GetPlayerName(playerid, dead, sizeof(dead));
                    
// we get the victims name with this function and store it into our previously made variable "killer";
                    
GetPlayerName(issuerid, killer, sizeof(killer));
                    
//format the message, means we put that text into "headmsg".
                    
format(headmsg, sizeof(headmsg), "{FFDC2E}%s (%i) Has Been Killed in a Headshot by %s (%i)!",dead, playerid, killer,issuerid);
                    
// once we've formatted the message we're ready to send the message to all players!
                    
SendClientMessageToAll(0xAA3333AA, headmsg);
                    
//kill the player
                    
SetPlayerHealth(playerid, 0.0);
                    
//and tell the server that he's dead!
                
}
            }
        }
        else
            
SendClientMessage(issuerid, -1, "That player is in your team!");        
    }
    return 
1;
} 
Command to enable/disable headshot system

*Optimized by Sreyas
PHP код:
COMMAND:seths(playerid, params[]) 
{ 
        
//replace with your admin system 
        
if(IsPlayerAdmin(playerid)) 
        { 
            
HeadShotSystem = !HeadShotSystem; 
            new 
string11[109], pname[24]; 
            
GetPlayerName(playerid, pname, 24); 
            
format(string11, sizeof(string11), "[Admin] Server admin %s(%d) has %s Headshot system!", pname,playerid,(HeadShotSystem)?("enabled"):("disabled")); 
            
SendClientMessageToAll(-1, string11); 
        } 
        return 
1; 
} 



Requirements:
- SA:MP version 0.3z +(bodypart)
- sscanf (for the cmd we've used)
- A IDE


Credits:
- SA:MP Team.
- ****** for sscanf



Did i miss something, lemme know with a post, and remember! this is a shit tutorial!
Reply
#2

PHP код:
stock IsPlayerDead(playerid)
{
    new 
Float: health = 0.0;
    
GetPlayerHealth(playerid, health);
    if(
GetPlayerState(playerid) == PLAYER_STATE_WASTED && health <= 0.0) 
        return 
true;
    return 
false;
} 
You don't need "playerDead" variable.



The right way for checking teams aren't equal:
PHP код:
if(GetPlayerTeam(issuerid) == NO_TEAM || GetPlayerTeam(playerid) == NO_TEAM || GetPlayerTeam(issuerid) != GetPlayerTeam(playerid)) 
Reply
#3

OPDeath callback...
Reply
#4

Edited with those changes, thanks.
Reply
#5

Good Tutoiral
Reply
#6

Nice tutorial, though I'm a bit confused with this line (Just the first two checks):
PHP код:
if(GetPlayerTeam(issuerid) == NO_TEAM || GetPlayerTeam(playerid) == NO_TEAM 
Can you elaborate this ?

And is NO_TEAM already defined by pawn its self?

Excuse me, but haven't worked with this before, hence the question.
Reply
#7

NO_TEAM is pre-defined by the main SA-MP include. The value of NO_TEAM is 255. There is a large difference between Pawn and SA-MP Pawn.
Reply
#8

Quote:
Originally Posted by saffierr
Посмотреть сообщение
Nice tutorial, though I'm a bit confused with this line (Just the first two checks):
PHP код:
if(GetPlayerTeam(issuerid) == NO_TEAM || GetPlayerTeam(playerid) == NO_TEAM 
Can you elaborate this ?

And is NO_TEAM already defined by pawn its self?

Excuse me, but haven't worked with this before, hence the question.
PHP код:
if(GetPlayerTeam(issuerid) == NO_TEAM || GetPlayerTeam(playerid) == NO_TEAM || GetPlayerTeam(issuerid) != GetPlayerTeam(playerid)) 
It basically means, if both players have no team, then they can kill each other (typically freeroam / dm servers), OR if both players' teams are different (eg: playerid team: 3, issuerid team:2), then proceed, otherwise nope.

And yes, NO_TEAM is pre-defined just like MAX_PLAYERS.
Reply
#9

Ah, alright I see, thanks both of you.

Keep up the good work, iLearn!

Edit: Wouldn't it be better to have the 'HeadShotSystem check' before the check above?
Reply
#10

nice work iLearner :{}
Reply
#11

Good Job !! +Rep
And i will use that for my next server
Reply
#12

Actually you can directly do this instead of a function "IsPlayerDead(playerid)":
PHP Code:
if (GetPlayerState(playerid) != PLAYER_STATE_WASTED) 
The difference is when you check if health is less than 0.0 then the player is actually in death window, but if you just check if player state is PLAYER_STATE_WASTED, then the player can be in Death state or Class selection. So ya your headshot shouldn't work in class selection so just state check is enough.
Reply
#13

Make up your mind and lemme know, Gammix.
Reply
#14

"Stock by Gammix"

It's not a stock, it's a function.

-----

"if (HeadShotSystem == true)"

You could just do "if(HeadShotSystem)" instead.

P.S. "if(!HeadShotSystem)" for false.

-----

"else if(HeadShotSystem == false)"

"else" is more than enough. If the first if-then is true then obviously the else below it will be false.

-----

"else SendClientMessage(issuerid, -1, "That player is in your team!");"

A big fail for that as you placed it for this if-then: "if(HeadShotSystem == true)"

-----

I suggest removing the previously mentioned message and placing the 4 if-thens (you can find them below) in just one statement.

"if(issuerid != INVALID_PLAYER_ID && weaponid == 34 && bodypart == 9)"
"if(HeadShotSystem == true)"
"if(GetPlayerTeam(issuerid) == NO_TEAM || GetPlayerTeam(playerid) == NO_TEAM || GetPlayerTeam(issuerid) != GetPlayerTeam(playerid))"
"if(!IsPlayerDead(playerid))"

-----

pawn Code:
stock IsPlayerDead(playerid)  
{  
    new Float: health = 0.0;  
    GetPlayerHealth(playerid, health);  
    if(GetPlayerState(playerid) == PLAYER_STATE_WASTED && health <= 0.0)  
        return true;  
    return false;  
}
Too overdone, just use a variable (boolean) and set it to true when the player spawns, and to false when the player dies or leaves the server. Simple as that.
Reply
#15

I had done that, but gammix suggested that 'function' about the rest I'll adjust.
Reply
#16

"if(GetPlayerTeam(issuerid) == NO_TEAM || GetPlayerTeam(playerid) == NO_TEAM || GetPlayerTeam(issuerid) != GetPlayerTeam(playerid))"

can also be written like this:

pawn Code:
if(GetPlayerTeam(issuerid) | GetPlayerTeam(playerid) == NO_TEAM || GetPlayerTeam(issuerid) != GetPlayerTeam(playerid))
Reply
#17

Quote:
Originally Posted by SickAttack
View Post
"Stock by Gammix"
"if (HeadShotSystem == true)"

You could just do "if(HeadShotSystem)" instead.

P.S. "if(!HeadShotSystem)" for false.

-----

"else if(HeadShotSystem == false)"

"else" is more than enough. If the first if-then is true then obviously the else below it will be false.
"else" is indeed more than enough, though I personally prefer to have it included as well.

The things you are pointing out are nothing more than 'personal styles and/or preferences'.
The one prefers to script it like "if(HeadShotSystem == true)" and the other prefers to script it like "if(HeadShotSystem)" They're both not wrong.

So, you pointed out pretty unrelated things.
Reply
#18

Quote:
Originally Posted by saffierr
View Post
"else" is indeed more than enough, though I personally prefer to have it included as well.

The things you are pointing out are nothing more than 'personal styles and/or preferences'.
The one prefers to script it like "if(HeadShotSystem == true)" and the other prefers to script it like "if(HeadShotSystem)" They're both not wrong.

So, you pointed out pretty unrelated things.
I don't see how it's not related, because it basically is as for feedback, suggestions and better programming practices.

You won't find "== true/false" being used in "higher level" projects (or however you want to call them) to be honest.

-----

The same thing applies to:

"new bool:Something = false;"

That "= false" is not required, but logically it isn't needed and removing it is most likely considered as better programming practice.
Reply
#19

Quote:
Originally Posted by SickAttack
View Post
I don't see how it's not related, because it basically is as for feedback, suggestions and better programming practices.

You won't find "== true/false" being used in "higher level" projects (or however you want to call them) to be honest.

-----

The same thing applies to:

"new bool:Something = false;"

That "= false" is not required, but logically it isn't needed and removing it is most likely considered as better programming practice.
How is it considered as 'better' lol, I truly don't see how, as it's different for everyone.
Having "new bool:Something = false;" is just for the sight of your eyes, and yes, I know a boolean is FALSE by default, but as I've said, it's just for the sight.
I do not see how it is possibly considered as better.
Reply
#20

Great for beginners!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)