[Tutorial] How To Make Anti Cheat for your server [V0.1] [ZCMD]
#1


So Hi all today I am going to show you how to make some anti cheats for your server!

in this tutorial we are going to need:

sscanf by ******
ZCMD by zeex

Right Now Anti Cheats:

-Weapon Hack
-Anti RCON login attempt
-Anti Spawn Kill
-Anti Jetpack spawn hack

NEW On 0.2:
-Anti High Ping
-Anti Packet Loss

New On 0.3:

-Anti CBUG system!

New on V0.4:

-Anti SPAM!
-Anti ADV!
-Anti HH!

So let's start

first let's start with Weapon Hack, Weapon hack is really easy to be detactable
at this anti cheat we are going to use onplayerupdate so Onplayerupdate:

first at the top of the script:
pawn Код:
#define DIALOG_ANTI 10 // here we define the dialog of the Anti cheat as dialog id 10 you can change it if you want
Now OnPlayerUpdate We need to put those following codes: (Explaining in comments)
pawn Код:
public OnPlayerUpdate(playerid)
{
    new PlayerWeapon[MAX_PLAYERS];//here we create a var called PlayerWeapon and we are going to make this var for all the players
    new gunname[32]; // we use this one to detect the gun name from the id of the weapon
    new string[120];//this is the string we are going to use it to format the message
    new string2[120];//this is the string we are going to use it to format the dialog
    PlayerWeapon[playerid] = GetPlayerWeapon(playerid);//here we define the PlayerWeapon[playerid] as GetPlayerWeapon(playerid) so
    //if you did PlayerWeapon[playerid] == 38 it's the same as GetPlayerWeapon(playerid) == 38
    //so you are going to ask yourself what is 38? 38 is minigun you can also find all the other guns here on sa-mp wiki:
    //https://sampwiki.blast.hk/wiki/Weapons this one will show you each weapon with it's ID
    if(PlayerWeapon[playerid] == 38 || PlayerWeapon[playerid] == 39 || PlayerWeapon[playerid] == 36)//so if the player weapon is 38 aka minigun
    {//or satchel or HS rocket
    GetWeaponName(PlayerWeapon[playerid],gunname,sizeof(gunname));//here is the variable getweaponname I will explain it now
    //The right syntax for the GetWeaponName is : GetWeaponName(weaponid, const weapon[], len); the first one is for the weapon id and the second
    //and the second is for the string we are going to store the weapon name in and the last one is the size of that string so let's kick the player?
    format(string,sizeof(string),"[ANTI-CHEAT] Player: %s ID: %d Has been Kicked Reason: Weapon Hack || Weapon: %s",GetName(playerid),playerid,gunname);
    SendClientMessageToAll(-1,string);//now we are going to send the formated message to all the players
    //at this one: we are going to format the dialog that we are going to send to the banned player
    //you can change the http://www.website.com too your own website :)
    format(string2,sizeof(string2),"You Have Been Banned By Anti Cheat!\nReason:Weapon Hack\nWeapon:%s\nIf you feel you are wrongly banned please visit:\nwww.website.com",gunname);
    ShowPlayerDialog(playerid,DIALOG_ANTI,DIALOG_STYLE_MSGBOX,"Anti Cheat!",string2,"Okay","");//we are going to show the dialog to the player
    Ban(playerid);//and we are going to ban that player
    }
    return 1;
}
so if you compiled right now I am sure that you will have this error: undefined symbol GetName or something like that
if you had it, don't worry! it just means that you didn't define the GetName stock so how can you get rid of this error?
you have to define the stock , so in any place in your gamemode put:
pawn Код:
stock GetName(playerid)
{
    new pName22[68];
    GetPlayerName(playerid, pName22, sizeof(pName22));
    return pName22;
}
so no errors? that's good now we have made our advanced Weapon hack Anti Cheat! but for sure that's not enough to secure the server
so after the weapon hack tutorial, we have to make one of the most important anti cheats ever !! we gonna make anti wrong rcon password
I know that it's not considered as "cheat" but it's important
so at this one we are going to use the onrconloginattempt function so let's go there!
if you don't have it then here it is:
pawn Код:
public OnRconLoginAttempt(ip[], password[], success)
{

return 1;
}
so inside the OnRconLoginAttempt after the { bracket we need to put our main functions
this one is going to be easy and it will not require a lot
pawn Код:
public OnRconLoginAttempt(ip[], password[], success)
{
    if(!success) //at this one we are going to check if he successed or not , if he didn't then:
    {
        new PlayerIP[16];//this one is used to store the ip of the player
        for(new i=0; i<MAX_PLAYERS; i++) //Loop through all players
        {
            GetPlayerIp(i, PlayerIP, sizeof(PlayerIP));
            if(!strcmp(ip, PlayerIP, true))//if the player ip is the same as PlayerIP we are going to make it on him
            {
                //you can change the http://www.website.com too your own website :)
                ShowPlayerDialog(i,DIALOG_ANTI,DIALOG_STYLE_MSGBOX,"Anti Cheat!","You Have Been Banned By Anti Cheat!\nReason:Wrong Rcon login\nIf you feel you are wrongly banned please visit:\nwww.website.com","Okay","");//we are going to show the dialog to the player
                Ban(i);//then we are going to ban him
            }
        }
    }
    return 1;
}
So right now we have made 2 anti cheats, one for anti weapon hack and the second for wrong rcon attempt
But I don't think that both of them are enough to protect the player
so now we are going to make anti spawn kill !
so we are going to use OnPlayerSpawn on this one
but first, at the top of yourscript:
pawn Код:
new JustSpawned[MAX_PLAYERS];//detect if the player is just spawned or not
#define SPAWN_TIME 3 // this one will be the timer you can change the 3 seconds to any other time you want
now onplayerspawn we are going to do our function:
pawn Код:
JustSpawned[playerid] = 1;//we set JustSpawned to 1 which means that the player is just spawned
SetTimerEx("JSpawned",SPAWN_TIME*1000,0,"d",playerid);//now we are going to set a timer for the player and we are going to make 0 loop which means it will not be repeated after the time is over
so now if you compiled it may give a warning that the JSpawned is never used so let's define it?
pawn Код:
forward JSpawned(playerid);//here we are going to forward the JSpawned function
public JSpawned(playerid)//and here we are going to start to do the main function
{//open bracket for sure
JustSpawned[playerid] = 0;//we set JustSpawned to 0 which means he got spawned from a long time ago
return 1;//we are going to use return 1; to avoid bugs
}
so here we did the timer function BUT we are not finished yet, now we have to detect if the player is getting attacked when he is just spawned or not
so onplayertakedamage:
if you don't have the function then here is it:
pawn Код:
public OnPlayerTakeDamage(playerid, issuerid, Float:amount, weaponid)
{
    return 1;
}
now let's put somehting inside it, so after OnPlayerTakeDamage after the { bracket we need to put:
pawn Код:
public OnPlayerTakeDamage(playerid, issuerid, Float:amount, weaponid)
{
    if(JustSpawned[playerid] == 1)//if the player is just spawned
    {//opening bracket
    new Float:X,Float:Y,Float:Z;//we are going to define X,Y,Z
    GetPlayerPos(issuerid,X,Y,Z);//we are going to store the X,Y,Z of the attacker id
    SetPlayerPos(issuerid,X,Y,Z+3);//we are going to set the pos of the attacker id to Z+3 that means it will put him in the air
    GameTextForPlayer(issuerid,"Don't Spawn Kill!",4000,2);//here we are going to show a gametext for the player for 4000 ms which is equal 4 sec and tell him Don't Spawn Kill!
    }//closing the bracket
    return 1;//NEVER FORGET TO USE return 1;
}
so now we are going to make the simplest one which is for jetpack
so onplayerupdate we have to put that:
pawn Код:
if(GetPlayerSpecialAction(playerid) == SPECIAL_ACTION_USEJETPACK)//if we detected that the player special action is jetpack then:
{
new string22[120];//we are going to define a new string because we are going to store things there
//here we are going to format the string by getting the player name and ID and putting it there:
format(string22,sizeof(string22),"[ANTI - CHEAT] Player: %s ID: %d has been banned by anti cheat! Reason: Anti Jetpack hack",GetName(playerid),playerid);
SendClientMessageToAll(-1,string22);//then we are going to send the message to everyone in game
//you can change the http://www.website.com too your own website :)
ShowPlayerDialog(playerid,DIALOG_ANTI,DIALOG_STYLE_MSGBOX,"Anti Cheat!","You Have Been Banned By Anti Cheat!\nReason:Jet Pack\nIf you feel you are wrongly banned please visit:\nwww.website.com","Okay","");//we are going to show the dialog to the player
Ban(playerid);//we are going to ban the player
}
Now it's time to do Anti High Ping and Anti Packet Loss!

First on the top of the script we have to define the MAX things allowed on this server so we gonna do this:
pawn Код:
#define MAX_PING 1024 //The Maximum ping allowed in the server! change the 1024 to any max ping you want!
#define MAX_PL 12.0 //The Maximum packet loss allowed in the server! change 12.0 to any max packetloss you want!
#define MAX_PINGWARN 5 //The Maximum warns for the player before it kick him for high ping! change it if you want!
#define MAX_PLWARN 5 //The Maximum warns for the player before it kick him for high ping! change it if you want!
new PlayerPingWarns[MAX_PLAYERS];//The times that player got warned for High Ping!
new PlayerPLWarns[MAX_PLAYERS];//The times that player got warned for High PacketLoss!
new PlayerStatsTimer[MAX_PLAYERS];//The timer define!
Now we are going to do a timer to see the player ping and packetloss, but first we need to Make sure if the player
is Spawned or not! so at the top of the script:
pawn Код:
new PlayerSpawned[MAX_PLAYERS] = {0};//we set playerspawned as 0 for default!
now OnPlayerSpawn
pawn Код:
PlayerSpawned[playerid] = 1;//we set PlayerSpawned to 1! which means he is spawned!
now OnPlayerDeath
pawn Код:
PlayerSpawned[playerid] = 0; // we set PlayerSpawned to 0! which means that the player is not spawned!
Now OnPlayerSpawn Again we need to add the Timer that will do the whole function!
pawn Код:
PlayerStatsTimer[playerid] = SetTimerEx("CheckStats", 1000, true, "i", playerid);//we are going to make a timer called CheckStats!
so after we created the timer we need to add some functions so our code will work fine!
Let's add the get player packetloss stock! at any place in your gm [need to be after the includes not before it] add:
pawn Код:
stock Float:GetPlayerPacketLoss(playerid)//the stock
{
        new stats[401], stringstats[70];//those are the variables we will need in the stock
        GetPlayerNetworkStats(playerid, stats, sizeof(stats));//this one will get the net stats
        new len = strfind(stats, "Packetloss: ");//and this one will get the packetloss
        new Float:packetloss = 0.0;//the float for the packetloss
        if(len != -1)
        {
                strmid(stringstats, stats, len, strlen(stats));
                new len2 = strfind(stringstats, "%");
                if(len != -1)
                {
                        strdel(stats, 0, strlen(stats));
                        strmid(stats, stringstats, len2-3, len2);
                        packetloss = floatstr(stats);
                }
        }
        return packetloss;
}
So now let's do our timer function!
pawn Код:
forward CheckStats(playerid);//forward the function!
public CheckStats(playerid)//now we are going to use public!
{//we open the bracket for CheckStats
new string[120];//we make a string!
new string2[120];//we make a second string!
if(GetPlayerPing(playerid) >= MAX_PING && PlayerPingWarns[playerid] < MAX_PINGWARN)//If the player ping is more than or equal to the maximum ping and the player warns is not equal the max warns!
{
PlayerPingWarns[playerid] ++; // we increase the warns!
format(string,sizeof(string),"Warning! High Ping! [%d/%d]",PlayerPingWarns[playerid],MAX_PINGWARN);//we Warn the player that his ping is high!
SendClientMessage(playerid,-1,string);//then we send it!
}
else if(GetPlayerPing(playerid) >= MAX_PING && PlayerPingWarns[playerid] == MAX_PINGWARN)//if the player ping is more than the max ping and the player ping warns is = to the max warns
{
PlayerPingWarns[playerid] = 0;//we set it to 0 !
format(string,sizeof(string),"Warning! High Ping! [%d/%d]",PlayerPingWarns[playerid],MAX_PINGWARN);//we Warn the player that his ping is high!
SendClientMessage(playerid,-1,string);//then we send it!
format(string2,sizeof(string2),"You Have Been Kicked By Anti Cheat!\nReason:High Ping!");//we are going to format the dialog !
ShowPlayerDialog(playerid,DIALOG_ANTI,DIALOG_STYLE_MSGBOX,"Anti Cheat!",string2,"Okay","");//we are going to show the dialog to the player
Kick(playerid);//finally we kick him!
}

if(GetPlayerPacketLoss(playerid) >= MAX_PL && PlayerPLWarns[playerid] < MAX_PLWARN)//If the player Packetloss is more than or equal to the maximum packetloss and the player warns is not equal the max warns!
{
PlayerPLWarns[playerid] ++; // we increase the warns!
format(string,sizeof(string),"Warning! High PacketLoss! [%d/%d]",PlayerPingWarns[playerid],MAX_PLWARN);//we Warn the player that his Packetloss is high!
SendClientMessage(playerid,-1,string);//then we send it!
}
else if(GetPlayerPing(playerid) >= MAX_PL && PlayerPLWarns[playerid] == MAX_PLWARN)//if the player ping is more than the max ping and the player Packetloss warns is = to the max warns
{
PlayerPLWarns[playerid] = 0;//we set it to 0 !
format(string,sizeof(string),"Warning! High Packetloss! [%d/%d]",PlayerPLWarns[playerid],MAX_PLWARN);//we Warn the player that his Packetloss is high!
SendClientMessage(playerid,-1,string);//then we send it!
format(string2,sizeof(string2),"You Have Been Kicked By Anti Cheat!\nReason:High Packetloss!");//we are going to format the dialog !
ShowPlayerDialog(playerid,DIALOG_ANTI,DIALOG_STYLE_MSGBOX,"Anti Cheat!",string2,"Okay","");//we are going to show the dialog to the player
Kick(playerid);//finally we kick him!
}
return 1;//we use return 1 to avoid bugs
}//we close the Chectstats bracket! it means that we finished!
so this CBUG system is going to be easy! as we are going to need one function! so at the top of the gamemode put:
[make sure it's after includes]:
pawn Код:
new CbugWarnings[MAX_PLAYERS];//we created this one to get the player warnigns time!
#define MAX_CBUGWARNINGS 10//the player will get warned 10 times then get kicked!
now OnPlayerStateChange we need to put:
pawn Код:
if ((oldkeys & KEY_FIRE) && (newkeys & KEY_CROUCH))  //if the player used  fire then Crouch after that!
 {
 if(CbugWarnings[playerid] < MAX_CBUGWARNINGS) // if the cbug warnings is less than the max warnings!
 {
 CbugWarnings[playerid] ++;//we increase the cbug warns of the player!
 new string[120];//we define a string called string!
 format(string,sizeof(string),"Warning! Don't Cbug [%d/%d]",CbugWarnings[playerid],MAX_CBUGWARNINGS);//we format the string and warn the player!
 SendClientMessage(playerid,-1,string);//then we send that message!
 }
 else if(CbugWarnings[playerid] >= MAX_CBUGWARNINGS)
 {
 CbugWarnings[playerid] = 0;//we set the Cbugwarninsg to 0!
 new string[120];//we define a string called string!
 new string2[120];///we define an other string called string2!
 format(string,sizeof(string),"[ANTI-CHEAT] Player: %s ID: %d Has been Kicked Reason: CBUG",GetName(playerid),playerid);//We Format the string and tell the players that there is player who got kicked for CBUG!
 SendClientMessageToAll(-1,string);//Then we send it to all!
 format(string2,sizeof(string2),"You Have Been Kicked By Anti Cheat!\nReason:CBUG");//we format the dialog!
 ShowPlayerDialog(playerid,DIALOG_ANTI,DIALOG_STYLE_MSGBOX,"Anti Cheat!",string2,"Okay","");//we are going to show the dialog to the player
 Kick(playerid);//THEN we Kick that player!
 }
 }
So what if the player got disconnected but he had CBUG warnings? then OnPlayerDisconnect:
pawn Код:
if(CbugWarnings[playerid] > 0) //if the player got warned at least one time or more!
{
CbugWarnings[playerid] = 0;//we Set it to 0!
}
Okay So Let's do an ANTI SPAM!
So anti spam is some how useful if there is no admin online.
I came to a server once [ Don't want to say it's name] and everyone was spamming And I hated it
So Today I decided to do the next Version For anti cheat! Alright then
At the top of the script:

pawn Код:
#define MAX_SPAM 3 // The MAX spam allowed for the player.
#define MAX_DECREASECOUNT 5 //Decrease count means decrease the player spam and 5 is = 5 seconds
new PlayerSpam[MAX_PLAYERS]; // The times that the player spammed in.
new SpamTimer[MAX_PLAYERS]; // The timer we are going to use to decrease the count.
Okay Good now OnPlayerConnect we need to set the PlayerSpam to 0 right?
So OnPlayerConnect put:
pawn Код:
PlayerSpam[playerid] = 0;//we Set the player spam to 0!
And OnPlayerDisconnect:
pawn Код:
PlayerSpam[playerid] = 0;//we Set the player spam to 0!
Now OnPlayerText:
pawn Код:
SpamTimer[playerid] = SetTimerEx("DecreaseSpam",MAX_DECREASECOUNT*1000,1,"d",playerid)
if(PlayerSpam[playerid] < MAX_SPAM)//If the playerspam is less than the max_spam
{
 PlayerSpam[playerid] ++;
}
else if(PlayerSpam[playerid] >= MAX_SPAM)//If the player spam is bigger than or equal to the max spam allowed!
{
new TalkString[120],string[120];
//WE FORMAT THE STRING
format(string,sizeof(string),"[ANTI-CHEAT] Player: %s ID: %d Has been Kicked Reason: SPAM",GetName(playerid),playerid);
//THEN WE SEND IT TO EVERYONE!
SendClientMessageToAll(-1,string);
format(TalkString,sizeof(TalkString),"You Have Been Kicked By Anti Cheat!\nReason:SPAM");
//we are going to show the dialog to the player
ShowPlayerDialog(playerid,DIALOG_ANTI,DIALOG_STYLE_MSGBOX,"Anti Cheat!",TalkString,"Okay","");
//we set the playerspam to 0 so it wont mix with other players when they connect!
PlayerSpam[playerid] = 0;
//we kill the timer!
KillTimer(SpamTimer[playerid]);
//Then we kick the player!
Kick(playerid);
}
so good! now we did the main thing in The OnPlayerText! now let's do the Timer!
so at any place in your gm but after the #Include not before it:
pawn Код:
//we forward the DecreaseSpam Timer!
forward DecreaseSpam(playerid);
//then we use public to do the main function in it!
public DecreaseSpam(playerid)
{
//we decrease the PlayerSpam by 1 !
PlayerSpam[playerid] --;
//Then we return 1!
return 1;
}
so now we did the Main function and everything is ready!
Now It's time to make an easier function it's anti adv! now first we need to put a stock
that defines if the player has adv or not! so at any place in your GM but make sure it's after the includes not before it:

pawn Код:
stock CheckAdv(word[])
{
    if(strlen(word)>22) return 0;
    if(strfind(word,".", true)==-1) return 0;

    new ip[5][256],index;
    ip[0] = strtok(word,index,'.');
    ip[1] = strtok(word,index,'.');
    ip[2] = strtok(word,index,'.');
    if(strfind(word,":",true)>0){
        ip[3] = strtok(word,index,':');
        if(strfind(word,",",true)>0) ip[4] = strtok(word,index,',');else ip[4] = strtok(word,index);
    } else {
        if(strfind(word,",",true)==strlen(word)) ip[3] = strtok(word,index,',');else ip[3] = strtok(word,index);
        valstr(ip[4],0);
    }
    if(!IsNumeric(ip[0])||!IsNumeric(ip[1])||!IsNumeric(ip[2])||!IsNumeric(ip[3])||!IsNumeric(ip[4])
        ||!strlen(ip[0])||!strlen(ip[1])||!strlen(ip[2])||!strlen(ip[3])||!strlen(ip[4])
        ||(strval(ip[0])==192&&strval(ip[1])==168)
        ||(strval(ip[0])==172&&strval(ip[1])>=16&&strval(ip[1])<=31)
        ||strval(ip[0])==10||(strval(ip[0])==127&&strval(ip[1])==0&&strval(ip[2])==0&&strval(ip[3])==1)) return 0;
    return 1;
}
now OnPlayerText:
pawn Код:
new word[150],Index;while(Index < strlen(text)) {
        word = strtok(text,Index);
        if(CheckAdv(word)==1){//If there is a word of the words in the CheckAdv stock!
            //If the player text contained . and numbers!
            new i=strfind(text,word),j=i+strlen(word)-1; text[i++]='[';
            while(i<j) {text[i]='•';i++;}
            text[j]=']';
            Kick(playerid);//This one will kick the player for sure!
            new string2[128];//WE MAKE A string called string2
            //First we format it!
            format(string2, sizeof(string2), "[ANTI-CHEAT] Player: %s ID: %d Has been Kicked Reason: SPAM",GetName(playerid),playerid);
            SendClientMessageToAll(-1, string2);//we send it then!

        }
    }
now let's define strtok and numeric:
at any place in your GM:
pawn Код:
stock strtok(const string[], &index,seperator=' ')
{
        new length = strlen(string);
        new offset = index;
        new result[128];
        while ((index < length) && (string[index] != seperator) && ((index - offset) < (sizeof(result) - 1)))
        {
                result[index - offset] = string[index];
                index++;
        }

        result[index - offset] = EOS;
        if ((index < length) && (string[index] == seperator))
        {
                index++;
        }
        return result;
}
pawn Код:
IsNumeric(const string[])
{
    for (new i = 0, j = strlen(string); i < j; i++)
    {
        if (string[i] > '9' || string[i] < '0') return 0;
    }
    return 1;
}
Alright Then! now we did anti ADV and anti SPAM! now it's time to take ourselves to an important hack!
HH! HH means Health Hack and it's one of the important hacks that every server have to protect players from it!
Alright then At this point we will use OnPlayerTakeDamage!
but first at the top of the script:
pawn Код:
new GotHit[MAX_PLAYERS];//the times that the player got hit by the play!
new Float:OldHealth[MAX_PLAYERS];//this one will detect the players Old Health!
new Float:NewHealth[MAX_PLAYERS];//This one will detect the players new Health !
#define DETECT_AFTER 6 //PLEASE DON'T MODIFY IT OR IT MAY BAN INNOCENT PLAYERS!
Alright then Now OnPlayerTakeDamage We need to put:
pawn Код:
GotHit[playerid] ++ ; //we increase the Time that the player got HIT!
if(GotHit[playerid] >= 3 && GotHit[playerid] < 6)//IF THE PLAYER GOT HEALTH 3 TIMES OR MORE BUT LESS THAN 6!
{
GetPlayerHealth(playerid,OldHealth[playerid]);//WE GET THE PLAYER HEALTH!
}
if(GotHit[playerid] >= DETECT_AFTER)//IF THE PLAYER GOT HIT FOR 6 TIMES OR MORE!
{
GetPlayerHealth(playerid,NewHealth[playerid]);
if(OldHealth[playerid] == NewHealth[playerid])//IF THE PLAYER OLD HEALTH IS THE SAME AS THE NEW!
{
new string22[120];//we are going to define a new string because we are going to store things there
//here we are going to format the string by getting the player name and ID and putting it there:
format(string22,sizeof(string22),"[ANTI - CHEAT] Player: %s ID: %d has been Kicked by anti cheat! Reason: HH!",GetName(playerid),playerid);
SendClientMessageToAll(-1,string22);//then we are going to send the message to everyone in game
ShowPlayerDialog(playerid,DIALOG_ANTI,DIALOG_STYLE_MSGBOX,"Anti Cheat!","You Have Been Kicked By Anti Cheat!\nReason:Health Hack!","Okay","");//we are going to show the dialog to the player
Kick(playerid);//we are going to kick the player
}
}
Congratz! You have made your own Anti HH,Anti SPAM, And Anti ADV! Now the players can play safe!
Without worrying if there is no admins Online, Keep On following the tutorial for more anti hacks!
Incoming : Ammo Hack,Weapon Hack,Air Break!
Incoming [Not needed to add it]: saving logs! [it will save the logs when a player get kicked or banned by anti cheat and put it in a file!]
So I think that it's enough for now to protect the player , I am going to update this tutorial soon and I will explain more soon!
Reply
#2

Awesome tutorial !! keep it up :P
Reply
#3

sscanf by ****** not y_ini
And it's been explained by many people why OnPlayerUpdate shouldn't be used for various purposes

Other than that, good tutorial
Reply
#4

Quote:
Originally Posted by DavidBilla
Посмотреть сообщение
sscanf by ****** not y_ini
And it's been explained by many people why OnPlayerUpdate shouldn't be used for various purposes

Other than that, good tutorial
hahaha good point, updated to ****** not y_ini
and thanks for commenting
Reply
#5

Great.
Reply
#6

Fix indentation, learn about 2 dimensional arrays.
Reply
#7

Quote:
Originally Posted by thefatshizms
Посмотреть сообщение
Fix indentation, learn about 2 dimensional arrays.
hmm if you compiled I am sure you wouldn't have any indentation warnings

anyways I fixed some bugs in the tutorial it should work more fine now..
Reply
#8

Nice tutorial ! Good job.
Reply
#9

Quote:
Originally Posted by xWarrior
Посмотреть сообщение
Nice tutorial ! Good job.
Thanks a lot!

Quote:
Originally Posted by Kinglee
Посмотреть сообщение
Great.
Hahaha thank you
Reply
#10

Nice tutorial Keep it up
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)