SA-MP Forums Archive
[Include] GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Filterscripts (https://sampforum.blast.hk/forumdisplay.php?fid=17)
+---- Forum: Includes (https://sampforum.blast.hk/forumdisplay.php?fid=83)
+---- Thread: [Include] GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! (/showthread.php?tid=403713)



GetPlayerAimedBodyPart (v2.0) - Detect Headshots, Armshots, Legshots ! - Dinnozor - 31.12.2012

How it works

Using GetPlayerCameraFrontVector, GetPlayerCameraPos, but not any loops, this simple function detects where the shooter is aiming, and it returns a value according to where the shooter is aiming.
Works for every weapon : you can use this with guns, but also with close range weapons - see the video with the katana for example. It even detect the headshots when the target is in a vehicle, and headshots/armshots for crouched players !

Ideal for DM and zombie servers of course, but also nice for RP servers to get more realistic shootings !

Function

pawn Код:
stock GetPlayerAimedBodyPart(playerid, targetid, Float:range,weapon); //Returns the bodypart of targetid which playerid is aiming. Use it with OnPlayerTakeDamage ; I only tested it with it.
Callbacks

pawn Код:
public OnPlayerHeadshot(playerid,targetid,weaponid);//Do whatever you want when a player is hit in the head, the arm, the leg...
public OnPlayerLegshot(playerid,targetid,weaponid);
public OnPlayerArmshot(playerid,targetid,weaponid);
Put them wherever you want in your script.

In Game function

Код:
/widescreen - since 2.0, activates or deactivates the Widescreen mode for the player.
I made this function so the player manages manually the Widescreen ON/OFF mode. Indeed, as I try to explain below, although in the 1.0 and 1.01 versions being in Widescreen ON mode made it really easier to make headshots, this is not anymore a problem since 2.0, so the script doesn't have to check itself if the player uses Widescreen or not. It is now the player's problem since it doesn't give him advantages to use it or not. Don't hesitate to ask questions about this

v2.0 update (06/01/2013)
Pastebin (v2.0)
v1.01 update (03/01/2013)
Pastebin (v1.01 - Fix)
Pastebin (v1.0)
Example

Here is how I used the callbacks in the video (see code below) :
  • If hit in the head, if the player doesn't have a helmet the player dies or loses a lot of health according to the shooter weapon.
  • If hit in the leg, player will randomly fall or not.
  • If hit in the arm, the player might lose his weapon.


pawn Код:
public OnPlayerHeadshot(playerid,targetid,weaponid)
{
    new Float:Arm,Float:heal;

    GetPlayerArmour(targetid,Arm);
    GetPlayerHealth(targetid,heal);
   
    switch(weaponid){
                                case 33,34,30,31,25..27,24:{
                                    if(Casque[playerid]>1&&Arm>0){
                                        Casque[playerid]--;
                                        SetPlayerArmour(targetid,Arm-25);
                                    }
                                    else SetPlayerHealth(targetid,0);
                                }
                                case 22,23,28,29,32:{
                                    if((Arm>0&&Casque[targetid]>0)||GetPlayerSkin(targetid)==285){
                                        Casque[targetid]--;
                                        SetPlayerArmour(targetid,Arm-15);
                                    }
                                    else SetPlayerHealth(targetid,floatround(heal-30,floatround_round));
                                }
                                case 8:SetPlayerHealth(targetid,0);
                                case 4..6,1:SetPlayerHealth(targetid,floatround(heal-30,floatround_round));
                                default:SetPlayerHealth(targetid,floatround(heal-5,floatround_round));
    }
    GameTextForPlayer(playerid,"HEADSHOT !",1000,6);
    GameTextForPlayer(targetid,"OUCH ! HEADSHOT !",1000,6);
    return 1;
}

public OnPlayerLegshot(playerid,targetid,weaponid)
{
    switch(weaponid){
                                case 33,34,30,31,25..27,24:{
                                    if(random(3)==1) OnePlayAnim(targetid,"ped","FLOOR_hit",4,0,1,1,0,0);
                                }
                                case 22,23,28,29,32:{
                                    if(random(5)==1) OnePlayAnim(targetid,"ped","FLOOR_hit",4,0,1,1,0,0);
                                }
                                case 8:{
                                    if(random(2)==1) OnePlayAnim(targetid,"ped","FLOOR_hit",4,0,1,1,0,0);
                                }
                                case 4..6,1:
                                {
                                    if(random(3)==1) OnePlayAnim(targetid,"ped","FLOOR_hit",4,0,1,1,0,0);
                                }
                                default:{
                                    if(random(3)==1) OnePlayAnim(targetid,"ped","FLOOR_hit",4,0,1,1,0,0);
                                }
    }
    GameTextForPlayer(playerid,"LEGSHOT !",1000,6);
    GameTextForPlayer(targetid,"OUCH ! LEGSHOT !",1000,6);
    return 1;
}

public OnPlayerArmshot(playerid,targetid,weaponid)
{
    new wep=GetPlayerWeapon(targetid);
    if(wep!=0){
        switch(weaponid){
                                    case 33,34,30,31,25..27,24:{
                                        if(random(2)==1) DropWep(targetid,wep);
                                    }
                                    case 22,23,28,29,32:{
                                        if(random(3)==1) DropWep(targetid,wep);
                                    }
                                    case 8:{
                                        if(random(2)==1) DropWep(targetid,wep);
                                    }
                                    case 4..6,1:
                                    {
                                        if(random(2)==1) DropWep(targetid,wep);
                                    }
                                    default:{
                                        if(random(2)==1) DropWep(targetid,wep);
                                    }
        }
        GameTextForPlayer(playerid,"ARMSHOT !",1000,6);
        GameTextForPlayer(targetid,"OUCH ! ARMSHOT !",1000,6);
    }
    return 1;
}
Video

[ame="http://www.youtube.com/watch?v=2Y4ngd_wpzY"]Video[/ame]
Notice it works pretty well (this video was made with 1.0 version)

Installation

Just put this on top of your script :

pawn Код:
#include <GPABP>
Then, just put the callbacks seen above wherever you want in your script.

Q & A
Credits Thanks also to TheArcher, wups, Nanory for their help and contribution.


Don't hesitate to ask questions or suggest improvements. Feel free to share/use/modify but please don't remove credits if you share it.


Re: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - TheArcher - 31.12.2012

Pretty nice script ^_^. I have one suggestion.

Instead of modifying the include for

pawn Код:
public OnPlayerHeadshot(playerid,targetid,weaponid);
public OnPlayerLegshot(playerid,targetid,weaponid);
public OnPlayerArmshot(playerid,targetid,weaponid);
Just edit this part:

pawn Код:
case 1:OnPlayerHeadshot(issuerid,playerid,weaponid);
case 2:OnPlayerLegshot(issuerid,playerid,weaponid);
case 3:OnPlayerArmshot(issuerid,playerid,weaponid);
to

pawn Код:
case 1:CallLocalFunction("OnPlayerHeadshot", "ddd", issuerid,playerid,weaponid);
case 2:CallLocalFunction("OnPlayerLegshot", "ddd", issuerid,playerid,weaponid);
case 3:CallLocalFunction("OnPlayerArmshot", "ddd", issuerid,playerid,weaponid);
So, the callback is called only if your FS/GM has the "public".


Re: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - Lorenc_ - 31.12.2012

Hmm. I still will forever doubt such a feature will be accurate. But well done anyway. There was a GetPlayerWeaponVector function made, I forgot the author however maybe consider using that if it would work.


Re: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - Yiin - 31.12.2012

Great script ! thx


Re: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - Aldo. - 31.12.2012

Now test it on a server with 100+ players


Re: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - Konstantinos - 31.12.2012

Quote:
Originally Posted by Lorenc_
Посмотреть сообщение
I still will forever doubt such a feature will be accurate.
Me too. When a player with 300 ping will run and I hit his head with sniper (lag shooting), the camera's position will be kinda different compared to a player who doesn't move.


Re: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - Dinnozor - 31.12.2012

First, thanks for your comments and feedback.

@ TheArcher : Thanks for the suggestion. It is the first time I release an "include" so I didn't really know how I should post it. I will consider what you said about the callbacks.

@ Lorenc & Dwane : Of course there are some imperfections, but as you can see in the video, the result is pretty good, as every distance and with every weapon. I ******d the "GetPlayerWeaponVector" stuff but couldn't find anything interesting.
However in this script, I considered the fact that, when you aim with a weapon, the GetPlayerCameraFrontVector (on the Z axis) won't be really accurate, except with the sniper rifle. Indeed, when you're aiming, the player CameraFrontVector doesn't look exactly where you aim, the crosshair, but below it. At first I didn't consider this, then the results were awful and you could make headshots from very short distances only. That's why I used some trigo with angles I determined for each kind of weapon, making some tests, to get the most accurate result I could.
About the lag, since it uses the player pos, it will sure be tough to hit a player with lag, but it always is ^^ Although (if I can I will make some tests with other people), if you aim in front of the player while he moves, theoretically you could make headshots and stuff... To be tested.

@ Aldo : Unlike the last script I saw about this "headshot" problem, this script doesn't use any loop. It is only basic calculation from distances and player vectors. I can't test it on a 100+ server for now, but it would be interesting indeed if someone could tell us what it does... Though I don't think this eats much Ram.


Re: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - Maxips2 - 31.12.2012

What if the target is in movement? (His arms would swing and his legs would move)
What if the target is falling/jumping?

Does it detect those things?

BTW nice work


Respuesta: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - RubenZone - 31.12.2012

I have a doubt. How you declared, "Casque"? xD is it a normal variable?
Excellent contribution, I will add in Zombie Walk. thank you very much


Re: GetPlayerAimedBodyPart - Detect Headshots, Armshots, Legshots ! - Dinnozor - 01.01.2013

Thanks for the feedback

I tested the script with 3 mates yesterday and they all thought it worked fine, even with a little lag (I was running the server with a Wifi connexion). Only the armshot is kind of difficult to get.

Quote:
Originally Posted by Maxips2
Посмотреть сообщение
What if the target is in movement? (His arms would swing and his legs would move)
What if the target is falling/jumping?

Does it detect those things?
Basically the script calculates where the player is aiming and, if the target (whose Pos is X Y Z for example) is hit and if the shooter aims below Z-0.3, the player is aiming the legs. Then if the target moves, the script doesn't care if the legs move, it just determines if the player is aiming below Z-0.3.

It is almost the same with the arms, except it depends on the X and Y coordinates (and the facing angle then) - that actually makes the armshot the toughest to detect.

About the falling/jumping stuff, it should work just as fine as any other movement (player running...).

Quote:
Originally Posted by RubenZone
Посмотреть сообщение
I have a doubt. How you declared, "Casque"? xD is it a normal variable?
Lol "casque" means "helmet" in French, it is just a variable in my test script