[Include] drift-detection.inc - drifting gamemodes or minigames with ease!
#1

drift-detection.inc: v1.0.1
This include provide basic drift detection functionality that can be used in any drift script, it doesn't require a plugin, just plug and start using it. It's aimed to be basic to avoid performance issues since it's written in PAWN. I have noticed that the drift plugin was removed from the forum (and it didn't work with newer SA-MP versions) so I decided to rewrite this include I've created a while ago and release it. I am willing to continue developing this include if it gains interest, so don't hesitate to suggest a feature or report a bug!

Preview:
Documentation:

Functions:

PHP код:
Drift::EnableDetection(playerid = -1);
Drift::EnableDamageCheck(playerid = -1);
Drift::DisableDetection(playerid = -1);
Drift::DisableDamageCheck(playerid = -1);
boolDrift::IsDetectionEnabled(playerid = -1);
boolDrift::IsDamageCheckEnabled(playerid = -1);
boolDrift::IsPlayerDrifting(playerid);
Drift::SetMinAngle(Floatangle);
Drift::SetMinSpeed(Floatspeed);
Drift::SetTimeoutTicks(ticks);
FloatDrift::GetMinAngle();
FloatDrift::GetMinSpeed();
Drift::GetTimeoutTicks(); 
Callbacks:

PHP код:
forward OnPlayerDriftStart(playerid);
forward OnPlayerDriftUpdate(playeridFloatdrift_angleFloatspeed);
forward OnPlayerDriftEnd(playeridreasonFloatdistancetime); 
End reasons:
  • DRIFT_END_REASON_DAMAGED: vehicle is damaged (only when DamageCheck is enabled)
  • DRIFT_END_REASON_TIMEOUT: player has stopped drifting for N * delay interval.
  • DRIFT_END_REASON_OTHER: player left his vehicle or disconencted from the server.
Installation:

sampctl:

Код:
sampctl package install ltkarim/drift-detection
GitHub:

https://github.com/ltkarim/drift-detection
Reply
#2

very nice
Reply
#3

lol why re-create the thread with the same include? Simply reposting to bump?
Reply
#4

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
lol why re-create the thread with the same include? Simply reposting to bump?
Link me to the old one please? There isn't any old threads that I could "bump".
Reply
#5

You deleted it lmao, you seriously gonna deny that?
What did you even update? I see no changes from the older thread that was about a year ago.
Reply
#6

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
You deleted it lmao, you seriously gonna deny that?
What did you even update? I see no changes from the older thread that was about a year ago.
This is an entire different include, the old one was released in 2016 which was poorly written and I don't want to support it anymore, thus a new thread.

Changes:

drift-detection.inc:

