В этом уроке мы будем использовать SQLite для сохранения статистики игроков.
Прежде всего мы добавляем нужные enum для нашей статистики:
Code: Select all
enum USER_DATA
{
USER_ID, //здесь мы сохраняем ID учетной записи в базе
USER_NAME[MAX_PLAYER_NAME], //то же самое относится и к имени
USER_PASSWORD[129], //сохранить пароль
USER_HUNGER, //голод игроков
USER_THIRST, //и жажда
bool: USER_LOGGED_IN
};
new User[MAX_PLAYERS][USER_DATA];
new DB: Database;
Далее мы создаём остальную часть базы данных:
Code: Select all
public OnFilterScriptInit()
{
Database = db_open("server.db");
db_query(Database, "CREATE TABLE IF NOT EXISTS users (userid INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(24) COLLATE NOCASE, password VARCHAR(129), hunger INTEGER DEFAULT 0 NOT NULL, thirst INTEGER DEFAULT 0 NOT NULL)");
AddPlayerClass(1, 2528.9143,-1667.7504,15.1689,91.2860,0,0,0,0,0,0);
return 1;
}
public OnPlayerConnect(playerid)
{
for(new i; i < _: USER_DATA; ++i) User[playerid][USER_DATA: i] = 0;
GetPlayerName(playerid, User[playerid][USER_NAME], MAX_PLAYER_NAME);
new Query[71], DBResult: Result;
format(Query, sizeof(Query), "SELECT password FROM users WHERE username = '%s' LIMIT 0, 1", DB_Escape(User[playerid][USER_NAME]));
Result = db_query(Database, Query);
if(db_num_rows(Result))
{
db_get_field_assoc(Result, "password", User[playerid][USER_PASSWORD], 129);
ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Login pannel", "Login pannel", "Please login to play", "Login", "Exit");
}
else ShowPlayerDialog(playerid, 1, DIALOG_STYLE_PASSWORD, "Register pannel", "Please register to play", "Register", "Exit");
db_free_result(Result);
return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
if(User[playerid][USER_LOGGED_IN] == true)
{
new Query[128];
format(Query, sizeof(Query), "UPDATE users SET hunger= %s, thirst = %s WHERE username = '%s'", User[playerid][USER_HUNGER], User[playerid][USER_THIRST], DB_Escape(User[playerid][USER_NAME]));
db_query(Database, Query);
}
for(new i; i < _: USER_DATA; ++i) User[playerid][USER_DATA: i] = 0;
return 1;
}
public OnPlayerSpawn(playerid)
{
return 1;
}
public OnPlayerDeath(playerid, killerid, reason)
{
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
if(dialogid == 0)
{
if(response)
{
if(!inputtext[0]) return ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Login pannel", "Please login to play", "Login", "Exit");
new buf[129];
WP_Hash(buf, 129, inputtext);
if(!strcmp(buf, User[playerid][USER_PASSWORD], false))
{
new Query[75], DBResult: Result;
format(Query, sizeof(Query), "SELECT * FROM users WHERE username = '%s' LIMIT 0, 1", DB_Escape(User[playerid][USER_NAME]));
Result = db_query(Database, Query);
if(db_num_rows(Result))
{
db_get_field_assoc(Result, "userid", Query, 7);
User[playerid][USER_ID] = strval(Query);
db_get_field_assoc(Result, "hunger", Query, 3);
User[playerid][USER_HUNGER] = strval(Query);
db_get_field_assoc(Result, "thirst", Query, 3);
User[playerid][USER_THIRST] = strval(Query);
User[playerid][USER_LOGGED_IN] = true;
SendClientMessage(playerid, -1, "You have successfully logged in to your account!");
}
db_free_result(Result);
}
else
{
SendClientMessage(playerid, -1, "Incorrect password!");
ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Login pannel", "Please login to play", "Login", "Exit");
}
}
else Kick(playerid);
return 1;
}
if(dialogid == 1)
{
if(response)
{
if(!IsValidPassword(inputtext))
{
SendClientMessage(playerid, -1, "The password is invalid, Valid characters are: A-Z, a-z, 0-9");
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_PASSWORD, "Register pannel", "Please register to play", "Register", "Exit");
return 1;
}
if(strlen(inputtext) < 3 || strlen(inputtext) > 24)
{
SendClientMessage(playerid, -1, "The password is invalid, Its lenght should be 3-24 characters");
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_PASSWORD, ""COL_BLUE"SERVER NAME"COL_WHITE" Register pannel", "Please register to play", "Register", "Exit");
return 1;
}
new Query[208];
WP_Hash(User[playerid][USER_PASSWORD], 129, inputtext);
format(Query, sizeof(Query), "INSERT INTO users (username, password) VALUES ('%s', '%s')", DB_Escape(User[playerid][USER_NAME]), DB_Escape(User[playerid][USER_PASSWORD]));
db_query(Database, Query);
User[playerid][USER_LOGGED_IN] = true;
SendClientMessage(playerid, -1, "You have just registered to our server! You have been automatically logged in!");
}
else Kick(playerid);
return 1;
}
return 1;
}
stock DB_Escape(text[])
{
new ret[ 80 * 2 ], ch, i, j;
while((ch = text[i++]) && j < sizeof(ret))
{
if(ch == '\'')
{
if(j < sizeof(ret) - 2)
{
ret[j++] = '\'';
ret[j++] = '\'';
}
}
else if(j < sizeof(ret))
{
ret[j++] = ch;
}
else
{
j++;
}
}
ret[sizeof(ret) - 1] = '\0';
return ret;
}
stock IsValidPassword(const password[])
{
for(new i = 0; password[i] != EOS; ++i)
{
switch(password[i])
{
case '0'..'9', 'A'..'Z', 'a'..'z': continue;
default: return 0;
}
}
return 1;
}
Теперь у нас есть база данных, чтобы сохранить наш голод и жажду , и мы будем устанавливать статистику игрока, когда он впервые регистрирует на сервере:
Code: Select all
User[playerid][USER_LOGGED_IN] = true;
SendClientMessage(playerid, -1, "Вы только что зарегистрировались на нашем сервере и автоматически авторизованы!");
User[playerid][USER_HUNGER] == 100); //мы устанавливаем голод 100
User[playerid][USER_THIRST] == 100); //и жажду
Теперь, когда мы установили значения, мы можем начать делать функции, чтобы уменьшить эту статистику. Пример:
Code: Select all
//Вы должны это определить в верху скрипта (дефайн)
#define PRESSED(%0) \
(((newkeys & (%0)) == (%0)) && ((oldkeys & (%0)) != (%0)))
//каждый раз вы прыгаете вы потеряете немного энергии, что означает у получите больше голода и жажды
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if(PRESSED(KEY_JUMP))
{
User[playerid][USER_HUNGER] -= 5); //берем 5 из голода игрока
User[playerid][USER_THIRST] -= 7); //и 7 жажды
}
return 1;
}
Теперь, когда у нас есть снижение энергии (повышение голода и жажды). Мы должны сделать так, если голод или жажда становится слишком низко то игрок потеряет часть здоровья или отключить бег, пока не повысится энергия. Примерно это будет выглядеть так:
Code: Select all
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if(PRESSED(KEY_JUMP))
{
if(User[playerid][USER_HUNGER] <= 10 || User[playerid][USER_THIRST] <= 10)
{
SendClientMessage(playerid, -1, "Вам не хватает энергии, чтобы прыгать, поешьте и попейте");
new Float:X, Float:Y, Float:Z;
GetPlayerPos(playerid, x, y, z);
SetPlayerPos(playerid, x, y, z);
//быстрый способ отключить прыжки (не проверено)
}
else
{
//если игрок имеет больший голод и жажду (10)
User[playerid][USER_HUNGER] -= 5); //берем 5 голода
User[playerid][USER_THIRST] -= 7); //7 жажды
}
}
return 1;
}
Теперь нам понадобится способ чтобы увеличить энергию (уменьшить голод и жажду). Вы можете использовать это в вашем коде, где вы покупаете еду:
Code: Select all
//example
if(listitem == 0) //asuming you have a dialog and this is list item 0 which would be a burger or something
{
User[playerid][USER_HUNGER] += 20);
SendClientMessage(playerid, -1, "Вы съели гамбургер, +20 голод");
}
if(listitem == 1) //and this would be a soda or such
{
User[playerid][USER_THIRST] += 20);
SendClientMessage(playerid, -1, "Вы пили содовую, +20 жажду" );
}
Теперь мы будем делать команду /energy, чтобы проверить голод и жажду:
Code: Select all
CMD:energy(playerid,params[])
{
new hunger= User[playerid][USER_HUNGER];
new thirst= User[playerid][USER_THIRST];
new string[60],stats[60];
format(string, sizeof string, "Голод: %s\nЖажда: %s", hunger, thirst);
format(stats, sizeof stats, "%s", string);
ShowPlayerDialog(playerid,6,DIALOG_STYLE_MSGBOX,"Энергия",string,"Ok","");
return 1;
}
Вы можете сделать больше функций, таких как таймер каждые 10 минут, что бы уменьшать голод и жажду. И когда у вас мало энергии вы теряете часть здоровья и т.д.