Code:
// includes, duh...
#include < amxmodx >
#include < csx >
#include < achievement_api >
// declaring the max client size
const MaxClients = 32;
// max steamid characters
const MaxSteamIdChars = 35;
// random number for the set_task
const TaskIdDelayConnect = 3799;
// to make it easier to retrieve the achievement data, we make an enumeration; making it a "structure"
enum _:AchievementDataStruct
{
_Name[ MaxClients ], // the name of the achievement
_Description[ 256 ], // the description of the achievement (cannot exceed 255 chars - limit set in api)
_Save_Name[ MaxClients ], // the save key of the achievement
_Max_Value // and finally the max value (also referred to as objective value in other achievement plugins)
};
// an array built from the struct
new const AchievementInfo[ AchievementDataStruct ] =
{
"Grenade Kills", // the name of the achievement
"Kill an enemy with a Grenade 50 times", // the description of the achievement (cannot exceed 255 chars - limit set in api)
"progress_grenade", // the save key of the achievement
50 // and finally the max value (also referred to as objective value in other achievement plugins)
};
// create a variable
new AchievementPointer;
// this variable will hold the unique index that the achievement has in the API, allowing you to use it to retrieve data
// variable to hold the steamid of a client
// 33 cells (for the 32 users) and 35 cells (for the steamid)
// const MaxClients = 32;
// const MaxSteamIdChars = 35;
new SteamId[ MaxClients + 1 ][ MaxSteamIdChars ];
// our objective counter, will hold the current kills of a client
// 33 cells (for all the 32 users)
new GrenadeKills[ MaxClients + 1 ];
// variable holding the max players (not max slots)
new MaxPlayers;
public plugin_init( ) // self explanatory
{
// register plugin
register_plugin( "Achievement API: Grenade Kills", "0.0.1", "Xellath" );
// register achievement to api
// in the order: Achievement Name, Description, Save Key and Max Value
AchievementPointer = RegisterAchievement( AchievementInfo[ _Name ], AchievementInfo[ _Description ], AchievementInfo[ _Save_Name ], AchievementInfo[ _Max_Value ] );
// will return index of achievement (stored in AchievementPointer)
// assign max players (not max slots)
MaxPlayers = get_maxplayers( );
// the achievement is now registered to the API, lets start with the grenade kill thingy
}
public client_connect( Client ) // called when client connects
{
// set a 10 sec task to check if user has completed or has data for the achievement
set_task( 10.0, "TaskDelayConnect", Client + TaskIdDelayConnect );
}
public TaskDelayConnect( TaskId )
{
// our client id (Client) = (TaskId - TaskIdDelayConnect (3799))
new Client = TaskId - TaskIdDelayConnect;
// get steamid of client
get_user_authid( Client, SteamId[ Client ], charsmax( SteamId ) );
// check if our client has objective data
GrenadeKills[ Client ] = GetAchievementData( SteamId[ Client ] /* our key */, AchievementInfo[ _Save_Name ] /* save name for achievement (declared in the array) */ );
// check if client already completed achievement
if( GetClientAchievementStatus( AchievementPointer, GrenadeKills[ Client ] ) == _In_Progress )
{
// achievement not completed
// save objective data to clients steamid
SetAchievementData( SteamId[ Client ] /* our key */, AchievementInfo[ _Save_Name ] /* save name for achievement */, GrenadeKills[ Client ] /* data */ );
}
else //if( GetClientAchievementStatus( AchievementPointer, Connections[ Client ] ) == _Unlocked )
{
// client has completed achievement already
// send completed to api, but don't announce (or else every client would get all achievements everytime the connect)
ClientAchievementCompleted( Client, AchievementPointer, .Announce = false );
}
// remove task
remove_task( Client + TaskIdDelayConnect );
}
public client_disconnect( Client )
{
// reset variable in case played indexes are magically switched and another client gets another set of connections
GrenadeKills[ Client ] = 0;
}
public client_death( Killer, Victim, WeaponIndex, Hitplace, TeamKill ) // called when a client dies
{
// check whether victim and killer are actual players (index above or equal 1 but lower or equal to 32)
if( 1 <= Victim <= MaxPlayers
&& 1 <= Killer <= MaxPlayers )
{
// victim did not kill himself
if( Victim != Killer )
{
// was the weapon a hegrenade?
if( WeaponIndex == CSW_HEGRENADE )
{
// yes it was
// check if client has unlocked the achievement
if( GetClientAchievementStatus( AchievementPointer, GrenadeKills[ Killer ] ) == _In_Progress )
{
// increment the objective value
GrenadeKills[ Killer ]++;
// save data
SetAchievementData( SteamId[ Killer ] /* our key */, AchievementInfo[ _Save_Name ] /* save name for achievement */, GrenadeKills[ Killer ] /* data */ );
// check if client just unlocked the achievement
if( GetClientAchievementStatus( AchievementPointer, GrenadeKills[ Killer ] ) == _In_Progress )
{
// client unlocked the achievement
// send completed to api, and announce
ClientAchievementCompleted( Killer, AchievementPointer, .Announce = true ); // true is default, but just to clarify
// the forward below is now called, so to award extra stuff, do something in the forward
}
}
}
}
}
}
public Forward_ClientEarnedAchievement( const AchiPointer, const Client ) // called when client earned the achievement
{
if( AchiPointer == AchievementPointer )
{
// this forward can be used to reward people stuff
// perhaps a model or just something extra (like ie. cash from cashmod, pointsystem etc.)
}
}
PHP Code:
<?php
// multi-dimensional array holding info for achievements
$data = array
(
0=>array
(
"1337", // achievement name
"Be online at 13:37", // description
1 // objective value (value set at completion)
),
1=>array
(
"Addict",
"Connect 500 times",
500
)
);
// mysql initzializing variables
$hostname = "localhost";
$username = "root";
$password = "pass";
$database = "achievement_api";
// connect to mysql
$connection = mysql_connect( $hostname, $username, $password );
if( !$connection )
{
// could not connect; throw error
die( 'Could not connect: ' . mysql_error( ) );
}
// check if steamid was entered
$steamid = $_GET['steamid'];
if( !$steamid )
{
// no steamid; throw error
die( 'No steamid entered!' );
}
// html body / style
echo "<html>";
echo "<style>";
echo "body{margin:0;padding:0;font-family:Tahoma,Helvetica,Arial,sans-serif;}table,tr,td{align:center;color:#222;background:#fff;margin:1;padding:1;border:solid #eee 1px;}";
echo "</style>";
echo "<body>";
// table (for the sake of simplicity)
echo "<table width=600>";
echo "<tr><td><b>Achievement Name</b></td><td><b>Description</b></td><td><b>Earned</b></td></tr>";
// select database in sql
mysql_select_db( $database, $connection );
// make the query
$query = "SELECT `data`, `key2` FROM `achievement_api_ex` WHERE `key1` = '$steamid';";
// send query
$result = mysql_query( $query, $connection );
// check if query picked up any data
if( !$result )
{
// no data found
die( 'No data found!' );
}
// achievement counter
$achievement = 0;
// achievements earned
$achievements = 0;
// fetch data from query
while( $row = mysql_fetch_array( $result ) )
{
// convert data to an int
$number = (int)$row['data'];
// check if data is more or equal to the max value (assigned in multi-dimensional array above)
$earned = ( ( $number >= $data[$achievement][2] ) ? "Yes" : "No" ); // "Yes" if more or equal, otherwise "No"
// check if client has earned
if( $earned == "Yes" )
{
$achievements++;
}
// print the data into the table
echo "<tr><td>". $data[$achievement][0] ."</td><td>" . $data[$achievement][1] . "</td><td>" . $earned . "</td></tr>";
// increment the achievement variable
$achievement++;
}
// total achievements earned
echo "Achievements Earned: " . $achievements ."<br>";
echo "Max Achievements: " . $achievement . "";
// close
echo "</table>";
echo "</body>";
?>
And a HTML file for you to enter the steamid: