This is more or less looking for different approaches and philosophies in programming here
How would you approach a system which stores & loads defined unlockables per player?
Assume we're using MySQL as our storage median and SourcePawn as our programming medium.
Examples?
How I would personally approach this?
MySQL Table schema as so:
Code:
CREATE TABLE IF NOT EXISTS player_achievements (
steam_id VARCHAR(32) NOT NULL,
achievement_id INT NOT NULL,
unlocked BOOLEAN NOT NULL,
PRIMARY KEY(steam_id, achievement_id)
);
Some mock code as so, leaving out the verbose mundane stuff:
PHP Code:
#include <sourcemod>
//Arbitrary Achievement Goals:
enum e_Achievements
{
Achievement_Point = 1, //Gain one point
Achievement_Die, //Die once
Achievement_Happy, //Become happy
}
bool g_Achievements[MAXPLAYERS + 1][e_Achievements];
Database g_Database;
public void OnPluginStart()
{
//Pretend connect database:
ConnectDatabaseStuff();
}
public void OnClientAuthorized(int client)
{
//Default to locked:
g_Achievements[client][e_Achievements] = false;
//Pretend to load preexisting achievments:
LoadAchievements(GetClientSerial(client));
}
/* Pretend to run the query:
* SELECT * FROM player_achievements WHERE steam_id = '%s';
*/
void LoadAchievements(int serial)
{
int client = GetClientFromSerial(serial);
//check stuff bla bla:
//skip lots of code...
int aCol, uQol;
results.FieldNameToNum("achievement_id", aCol);
results.FieldNameToNum("unlocked", uCol);
while(results.FetchRow())
{
//Get achievement id, "cast" as achievement:
e_Achievements achievement = view_as<e_Achievements>(results.FetchInt(aCol));
//Set unlocked status
g_Achievements[client][achievement] = view_as<bool>(results.FetchInt(uCol));
}
}
//Pretend our player did something to unlock an achievement...
void UnlockAchievement(int client)
{
if(!g_Achievements[client][Achievement_Die])
{
g_Achievements[client][Achievement_Die] = true;
char query[256]; Format(query, sizeof(query), "INSERT IGNORE INTO player_achievements (steam_id, achievement_id, unlocked) VALUES ('%s', %i, 1) ON DUPLICATE KEY UPDATE unlocked = 1;", steamid, view_as<int>(Achievement_Die));
g_Database.Query(PretendQueryHandler, query);
PrintToChat(client, "yay you died!!");
}
}
Thus leaving us with a simple solution of:
By default (in memory) you do not have X unlocked.
Once you unlock X, it is set to true and inserted into the database.
Y will always be locked until you unlock it just by the default nature of things.
X will be unlocked because you unlocked it and the database will load as such.