Gamemode isn't saving stats (****** & Kush's tutorial)
#1

Hey,

I am using the latest SA-MP (DL version); and I can't get the system to write the stats in the text file that I created a folder for..

Here is my script:

Код:
#include <a_samp>
#include <YSI\y_ini>

main( ) { }

//======= DEFINITIONS =========

//Registration System
#define PATH "/Accounts/%s.ini"

#define DIALOG_REGISTER 1
#define DIALOG_LOGIN 2
#define DIALOG_SUCCESS_1 3
#define DIALOG_SUCCESS_2 4

#define COL_WHITE "{FFFFFF}"
#define COL_RED "{F81414}"
#define COL_GREEN "{00FF22}"
#define COL_LIGHTBLUE "{00CED1}"
//---------------------------

//====== END OF DEFINITIONS =========

//========= ENUMS =============

//Registration System
enum pInfo
{
    pPass,
    pCash,
    pAdmin,
    pKills,
    pDeaths
}
new PlayerInfo[MAX_PLAYERS][pInfo];
//--------------------------------------

//======== END OF ENUMS =========


//======== FUNCTIONS ========================
//Registration System
forward LoadUser_data(playerid,name[],value[]);
public LoadUser_data(playerid,name[],value[])
{
	INI_Int("Password",PlayerInfo[playerid][pPass]);
	INI_Int("Cash",PlayerInfo[playerid][pCash]);
	INI_Int("Admin",PlayerInfo[playerid][pAdmin]);
	INI_Int("Kills",PlayerInfo[playerid][pKills]);
    INI_Int("Deaths",PlayerInfo[playerid][pDeaths]);
 	return 1;
}
//---------------------------------
//========== END OF FUNCTIONS ===============

//========== STOCKS ==============
//REGISTRATION SYSTEM
stock UserPath(playerid)
{
	new string[128],playername[MAX_PLAYER_NAME];
	GetPlayerName(playerid,playername,sizeof(playername));
	format(string,sizeof(string),PATH,playername);
	return string;
}
/*Credits to Dracoblue*/
stock udb_hash(buf[]) {
	new length=strlen(buf);
    new s1 = 1;
    new s2 = 0;
    new n;
    for (n=0; n<length; n++)
    {
       s1 = (s1 + buf[n]) % 65521;
       s2 = (s2 + s1)     % 65521;
    }
    return (s2 << 16) + s1;
}
//--------------------------------------
//============= END OF STOCKS =================


public OnGameModeInit()
{
	// Don't use these lines if it's a filterscript
	SetGameModeText("Life of Fort Carson");
	AddPlayerClass(76,-177.3635,1110.9661,19.7422,132.1115,0,0,0,0,0,0); // FORTCARSONSPAWN
	return 1;
}

public OnGameModeExit()
{
	return 1;
}

public OnPlayerRequestClass(playerid, classid)
{
	SetPlayerPos(playerid, -199.6335, 1104.6046, 19.5938);
	SetPlayerCameraPos(playerid, -193.4531, 1101.3687, 19.5938);
	SetPlayerCameraLookAt(playerid, -196.6335, 1103.3114, 19.5938);
	return 1;
}

public OnPlayerConnect(playerid)
{
	if(fexist(UserPath(playerid)))
	{
		new pname[MAX_PLAYER_NAME], string[22 + MAX_PLAYER_NAME];
	    GetPlayerName(playerid, pname, sizeof(pname));
	    format(string, sizeof(string), "%s has joined the server", pname);
	    SendClientMessageToAll(0xAAAAAAAA, string);
	    
		INI_ParseFile(UserPath(playerid), "LoadUser_%s", .bExtra = true, .extra = playerid);
  		ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT,""COL_WHITE"Login",""COL_WHITE"Type your password below to login.","Login","Quit");
	}
	else
	{
 		ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT,""COL_WHITE"Registering...",""COL_WHITE"Type your password below to register a new account.","Register","Quit");
	}
	return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
	new INI:File = INI_Open(UserPath(playerid));
	INI_SetTag(File,"data");
	INI_WriteInt(File,"Cash",GetPlayerMoney(playerid));
	INI_WriteInt(File,"Admin",PlayerInfo[playerid][pAdmin]);
	INI_WriteInt(File,"Kills",PlayerInfo[playerid][pKills]);
	INI_WriteInt(File,"Deaths",PlayerInfo[playerid][pDeaths]);
	INI_Close(File);
	
 	new pname[MAX_PLAYER_NAME], string[39 + MAX_PLAYER_NAME];
    GetPlayerName(playerid, pname, sizeof(pname));
    switch(reason)
    {
        case 0: format(string, sizeof(string), "%s has left the server. (Lost Connection)", pname);
        case 1: format(string, sizeof(string), "%s has left the server. (Leaving)", pname);
        case 2: format(string, sizeof(string), "%s has left the server. (Kicked)", pname);
    }
    SendClientMessageToAll(0xAAAAAAAA, string);
    
	return 1;
}

public OnPlayerSpawn(playerid)
{
	return 1;
}

public OnPlayerDeath(playerid, killerid, reason)
{
	PlayerInfo[killerid][pKills]++;
	PlayerInfo[playerid][pDeaths]++;
	return 1;
}

public OnVehicleSpawn(vehicleid)
{
	return 1;
}

public OnVehicleDeath(vehicleid, killerid)
{
	return 1;
}

public OnPlayerText(playerid, text[])
{
	return 1;
}

public OnPlayerCommandText(playerid, cmdtext[])
{
	if (strcmp("/savemyshit", cmdtext, true, 10) == 0)
	{
		new INI:File = INI_Open(UserPath(playerid));
		INI_SetTag(File,"data");
		INI_WriteInt(File,"Cash",GetPlayerMoney(playerid));
		INI_WriteInt(File,"Admin",PlayerInfo[playerid][pAdmin]);
		INI_WriteInt(File,"Kills",PlayerInfo[playerid][pKills]);
		INI_WriteInt(File,"Deaths",PlayerInfo[playerid][pDeaths]);
		INI_Close(File);
		SendClientMessage(playerid, 0x00FF00FF, "SAVEMYSHIT WORKS!");
		return 1;
	}
	
	return 0;
}

public OnPlayerEnterVehicle(playerid, vehicleid, ispassenger)
{
	return 1;
}

public OnPlayerExitVehicle(playerid, vehicleid)
{
	return 1;
}

public OnPlayerStateChange(playerid, newstate, oldstate)
{
	return 1;
}

public OnPlayerEnterCheckpoint(playerid)
{
	return 1;
}

public OnPlayerLeaveCheckpoint(playerid)
{
	return 1;
}

public OnPlayerEnterRaceCheckpoint(playerid)
{
	return 1;
}

public OnPlayerLeaveRaceCheckpoint(playerid)
{
	return 1;
}

public OnRconCommand(cmd[])
{
	return 1;
}

public OnPlayerRequestSpawn(playerid)
{
	return 1;
}

public OnObjectMoved(objectid)
{
	return 1;
}

public OnPlayerObjectMoved(playerid, objectid)
{
	return 1;
}

public OnPlayerPickUpPickup(playerid, pickupid)
{
	return 1;
}

public OnVehicleMod(playerid, vehicleid, componentid)
{
	return 1;
}

public OnVehiclePaintjob(playerid, vehicleid, paintjobid)
{
	return 1;
}

public OnVehicleRespray(playerid, vehicleid, color1, color2)
{
	return 1;
}

public OnPlayerSelectedMenuRow(playerid, row)
{
	return 1;
}

public OnPlayerExitedMenu(playerid)
{
	return 1;
}

public OnPlayerInteriorChange(playerid, newinteriorid, oldinteriorid)
{
	return 1;
}

public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
	return 1;
}

public OnRconLoginAttempt(ip[], password[], success)
{
	return 1;
}

public OnPlayerUpdate(playerid)
{
	return 1;
}

public OnPlayerStreamIn(playerid, forplayerid)
{
	return 1;
}

public OnPlayerStreamOut(playerid, forplayerid)
{
	return 1;
}

public OnVehicleStreamIn(vehicleid, forplayerid)
{
	return 1;
}

public OnVehicleStreamOut(vehicleid, forplayerid)
{
	return 1;
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    switch( dialogid )
    {
        case DIALOG_REGISTER:
        {
            if (!response) return Kick(playerid);
            if(response)
            {
                if(!strlen(inputtext)) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, ""COL_WHITE"Registering...",""COL_RED"You have entered an invalid password.\n"COL_WHITE"Type your password below to register a new account.","Register","Quit");
                new INI:File = INI_Open(UserPath(playerid));
                INI_SetTag(File,"data");
                INI_WriteInt(File,"Password",udb_hash(inputtext));
                INI_WriteInt(File,"Cash",0);
                INI_WriteInt(File,"Admin",0);
                INI_WriteInt(File,"Kills",0);
                INI_WriteInt(File,"Deaths",0);
                INI_Close(File);
                
                SetSpawnInfo(playerid, 0, 0, -177.36, 1110.96, 19.74, 132.11, 0, 0, 0, 0, 0, 0);
                //SpawnPlayer(playerid);
                ShowPlayerDialog(playerid, DIALOG_SUCCESS_1, DIALOG_STYLE_MSGBOX,""COL_WHITE"Welcome to Fort Carson",""COL_GREEN"Thank you for registering your database","Ok","");
			}
        }

        case DIALOG_LOGIN:
        {
            if ( !response ) return Kick ( playerid );
            if( response )
            {
                if(udb_hash(inputtext) == PlayerInfo[playerid][pPass])
                {
                    INI_ParseFile(UserPath(playerid), "LoadUser_%s", .bExtra = true, .extra = playerid);
                    GivePlayerMoney(playerid, PlayerInfo[playerid][pCash]);
					ShowPlayerDialog(playerid, DIALOG_SUCCESS_2, DIALOG_STYLE_MSGBOX,""COL_WHITE"Success!",""COL_GREEN"You have successfully logged in!","Ok","");
                }
                else
                {
                    ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT,""COL_WHITE"Login",""COL_RED"You have entered an incorrect password.\n"COL_WHITE"Type your password below to login.","Login","Quit");
                }
                return 1;
            }
        }
    }
    return 1;
}

