[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(playeridissueridFloat:amountweaponidbodypart
  • 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 код:
booleanserver variable not player variable
new bool:HeadShotSystem
Main Code

PHP код:
public OnPlayerTakeDamage(playeridissueridFloat:amountweaponidbodypart)
{    
    
// 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(playeriddeadsizeof(dead));
                    
// we get the victims name with this function and store it into our previously made variable "killer";
                    
GetPlayerName(issueridkillersizeof(killer));
                    
//format the message, means we put that text into "headmsg".
                    
format(headmsgsizeof(headmsg), "{FFDC2E}%s (%i) Has Been Killed in a Headshot by %s (%i)!",deadplayeridkiller,issuerid);
                    
// once we've formatted the message we're ready to send the message to all players!
                    
SendClientMessageToAll(0xAA3333AAheadmsg);
                    
//kill the player
                    
SetPlayerHealth(playerid0.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(playeridparams[]) 

        
//replace with your admin system 
        
if(IsPlayerAdmin(playerid)) 
        { 
            
HeadShotSystem = !HeadShotSystem
            new 
string11[109], pname[24]; 
            
GetPlayerName(playeridpname24); 
            
format(string11sizeof(string11), "[Admin] Server admin %s(%d) has %s Headshot system!"pname,playerid,(HeadShotSystem)?("enabled"):("disabled")); 
            
SendClientMessageToAll(-1string11); 
        } 
        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 
Floathealth 0.0;
    
GetPlayerHealth(playeridhealth);
    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: 2 Guest(s)