PHP код:
public OnPlayerUpdate(playerid)
{
    if(
g_DriftFlags DRIFT_CHECK_ENABLED && g_DriftPlayers[playerid][playerFlags] & DRIFT_CHECK_ENABLED)
    {
        if(
GetTickCount() > g_DriftPlayers[playerid][lastTimestamp])
        {
            new 
vehicleID GetPlayerVehicleID(playerid);
            if(
vehicleID && GetPlayerState(playerid) == PLAYER_STATE_DRIVER && IsModelACar(GetVehicleModel(vehicleID)))
            {
                new 
FloatvXFloatvYFloatvZ;
                
GetVehicleVelocity(vehicleIDvXvYvZ);
                new 
Floatangle;
                
GetVehicleZAngle(vehicleIDangle);
                new 
Floatspeed;
                
speed floatsqroot(vX*vX vY*vY vZ*vZ) * 180.0;
                
                new 
Floatdirection;
                
direction atan2(vYvX);
                
direction -= 90.0;
        
                if(
direction 0direction += 360.0;
                new 
FloatdriftAngle;
                
driftAngle angle floatabs(direction);
                if(
driftAngle 270.0driftAngle -= 270.0;
                if(
driftAngle < -270.0driftAngle += 270.0;
                
driftAngle floatabs(driftAngle);
            
                switch(
g_DriftPlayers[playerid][driftState])
                {
                    case 
DRIFT_STATE_NONE:
                    {
                        if(
MIN_DRIFT_ANGLE <= driftAngle <= MAX_DRIFT_ANGLE && speed >= MIN_DRIFT_SPEED)
                        {                        
                            
g_DriftPlayers[playerid][driftState] = DRIFT_STATE_DRIFTING;
                            
g_DriftPlayers[playerid][startTimestamp] = GetTickCount();
                            
GetVehicleHealth(vehicleIDg_DriftPlayers[playerid][vHealth]);
                            
GetPlayerPos(playeridg_DriftPlayers[playerid][startPosX], g_DriftPlayers[playerid][startPosY], g_DriftPlayers[playerid][startPosZ]);
                            
                            
#if defined OnPlayerDriftStart
                                
OnPlayerDriftStart(playerid);
                            
#endif
                        
}
                    }
                    case 
DRIFT_STATE_DRIFTING:
                    {
                        if(
g_DriftFlags DAMAGE_CHECK_ENABLED && g_DriftPlayers[playerid][playerFlags] & DAMAGE_CHECK_ENABLED)
                        {
                            new 
FloatvehicleHealth;
                            
GetVehicleHealth(vehicleIDvehicleHealth);
                            if(
vehicleHealth g_DriftPlayers[playerid][vHealth])
                            {
                                
GetPlayerPos(playeridvXvYvZ);
                                
g_DriftPlayers[playerid][driftState] = DRIFT_STATE_NONE;
                                
g_DriftPlayers[playerid][timeoutTicks] = 0;
                                
#if defined OnPlayerDriftEnd
                                    
new Floatdistance;
                                    
distance GetPlayerDistanceFromPoint(playeridg_DriftPlayers[playerid][startPosX], g_DriftPlayers[playerid][startPosY], g_DriftPlayers[playerid][startPosZ]);
                                    
OnPlayerDriftEnd(playeridDRIFT_END_REASON_DAMAGEDdistanceGetTickCount() - g_DriftPlayers[playerid][startTimestamp]);
                                
#endif
                            
}
                        }
                        else if(
MIN_DRIFT_ANGLE <= driftAngle <= MAX_DRIFT_ANGLE && speed >= MIN_DRIFT_SPEED)
                        {
                            
g_DriftPlayers[playerid][timeoutTicks] = 0;
                            
                            
#if defined OnPlayerDriftUpdate
                                
OnPlayerDriftUpdate(playeriddriftAnglespeed);
                            
#endif
                        
}
                        else
                        {
                            
g_DriftPlayers[playerid][timeoutTicks]++;
                            if(
g_DriftPlayers[playerid][timeoutTicks] >= DRIFT_TIMEOUT_INTERVAL)
                            {
                                
GetPlayerPos(playeridvXvYvZ);
                                
                                
g_DriftPlayers[playerid][driftState] = DRIFT_STATE_NONE;
                                
g_DriftPlayers[playerid][timeoutTicks] = 0;
                                
#if defined OnPlayerDriftEnd
                                    
new Floatdistance;
                                    
distance GetPlayerDistanceFromPoint(playeridg_DriftPlayers[playerid][startPosX], g_DriftPlayers[playerid][startPosY], g_DriftPlayers[playerid][startPosZ]);
                                    
OnPlayerDriftEnd(playeridDRIFT_END_REASON_TIMEOUTdistanceGetTickCount() - g_DriftPlayers[playerid][startTimestamp]);
                                
#endif
                            
}
                        }
                    }
                }
            }
            
g_DriftPlayers[playerid][lastTimestamp] = GetTickCount() + DRIFT_PROCESS_INTERVAL;
        }
    }
    
#if defined Drift_OnPlayerUpdate
        
return Drift_OnPlayerUpdate(playerid);
    
#else
        
return true;
    
#endif

drift.inc: (2016)

PHP код:
public OnPlayerUpdate(playerid) {
    if(
GetTickCount() > P_DATA[playerid][T_TICK])
    {
        new 
vehicleid;
        if( (
vehicleid GetPlayerVehicleID(playerid)) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER )
        {
            if(
__IsModelACar(GetVehicleModel(vehicleid)))
            {
                new 
Float:xFloat:yFloat:zFloat:aFloat:dFloat:sFloat:drift_angle;
                
GetVehicleVelocity(vehicleidxyz);
                
GetVehicleZAngle(vehicleida);
                
floatround(floatsqrootx*y*z*z) * 180);
                
atan2(yx);
                
floatsub(d90.0);
                if(
0.0floatadd(d360.0);
                
drift_angle d;
                if(
drift_angle 270.0drift_angle -= 270.0;
                if(
drift_angle < -270.0drift_angle += 270.0;
                
drift_angle floatabs(drift_angle);
                switch (
P_DATA[playerid][P_DRIFTING])
                {
                    case 
0:
                    {
                        if(
MIN_DRIFT_ANGLE <= drift_angle <= MAX_DRIFT_ANGLE && >= MIN_DRIFT_SPEED && !__IsVehicleDrivingBackwards(xya))
                        {
                            
P_DATA[playerid][P_DRIFTING] = true;
                            
P_DATA[playerid][D_STARTTICK] = GetTickCount();
                            
GetVehicleHealth(vehicleidP_DATA[playerid][V_HEALTH]);
                            
GetPlayerPos(playeridP_DATA[playerid][P_STARTX], P_DATA[playerid][P_STARTY], x);
                            
CallLocalFunction("OnDriftStart""i"playerid);
                        }
                    }
                    case 
1:
                    {
                        new 
Float:vhealthFloat:_xFloat:_yFloat:_z;
                        
GetVehicleHealth(vehicleidvhealth);
                        
GetPlayerPos(playerid_x_y_z);
                        if(
vhealth P_DATA[playerid][V_HEALTH]) 
                        {
                            
CallLocalFunction("OnDriftEnd""iifi"playeridDRIFT_END_REASON_CRASH__GetPointDistanceToPoint(P_DATA[playerid][P_STARTX],  P_DATA[playerid][P_STARTY], _x_y),  GetTickCount() - P_DATA[playerid][D_STARTTICK]);
                            
P_DATA[playerid] = R_DATA;
                        }
                        else if(
__IsVehicleDrivingBackwards(xya) || MIN_DRIFT_SPEED)
                        {
                            
CallLocalFunction("OnDriftEnd""iifi"playeridDRIFT_END_REASON_OTHER__GetPointDistanceToPoint(P_DATA[playerid][P_STARTX],  P_DATA[playerid][P_STARTY], _x_y),  GetTickCount() - P_DATA[playerid][D_STARTTICK]);
                            
P_DATA[playerid] = R_DATA;
                        }
                        else if(
MIN_DRIFT_ANGLE <= drift_angle <= MAX_DRIFT_ANGLE && >= MIN_DRIFT_SPEED)
                        {
                            
P_DATA[playerid][T_TIMEOUT] = 0;
                            
CallLocalFunction("OnDriftUpdate""iff"playeriddrift_angles);
                        }
                        else 
                        {
                            
P_DATA[playerid][T_TIMEOUT]++;
                            if(
P_DATA[playerid][T_TIMEOUT] >= DRIFT_TIMEOUT_INTERVAL)
                            {
                                
CallLocalFunction("OnDriftEnd""iifi"playeridDRIFT_END_REASON_TIMEOUT__GetPointDistanceToPoint(P_DATA[playerid][P_STARTX],  P_DATA[playerid][P_STARTY], _x_y),  GetTickCount() - P_DATA[playerid][D_STARTTICK]);
                                
P_DATA[playerid] = R_DATA;
                            }
                        }
                    }
                }
            }
        }
        
P_DATA[playerid][T_TICK] = GetTickCount() + PROCESS_INTERVAL;
    }
    
#if defined D_OnPlayerUpdate
        
return D_OnPlayerUpdate(playerid);
    
#else
        
return true;
    
#endif

Reply
#7

That's not how you go around releasing things, this is nothing different, it's literally the same include (drift based concept) you're supposed to update and notify not simply delete and recreate, that's how you fuck up the old users, you're also supposed to take people's opinions and criticizes instead of just accusing me of increasing post count simply for commenting my opinion on a release which i have the right to do whenever i feel like it.
Anyhow i'm gonna test this and see how it goes then report back here.

EDIT: it won't even compile: error 021: symbol already defined: "OnPlayerStateChange"

You missed an 'e' on line 324
Reply
#8

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
That's not how you go around releasing things, this is nothing different, it's literally the same include (drift based concept) you're supposed to update and notify not simply delete and recreate
I didn't delete the thread just to create this thread, it was deleted way before I even think of re-releasing this include.

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
EDIT: you forgot to hook OnPlayerStateChange
It is hooked.
Reply
#9

It's not hooked right, you missed an 'e' on line 324

it's : OnPlayerStateChang

when it's supposed to be OnPlayerStateChange
Reply
#10

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
It's not hooked right, you missed an 'e' on line 324

it's : OnPlayerStateChang

when it's supposed to be OnPlayerStateChange
Fixed, thank you.
Reply
#11

You're welcome, i also just tried using it, had 0 luck getting any response,
i used this:
PHP код:
public OnPlayerDriftStart(playerid)
{
    
SendClientMessageToAll(-1"Started");
    return 
1;
}

public 
OnPlayerDriftUpdate(playeridFloatdrift_angleFloatspeed)
{
    
SendClientMessageToAll(-1"Doing");
    return 
1;
}

public 
OnPlayerDriftEnd(playeridreasonFloatdistancetime)
{
    
SendClientMessageToAll(-1"Ended");
    return 
1;

and kept swinging my elegy all over the place and got 0 msgs, can you test it and upload a video? i need to see how you exactly detect drifting because i tried steerlocking, power sliding and long turns/short turns got nothing.
Reply
#12

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
You're welcome, i also just tried using it, had 0 luck getting any response,
i used this:
PHP код:
public OnPlayerDriftStart(playerid)
{
    
SendClientMessageToAll(-1"Started");
    return 
1;
}
public 
OnPlayerDriftUpdate(playeridFloatdrift_angleFloatspeed)
{
    
SendClientMessageToAll(-1"Doing");
    return 
1;
}
public 
OnPlayerDriftEnd(playeridreasonFloatdistancetime)
{
    
SendClientMessageToAll(-1"Ended");
    return 
1;

and kept swinging my elegy all over the place and got 0 msgs, can you test it and upload a video? i need to see how you exactly detect drifting because i tried steerlocking, power sliding and long turns/short turns got nothing.
https://gfycat.com/gifs/detail/Refle...lligatorlizard

You need to enable drift globally and per player first. Check test.pwn. The include itself is disabled by default, you have to call Drift::EnableDetection();
in script init and Drift::EnableDetection(playerid) to enable detection for the player.
Reply
#13

Okay it does work, i got some things to report tho, first of all the detection is too sensitive if i make a simple turn without turning my nos on it's detecting me drifting i can go all over the map with this without calling the drift end function so i SUGGEST 3 things,
1- make min speed 50.0 by default
2- make the angle detection sharper (smaller angle the car must turn more but not too much)
3- decrease the time of detection between each drift end.
And the damage detection won't work for me, i used damagecheckenable globally and per-player and it still wont work it keeps saying drift end reason 0

I can give you tips on this, it was hard for me to detect when i first started working on my drift system so if you can't get it to work, you basically get the vehicle's health the moment a player starts drifting, then when he's in the update-drift stage you keep checking for the vehicle's health if < when he started = drift end reason damage AND update the original car's health variable to the current vehicle's health. Also don't forget to update it every time SetVehicleHealth is used so you'll need to make this work for both filterscripts and gamemodes using #if defined FILTERSCRIPT and #else at the beginning and end and tell the users to include it in filterscripts and gamemodes and only edit through the gamemode.
Reply
#14

1-2. I am planning to create global functions to set the minimum angle & speed to initiate the drift so it could be adjusted per user needs, as well as increase the defaults in the next update.

3. Same goes for this, however I think it should be defaulted like that, but it'll be adjustable globally.

The damage detection worked for me flawlessy (although I have had to get another player to shoot my car), and this is exactly the same method you suggested, except for the SetVehicleHeath which will be hooked in the next update.

Thank you for your feedback.
Reply
#15

It won't work at all for me, i kept banging the car against walls it wouldn't end for damage reason, try it now, it only ends if someone shoots the car? shouldn't be whenever the car is damaged?
Reply
#16

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
It won't work at all for me, i kept banging the car against walls it wouldn't end for damage reason, try it now, it only ends if someone shoots the car? shouldn't be whenever the car is damaged?
I'll have a look again, but it should work either way:

PHP код:
if(g_DriftFlags DAMAGE_CHECK_ENABLED && g_DriftPlayers[playerid][playerFlags] & DAMAGE_CHECK_ENABLED)
{
    new 
FloatvehicleHealth;
    
GetVehicleHealth(vehicleIDvehicleHealth);
    if(
vehicleHealth g_DriftPlayers[playerid][vHealth])
    {
        
GetPlayerPos(playeridvXvYvZ);
        
g_DriftPlayers[playerid][driftState] = DRIFT_STATE_NONE;
        
g_DriftPlayers[playerid][timeoutTicks] = 0;
        
#if defined OnPlayerDriftEnd
            
new Floatdistance;
            
distance GetPlayerDistanceFromPoint(playeridg_DriftPlayers[playerid][startPosX], g_DriftPlayers[playerid][startPosY], g_DriftPlayers[playerid][startPosZ]);
            
OnPlayerDriftEnd(playeridDRIFT_END_REASON_DAMAGEDdistanceGetTickCount() - g_DriftPlayers[playerid][startTimestamp]);
        
#endif
    
}

Reply
#17

Quote:
Originally Posted by iKarim
Посмотреть сообщение
I'll have a look again, but it should work either way:

PHP код:
if(g_DriftFlags DAMAGE_CHECK_ENABLED && g_DriftPlayers[playerid][playerFlags] & DAMAGE_CHECK_ENABLED)
{
    new 
FloatvehicleHealth;
    
GetVehicleHealth(vehicleIDvehicleHealth);
    if(
vehicleHealth g_DriftPlayers[playerid][vHealth])
    {
        
GetPlayerPos(playeridvXvYvZ);
        
g_DriftPlayers[playerid][driftState] = DRIFT_STATE_NONE;
        
g_DriftPlayers[playerid][timeoutTicks] = 0;
        
#if defined OnPlayerDriftEnd
            
new Floatdistance;
            
distance GetPlayerDistanceFromPoint(playeridg_DriftPlayers[playerid][startPosX], g_DriftPlayers[playerid][startPosY], g_DriftPlayers[playerid][startPosZ]);
            
OnPlayerDriftEnd(playeridDRIFT_END_REASON_DAMAGEDdistanceGetTickCount() - g_DriftPlayers[playerid][startTimestamp]);
        
#endif
    
}

I looked at your code but it's too bad to not hook setvehiclehealth the way i told you but good job overall with the tips i provided it would be pretty cool and i would use it for my own, i might fork it on github to help out with the vehicle health damage check thing, good luck.
Reply
#18

Update v1.1.0

New functions:

PHP код:
stock Drift::SetMinAngle(Floatangle);
stock Drift::SetMinSpeed(Floatspeed);
stock Drift::SetTimeoutTicks(ticks);
stock FloatDrift::GetMinAngle();
stock FloatDrift::GetMinSpeed();
stock Drift::GetTimeoutTicks(); 
Changes:
  • Drift detection and vehicle damage checks are enabled globally by default.
  • Increased default drift angle and speed to initiate a drift
Download:

Github: https://github.com/ltkarim/drift-detection/releases
Reply
#19

Good job I like the new default settings, did you fix the damage check thing? Made sure it works?
Reply
#20

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
Good job I like the new default settings, did you fix the damage check thing? Made sure it works?
Thanks, and yes. It should be working fine now.
Reply


Forum Jump:


Users browsing this thread: 5 Guest(s)