11.01.2014, 14:15
(
Last edited by Voxel; 11/01/2014 at 04:37 PM.
)
Simple Hunger/Thirst System
Tutorial by Voxel
Introduction
Hello and welcome to my new tutorial on how to make a hunger and thirst system. In this tutorial we
will be using SQLite to save the players stats, if you are not familiar with SQLite I reccomend taking a look
at my SQLite filterscript and the tutorial which is made by Konstatinos.
This tutorial will expect you to know the basics for pawn scripting.
Lets get going shall we?!
Tutorial
Setting up our database to save our stats
First of all we are going to need some enums for our stats
Next we will set up the rest of the database
Now that we have a database to save our hunger and thirst in we can begin the real tutorial!
Right so first we will set the player stats when he first registers to the server:
Now that we set the values correctly we can begin making the functions to decrease these stats
an example would be:
Now that we have something that decreases our hunger and thirst we need to detect if the hunger or thirst is getting to low and the player will loose some health and maybe you could
also disable his sprinting since you would have no energy for that. So it would look like this:
Now we will need a way to eat and drink to increase our hunger and thirst, you can use this at your
code where you buy food and such:
Allright so now we will make a /energy command to check how hungry and thirsty you are.
Thats about it, you can make more features like a timer every 10 minutes that decreases the hunger and thirst
and when you get low on energy you loose some health etc.
I hope you learned something and have fun!
Tutorial by Voxel
Introduction
Hello and welcome to my new tutorial on how to make a hunger and thirst system. In this tutorial we
will be using SQLite to save the players stats, if you are not familiar with SQLite I reccomend taking a look
at my SQLite filterscript and the tutorial which is made by Konstatinos.
This tutorial will expect you to know the basics for pawn scripting.
Lets get going shall we?!
Tutorial
Setting up our database to save our stats
First of all we are going to need some enums for our stats
pawn Code:
enum USER_DATA
{
USER_ID, //here we save the account id in the database
USER_NAME[MAX_PLAYER_NAME], //same goes for the name
USER_PASSWORD[129], //and we save the password
USER_HUNGER, //here we save the players hunger
USER_THIRST, //and the thirst aswell
bool: USER_LOGGED_IN
};
new User[MAX_PLAYERS][USER_DATA];
new DB: Database;
pawn Code:
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;
}
Right so first we will set the player stats when he first registers to the server:
pawn Code:
//this is our register part of the script over at the dialogs
User[playerid][USER_LOGGED_IN] = true;
SendClientMessage(playerid, -1, "You have just registered to our server! You have been automatically logged in!");
User[playerid][USER_HUNGER] == 100); //we set the hunger to 100
User[playerid][USER_THIRST] == 100); //and the thirst to 100
an example would be:
pawn Code:
//you need this define on top of your script to detect keys properly
#define PRESSED(%0) \
(((newkeys & (%0)) == (%0)) && ((oldkeys & (%0)) != (%0)))
//everytime you jump you will loose a bit of energy which means u will get more hungry and thirsty
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if(PRESSED(KEY_JUMP))
{
User[playerid][USER_HUNGER] -= 5); //we take 5 of the players hunger
User[playerid][USER_THIRST] -= 7); //and 7 of the thirst
}
return 1;
}
also disable his sprinting since you would have no energy for that. So it would look like this:
pawn Code:
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if(PRESSED(KEY_JUMP))
{
if(User[playerid][USER_HUNGER] <= 10 || User[playerid][USER_THIRST] <= 10)
{
SendClientMessage(playerid, -1, "You do not have enough energy to jump, try eating and drinking"); //send a message informing the player his energy is to low
new Float:X, Float:Y, Float:Z;
GetPlayerPos(playerid, x, y, z);
SetPlayerPos(playerid, x, y, z);
//just a quick way to disable the jumping (not tested)
}
else
{
//if the player have larger hunger and thirst then 10
User[playerid][USER_HUNGER] -= 5); //we take 5 of the players hunger
User[playerid][USER_THIRST] -= 7); //and 7 of the thirst
}
}
return 1;
}
code where you buy food and such:
pawn Code:
//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); //we give the player +20 hunger
SendClientMessage(playerid, -1, "You ate a burger, +20 hunger");
}
if(listitem == 1) //and this would be a soda or such
{
User[playerid][USER_THIRST] += 20); //we give the player +20 thirst
SendClientMessage(playerid, -1, "You drank a soda, +20 thirst");
}
pawn Code:
//Using ZCMD
CMD:energy(playerid,params[])
{
new hunger= User[playerid][USER_HUNGER]; //we make a variable to store our stats in
new thirst= User[playerid][USER_THIRST]; //same here
new string[60],stats[60];
format(string, sizeof string, "Hunger: %s\nThirst: %s", hunger, thirst); //we display the stats in our dialog
format(stats, sizeof stats, "%s", string);
ShowPlayerDialog(playerid,6,DIALOG_STYLE_MSGBOX,"Energy",string,"Ok","");
return 1;
}
and when you get low on energy you loose some health etc.
I hope you learned something and have fun!