public OnPlayerClickPlayer(playerid, clickedplayerid, source)
{
	return 1;
}
I even tried to make a command that forces the INI file to open and save, but it didn't work either.

Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
	if (strcmp("/savemyshit", cmdtext, true, 10) == 0)
	{
		new INI:File = INI_Open(UserPath(playerid));
		INI_SetTag(File,"data");
		INI_WriteInt(File,"Cash",GetPlayerMoney(playerid));
		INI_WriteInt(File,"Admin",PlayerInfo[playerid][pAdmin]);
		INI_WriteInt(File,"Kills",PlayerInfo[playerid][pKills]);
		INI_WriteInt(File,"Deaths",PlayerInfo[playerid][pDeaths]);
		INI_Close(File);
		SendClientMessage(playerid, 0x00FF00FF, "SAVEMYSHIT WORKS!");
		return 1;
	}
	
	return 0;
}
Reply
#2

Quote:
Originally Posted by Logic_
Посмотреть сообщение
This question has been asked countless amounts of time. Using Dini is a mistake since it's very poorly slow and was made just to ease out to work with files, but later we got to see SQLite implementation and MySQL plugins in SA-MP.

Many people go forward to learn different saving systems rather than SQL because they think it's hard or useless, whereas SQL is a different language. It's not something that you'll just use in your SA-MP modifications, but also when you work with web development, and other projects.

SQL provides database relations and so much features, that it's something that you should use as a saving system rather than other INI/ file based solutions that are not just slower, but also come up with bugs and other issues. For example, if you need help with a INI file, many people would just give their guesses but if you get stuck with SQL, you will not just find SA-MP forum to help you with that, but also different websites and communities.

Also, there's no fast way to convert anything to a different saving system, take your time and do your changes slowly since you're new to it. Put your time in learning it and adapting your script to it and to be just dependent of it.

SQLite is a built-in native implementation in SA-MP server and it doesn't require a SQL server to store the database, it saves it in scriptfiles folder. Whereas MySQL requires use of external plugins and is way faster than SQLite, for it's own reasons. MySQL allows you to show your data on your websites incase if you want to have a UCP or something similar. SQLite also provides this feature but your server and website should be on one machine.

SQLite in my opinion is an overkill for SA-MP. So you should just stick to it if you don't want to go for MySQL.

I've built lots of Call of Duty TDM scripts, some roleplay and I've sticked to SQLite for most of them since they are just enough and you won't need MySQL unless you want your project to be Hi-Fi.
Once you've read this, move forward to modifying your script to SQLite or MySQL. If you're interested to convert your script into SQLite than continue reading else, stop.

1. First part: Making database stuff
Modify your PATH definition to your database path.
PHP код:
#define PATH "/Accounts/%s.ini" 
to
PHP код:
#define PATH "[database name].db 
replace [database name] with anything you like, in this case, I'll be using database.db.

Once that's done, create a global variable at the top of the script, for example:
PHP код:
new DBgSQL
You can name your variable anything you like, in this case, I've used gSQL. DB is a tag assigned to variable called gSQL;

Now, moving towards OnGameModeInit, make a database connection here:
PHP код:
public OnGameModeInit() {
    if((
gSQL db_open(PATH) == DB0) { // Opens a database connection with the path specified and assigns the connection ID to the variable "gSQL", then we compare the connection ID with ID 0, if both matches means that the database connection wasn't successful
        // database failed creating! you might want to close your server or lock it
    
}
    else {
        
// successful! now you can create a table! that table mentioned below comes here!!
    
}

A table is defined as:
Quote:

a table is a set of data elements (values) using a model of vertical columns (identifiable by name) and horizontal rows, the cell being the unit where a row and column intersect. A table has a specified number of columns, but can have any number of rows.

Now I'll create a table called Users and all the player accounts will be saved in this table as rows (or entries!)
PHP код:
db_query(gSQL"CREATE TABLE IF NOT EXISTS `Users` (`userid` INTEGER PRIMARY KEY AUTOINCREMENT, `username` VARCHAR(24) COLLATE NOCASE, `password` VARCHAR(65), `admin` INTEGER DEFAULT 0)"); 
Here userid, username and so on are fields/ columns! Integer means numbers if you're not unaware and VARCHAR is same as string but with defined size/ space. COLLATE NOCASE is a SQL keyword that you'll need to research yourself a little bit!

Now under OnGameModeExit, we'll close the database connection by using db_close. So your code will look like:
PHP код:
public OnGameModeExit() {
    
db_close(gSQL);

Now You've successfully created the database and a table, now you've to do the login/ register system.

2. Register/ Login system
Now your OnPlayerConnect will be modified:
PHP код:
public OnPlayerConnect(playerid) {
    new 
EMPTY_PINFO[pInfo];
    
PlayerInfo[playerid] = EMPTY_PINFO// We cleaned the PlayerInfo array
    
new query[128], name[MAX_PLAYER_NAME], DBResultresult;
    
GetPlayerName(playeridnamesizeof name); // fetched player name
    
format(querysizeof query"%s has joined the server"name);
    
SendClientMessageToAll(-1query);
    
format(querysizeof query"SELECT COUNT(*) FROM `Users` WHERE `username` = '%q'"name); // we ran a query to select the number of accounts registered with player's name.
    
result db_query(gSQLquery); // execute the query and save the result in the variable
    
if(db_num_rows(result)) { // this means that rows/ entries with that name are found
          
ShowPlayerDialog(playeridDIALOG_LOGINDIALOG_STYLE_INPUT,""COL_WHITE"Login",""COL_WHITE"Type your password below to login.","Login","Quit");
    }
    else { 
// not found any entries/ rows with that name.
         
ShowPlayerDialog(playeridDIALOG_REGISTERDIALOG_STYLE_INPUT,""COL_WHITE"Registering...",""COL_WHITE"Type your password below to register a new account.","Register","Quit");
    }
    
db_free_result(result); // free the result to avoid memory leaks.
    
return 1;

Now, I'm going to make two sample functions for you WHICH YOU'LL need to modify to your needs:
PHP код:
LoginPlayer(playerid) {
    new 
query[128], name[MAX_PLAYER_NAME], DBResultresult;
    
GetPlayerName(playeridnamesizeof name);
    
format(querysizeof query"SELECT * FROM `Users` WHERE `username` = '%q'"name); // Select everything from table called Users where username is equal to player-name
    
result db_query(gSQLquery);
    if (
db_num_rows(result)) {
        
PlayerInfo[playerid][UserKey] = db_get_field_assoc_int(result"userid");
        
PlayerInfo[playerid][UserAdmin] = db_get_field_assoc_int(result"admin");
        
db_get_field_assoc(result"password"PlayerInfo[playerid][UserPassword], 65);
        
// other stats... The fields must be present in the table too, otherwise they are not going to load!
    
}
    
db_free_result(result);
    return 
1;

PHP код:
RegisterPlayer(playeridpassword[]) {
    new 
query[128], name[MAX_PLAYER_NAME];
    
GetPlayerName(playeridnamesizeof name);
    
format(querysizeof query"INSERT INTO `Users` (`username`, `password`) VALUES('%q', '%q')"namepassword); // Insert into table Users with data for username and password
    
db_query(gSQLquery);
    return 
1;

Reply
#3

you can use mysql or sqlite and for solution here you go

Код:
public OnPlayerConnect(playerid)
{
	if(fexist(UserPath(playerid)))
	{
		new pname[MAX_PLAYER_NAME], string[22 + MAX_PLAYER_NAME];
	    GetPlayerName(playerid, pname, sizeof(pname));
	    format(string, sizeof(string), "%s has joined the server", pname);
	    SendClientMessageToAll(0xAAAAAAAA, string);
	    
		INI_ParseFile(UserPath(playerid), "LoadUser_data", .bExtra = true, .extra = playerid);
  		ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT,""COL_WHITE"Login",""COL_WHITE"Type your password below to login.","Login","Quit");
	}
	else
	{
 		ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT,""COL_WHITE"Registering...",""COL_WHITE"Type your password below to register a new account.","Register","Quit");
	}
	return 1;
}
replace this with your one
Код:
//Edited
LoadUser_%s
to
LoadUser_data
Reply
#4

Thank you so much guys! I will look into learning SQLite and will be back to your helpful replies.
I am open to learning new languages ^^
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)