Spoiler
/*
// Use this to create the table in MySQL
CREATE TABLE IF NOT EXISTS `pm_save` (
`SAVE_KEY` varchar(34) binary NOT NULL default '',
`XPS` varchar(255) binary NOT NULL default '',
`LAST_PLAY_DATE` timestamp(14) NOT NULL,
PRIMARY KEY (`SAVE_KEY`)
) TYPE=MyISAM COMMENT='PokeMod Saving Table';
// now it should work fine
//if using MySQL and are updating from v1.2.0 Beta J2 or lower, run these queries
ALTER TABLE `pm_save` ADD `LAST_PLAY_DATE` timestamp(14) NOT NULL;
ALTER TABLE `pm_save` MODIFY `XPS` varchar(255) binary NOT NULL default '';
//if using MySQL and are updating from v1.2.0 Beta K2 or lower, run this query
UPDATE `pm_save` SET `LAST_PLAY_DATE`=SYSDATE()
*/
// This makes sure theres no gaps in PlayersPoke
// Example:
// From: 5 390 0 0 10 200 16 1000
// To: 5 390 10 200 16 1000 0 0
public RefreshPoke(id)
{
if(Safari() || !id || !g_Connected[id])
return
new PlaceHolder[2][MAX_POKES]
new i, p = 0;
for(i = 0; i<MAX_ACTIVE_POKES; i++){
if( ValidPoke( PlayersPoke[id][i] ) ){
PlaceHolder[0][p] = PlayersPoke[id][i];
PlaceHolder[1][p] = PlayersXP[id][i];
p++;
}
}
for(i = p; i<MAX_ACTIVE_POKES; i++){
PlayersPoke[id][i] = 0;
PlayersXP[id][i] = 0;
}
p = MAX_ACTIVE_POKES;
for(i = MAX_ACTIVE_POKES; i<MAX_POKES; i++){
if( ValidPoke( PlayersPoke[id][i] ) ){
PlaceHolder[0][p] = PlayersPoke[id][i];
PlaceHolder[1][p] = PlayersXP[id][i];
p++;
}
}
for(i = p; i<MAX_POKES; i++){
PlayersPoke[id][i] = 0;
PlayersXP[id][i] = 0;
}
for(i = 0; i<MAX_POKES; i++){
PlayersPoke[id][i] = PlaceHolder[0][i];
PlayersXP[id][i] = PlaceHolder[1][i];
}
if(!SwitchPoke(id, Pokemon[id])){
for(i=0; i<MAX_ACTIVE_POKES; i++){
if(SwitchPoke(id, PlayersPoke[id][i]))
break;
}
}
}
///////////////////////////////////////////
// For MYSQL, find the database to use //
///////////////////////////////////////////
#if SAVE==SAVE_SQLX
public saving_init()
{
new host[64],user[32],pass[32],db[32]
get_ppcvar_string(pm_mysql_host,host,63)
get_ppcvar_string(pm_mysql_user,user,31)
get_ppcvar_string(pm_mysql_pass,pass,31)
get_ppcvar_string(pm_mysql_db,db,31)
register_pokeadmincmd("vault_to_sql","adminCopyVault", ADMIN_RCON,"- Copies vault XP to MySQL, should only be done once.")
// we tell the API that this is the information we want to connect to,
// just not yet. basically it's like storing it in global variables
SqlConnection = SQL_MakeDbTuple(host,user,pass,db)
if(!SqlConnection){
debugMessage( 0,0,"SQLx Connection Error. Check your cvars.")
return
}
else {
new data[2]
data[0] = 0
data[1] = 0
new sql[512]
copy(sql, 511, "CREATE TABLE IF NOT EXISTS `pm_save` ( `SAVE_KEY` varchar(34) binary NOT NULL default '', `XPS` varchar(255) binary NOT NULL default '', `LAST_PLAY_DATE` timestamp(14) NOT NULL, PRIMARY KEY (`SAVE_KEY`) ) TYPE=MyISAM COMMENT='PokeMod Saving Table'")
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
}
debugMessage( 0,7,"SQLx registering done" )
}
public adminCopyVault(id)
{
if (!(get_user_flags(id)&ADMIN_RCON ) && id!=0) return PLUGIN_HANDLED
if ( SqlConnection == Empty_Handle ) return PLUGIN_HANDLED
// Open up the vault file - read line by line
if ( !file_exists(g_VaultFile) ) return PLUGIN_HANDLED
console_print(id,"Please wait while the XP data is copied")
// Read through the file looking for shinfo entries
new parm[2]
parm[0] = id
parm[1] = 0
adminCopyVHelper(parm)
//Rest of this is done in the helper function
return PLUGIN_HANDLED
}
public adminCopyVHelper(parm[])
{
//Get data from parm
new id = parm[0]
new nextLine = parm[1]
// Read through the file looking for shinfo entries
new lengthRead
new data[512], Right[401], Left[111]
g_Connected[0] = -1
while ((nextLine = read_file(g_VaultFile,nextLine,data,511,lengthRead)) != 0) {
if ( lengthRead > 0 && equali(data, "PokeMod", 7) ) {
strbreak(data, Left, 110, Right, 400)
replace(Left,110,"PokeMod-",EMPTY)
replace_all(Left,34,"`","\\`")
replace_all(Left,34,"'","\\'")
writeData(0, Left, Right)
if (nextLine % 200 == 0) {
parm[1] = nextLine
console_print(id,"Delaying a few seconds before copying the next set of entries")
set_task(3.0, "adminCopyVHelper",0,parm,2)
return
}
}
}
//If it makes it this far it must be done copying
// OK now load the XP for any players playing
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for( new x=0; x < pnum; x++ )
LoadXP(players[x])
console_print(id,"Saved XP has been copied from the vault to the MySQL Database Successfully")
}
public SQLX_Handler(failstate, Handle:query, error[], errnum, data[], size)
{
new mode = data[0]
new id = data[1]
if(failstate){
if(failstate==TQUERY_QUERY_FAILED){
debugMessage(id,0,"SQLx Query Failed(%d): %s:'%d'",mode,error,errnum)
return
}
else{
debugMessage(id,0,"SQLx Connect Failed(%d): %s:'%d'",mode,error,errnum)
return
}
}
switch(mode)
{
case SQLX_LOADXP:{
if(SQL_NumResults(query)){
new Right[1501]
SQL_ReadResult(query, 0, Right, 500)
HandleLoad(id,Right)
}
else {
g_Connected[id] = -1
return
}
}
case SQLX_LOADRANK:{
if(SQL_NumResults(query)){
new Right[151]
SQL_ReadResult(query, 0, Right, 150)
HandleRanks(id, Right)
}
else
g_PokeRanksLoaded = -1
}
}
}
writeData(x, key[], xps_to_save[])
{
debugMessage(x, 8,"Trying to save XP data: '%s' - '%s'", key, xps_to_save)
new sql[512]
new data[2]
data[0] = 0
data[1] = x
if(!g_Connected[x])
return
else if(g_Connected[x]==-1){ //they didn't have xp already, g_Connected was -1
formatex(sql, 511, "INSERT INTO `pm_save` (SAVE_KEY) VALUES ('%s')", key )
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
g_Connected[x] = 1
}
formatex(sql, 511, "UPDATE `pm_save` SET `XPS`='%s' WHERE (SAVE_KEY='%s')",xps_to_save,key)
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
formatex(sql, 511, "UPDATE `pm_save` SET `LAST_PLAY_DATE`='%d' WHERE (SAVE_KEY='%s')",get_systime(),key)
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
}
public saving_end()
SQL_FreeHandle(SqlConnection)
#endif
#if SAVE==SAVE_MYSQL
public adminCopyVault(id)
{
if (!(get_user_flags(id)&ADMIN_RCON ) && id!=0) return PLUGIN_HANDLED
mySQLConnect()
if ( gMySQL <= SQL_FAILED ) return PLUGIN_HANDLED
//Turn Persistant on for this function
gPersistentTemp = true
// Open up the vault file - read line by line
if ( !file_exists(g_VaultFile) ) return PLUGIN_HANDLED
console_print(id,"Please wait while the XP data is copied")
// Read through the file looking for shinfo entries
new parm[2]
parm[0] = id
parm[1] = 0
adminCopyVHelper(parm)
//Rest of this is done in the helper function
return PLUGIN_HANDLED
}
public adminCopyVHelper(parm[])
{
//Get data from parm
new id = parm[0]
new nextLine = parm[1]
// Read through the file looking for shinfo entries
new lengthRead
new data[512], Right[401], Left[111]
while ((nextLine = read_file(g_VaultFile,nextLine,data,511,lengthRead)) != 0) {
if ( lengthRead > 0 && equali(data, "PokeMod", 7) ) {
strbreak(data, Left, 110, Right, 400)
replace(Left,110,"PokeMod-",EMPTY)
replace_all(Left,34,"`","\\`")
replace_all(Left,34,"'","\\'")
writeData(0, Left, Right)
if (nextLine % 200 == 0) {
parm[1] = nextLine
console_print(id,"Delaying a few seconds before copying the next set of entries")
set_task(3.0, "adminCopyVHelper",0,parm,2)
return
}
}
}
//If it makes it this far it must be done copying
// OK now load the XP for any players playing
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for( new x=0; x < pnum; x++ )
LoadXP(players[x])
console_print(id,"Saved XP has been copied from the vault to the MySQL Database Successfully")
//Set Persistent back how it was
gPersistentTemp = false
//Closes the connection if set not to be persistent
close_mysql()
}
public saving_init()
{
register_pokeadmincmd("vault_to_sql","adminCopyVault", ADMIN_RCON,"- Copies vault XP to MySQL, should only be done once.")
// Verify the type of DBI module that is loaded is supported
dbi_type(SQLtype, 15);
if (equali(SQLtype, g_MySQL))
{
SQL_TYPE = SQL_MYSQL;
}
else if (equali(SQLtype, g_SQLite))
{
SQL_TYPE = SQL_SQLITE;
}
else
{
SQL_TYPE = SQL_NONE;
debugMessage(_,_,"Unsupported database type found (%s), the supported databases are %s or %s", SQLtype, g_MySQL, g_SQLite);
return;
}
debugMessage( 0,7,"MYSQL registering done" )
}
public mySQLConnect()
{
gPersistent = get_ppcvar_num(pm_mysql_persistent)
if ( gMySQL >= SQL_OK ) {
if (!gPersistent && !gPersistentTemp) close_mysql()
else return
}
new host[64],user[32],pass[32],db[32],error[128]
get_ppcvar_string(pm_mysql_host,host,63)
get_ppcvar_string(pm_mysql_user,user,31)
get_ppcvar_string(pm_mysql_pass,pass,31)
get_ppcvar_string(pm_mysql_db,db,31)
if ( !strlen(host) && !strlen(user) && !strlen(db) ) {
get_cvar_string("amx_mysql_host",host,63)
get_cvar_string("amx_mysql_user",user,31)
get_cvar_string("amx_mysql_pass",pass,31)
get_cvar_string("amx_mysql_db",db,31)
}
// Set a default DB if it's SQLite and the user didn't supply one
if ( SQL_TYPE == SQL_SQLITE && strlen(db) < 1 )
copy( db, 127, "addons/amxmodx/data/amxx.db" );
gMySQL = dbi_connect(host,user,pass,db,error,127)
if (gMySQL <= SQL_FAILED) {
debugMessage(0,0,"MySQL connect error: '%s' (%s,%s,%s)",error,host,user,db)
return
}
//Only try to create the tables once
else if (CreateTables) {
new sql[512]
new Result:retval
if ( SQL_TYPE == SQL_SQLITE ){
if ( !sqlite_table_exists( gMySQL, "pm_save" ) ){
copy(sql, 511, "CREATE TABLE `pm_save` ( `SAVE_KEY` varchar(34) binary NOT NULL default '', `XPS` varchar(255) binary NOT NULL default '', `LAST_PLAY_DATE` timestamp(14) NOT NULL, PRIMARY KEY (`SAVE_KEY`) ) TYPE=MyISAM COMMENT='PokeMod Saving Table'")
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Making Tables: '%s' - '%s'", error, sql)
return
}
if ( SQL_TYPE == SQL_SQLITE )
{
new IntegrityCheck[64];
copy(sql, 511, "PRAGMA integrity_check");
new Result:res = dbi_query(gMySQL, sql);
// Check for an error
if ( res < RESULT_NONE )
{
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Making Tables: '%s' - '%s'", error, sql)
return;
}
// Get the integrity check value
while ( res && dbi_nextrow(res) > 0 )
{
dbi_result(res, "integrity_check", IntegrityCheck, 63);
}
// Free the result
dbi_free_result(res);
// Check to make sure the integrity check passed
if ( !equali(IntegrityCheck, "ok") )
{
// Should we disable saving here?
debugMessage(_,_,"SQL Lite integrity check failed");
return;
}
// Do some synchronous crap
format(sql, 511, "PRAGMA synchronous = %d", SQLITE_SYNC_OFF);
dbi_query(gMySQL, sql);
}
}
}
else {
copy(sql, 511, "CREATE TABLE IF NOT EXISTS `pm_save` ( `SAVE_KEY` varchar(34) binary NOT NULL default '', `XPS` varchar(255) binary NOT NULL default '', `LAST_PLAY_DATE` timestamp(14) NOT NULL, PRIMARY KEY (`SAVE_KEY`) ) TYPE=MyISAM COMMENT='PokeMod Saving Table'")
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Making Tables: '%s' - '%s'", error, sql)
return
}
}
CreateTables = false
}
}
writeData(x, key[], xps_to_save[])
{
mySQLConnect()
if ( gMySQL <= SQL_FAILED ) return
debugMessage( x, 8,"Trying to save XP data: '%s' - '%s'", key, xps_to_save)
new error[128],sql[512]
new Result:retval, Result:retvalins
//Thanks to HC for help with writing more efficient queries
//Check if this user has an entry already, if not make one
formatex(sql, 511, "SELECT * FROM `pm_save` WHERE `SAVE_KEY` = '%s'", key)
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Querying MySQL DB for %s: '%s' - '%s'", key, error, sql)
return
}
else if (!dbi_nextrow(retval)) {
formatex(sql, 511, "INSERT INTO `pm_save` (SAVE_KEY) VALUES ('%s')", key )
retvalins = dbi_query(gMySQL,sql)
if (retvalins <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Writing MySQL XP for %s: '%s' - '%s'", key, error, sql)
return
}
}
if (retval >= RESULT_OK) dbi_free_result(retval)
//Update users entry with current data
formatex(sql, 511, "UPDATE `pm_save` SET `XPS`='%s' WHERE (SAVE_KEY='%s')",xps_to_save,key)
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Writing MySQL XP for %s: '%s' - '%s'", key, error, sql)
return
}
//Closes the connection if set not to be persistent
close_mysql()
}
public close_mysql()
{
if (gMySQL <= SQL_FAILED || gPersistent || gPersistentTemp) return
dbi_close(gMySQL)
}
public saving_end()
{
if ( gMySQL <= SQL_FAILED ) return
dbi_close(gMySQL)
}
#endif
#if SAVE==SAVE_VAULT
writeData(x, key[], xps_to_save[])
{
debugMessage(x, 8,"Trying to save XP data: '%s' - '%s'", key, xps_to_save)
new vaultSaveKey[40]
//Make the key to save to
formatex(vaultSaveKey,39,"PokeMod-%s",key)
set_vaultdata(vaultSaveKey, xps_to_save)
}
#endif
#if SAVE==SAVE_NVAULT
public saving_init()
{
register_pokeadmincmd("vault_to_nvault","adminCopyVault", ADMIN_RCON,"- Copies vault XP to NVault, should only be done once.")
nvault_db = nvault_open("pm_save")
debugMessage( 0,7,"NVault registering done" )
}
writeData(x, key[], xps_to_save[])
{
debugMessage( x, 8,"Trying to save XP data: '%s' - '%s'", key, xps_to_save)
new vaultSaveKey[40]
//Make the key to save to
formatex(vaultSaveKey,39,"PokeMod-%s",key)
nvault_set(nvault_db, key, xps_to_save)
}
public adminCopyVault(id)
{
if (!(get_user_flags(id)&ADMIN_RCON ) && id!=0) return PLUGIN_HANDLED
// Open up the vault file - read line by line
if ( !file_exists(g_VaultFile) ) return PLUGIN_HANDLED
console_print(id,"Please wait while the XP data is copied")
// Read through the file looking for shinfo entries
new parm[2]
parm[0] = id
parm[1] = 0
adminCopyVHelper(parm)
//Rest of this is done in the helper function
return PLUGIN_HANDLED
}
public adminCopyVHelper(parm[])
{
//Get data from parm
new id = parm[0]
new nextLine = parm[1]
// Read through the file looking for shinfo entries
new lengthRead
new data[512], Right[401], Left[111]
while ((nextLine = read_file(g_VaultFile,nextLine,data,511,lengthRead)) != 0) {
if ( lengthRead > 0 && equali(data, "PokeMod", 7) ) {
strbreak(data, Left, 110, Right, 400)
replace(Left,110,"PokeMod-",EMPTY)
writeData(0, Left, Right)
if (nextLine % 200 == 0) {
parm[1] = nextLine
console_print(id,"Delaying a few seconds before copying the next set of entries")
set_task(3.0, "adminCopyVHelper",0,parm,2)
return
}
}
}
//If it makes it this far it must be done copying
// OK now load the XP for any players playing
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for( new x=0; x < pnum; x++ )
LoadXP(players[x])
console_print(id,"Saved XP has been copied from the vault to the NVault Database Successfully")
}
#endif
public LoadXP(id)
{
if( !PM_Loaded ){
g_Connected[id] = 0;
return false;
}
if( g_isWild[id] > 0 )
return true
if( !SaveXPon() )
return true
new key[35]
if( getSaveKey(id, key, true) )
{
#if SAVE==SAVE_NVAULT
new Right[1501]
new vaultSaveKey[40], time
formatex(vaultSaveKey,39,"PokeMod-%s",key)
nvault_lookup(nvault_db, key, Right, 1500, time)
#endif
#if SAVE==SAVE_VAULT
new Right[1501]
new vaultSaveKey[40]
formatex(vaultSaveKey,39,"PokeMod-%s",key)
get_vaultdata(vaultSaveKey, Right, 1500)
#endif
#if SAVE==SAVE_MYSQL
new Right[1501]
new sql[512], error[128]
new Result:retvalxp
mySQLConnect()
if ( gMySQL <= SQL_FAILED ) return false
formatex(sql, 511, "SELECT `XPS` FROM `pm_save` WHERE `SAVE_KEY` = '%s'", key)
retvalxp = dbi_query(gMySQL,sql)
if(retvalxp <= RESULT_FAILED){
dbi_error(gMySQL,error,127)
debugMessage(id,0,"Error Querying MySQL DB for %s: '%s' - '%s'", key, error, sql)
//Closes the connection if set not to be persistent
close_mysql()
return false
}
else if (!dbi_nextrow(retvalxp)) {
dbi_error(gMySQL,error,127)
debugMessage(id,3,"No Saved XP Loaded for %s: '%s'", key, error)
if (retvalxp >= RESULT_OK) dbi_free_result(retvalxp)
//Closes the connection if set not to be persistent
close_mysql()
g_Connected[id] = -1
return true
}
dbi_field(retvalxp, 1, Right, 500)
#endif
#if SAVE==SAVE_SQLX
if(SqlConnection == Empty_Handle)
return false
new sql[512]
new data[2]
data[0] = SQLX_LOADXP
data[1] = id
formatex(sql, 511, "SELECT `XPS` FROM `pm_save` WHERE `SAVE_KEY` = '%s'", key)
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
return true
#else //Only SQLx won't be handling it straight from here
return HandleLoad(id,Right)
#endif
}
g_Connected[id] = 0;
return false;
}
HandleLoad(id, Right[1501])
{
debugMessage(id,8,"loading %s",Right );
//we don't have any saved data
if(equali(Right,EMPTY))
return NewPlayerSettings(id);
new Left[51], i;
for( i = 0; i<MAX_POKES; i++)
{
strbreak(Right, Left, 50, Right, 1500)
if( equal(Left, COLON, 1) ) break //stop if this is the end of the data we want to look at
PlayersPoke[id][i] = str_to_num(Left)
strbreak(Right, Left, 50, Right, 1500)
if( equal(Left, COLON, 1) ) break //stop if this is the end of the data we want to look at
PlayersXP[id][i] = str_to_num(Left)
}
while( !equal(Left, COLON, 1) && !equali(Right,EMPTY)){ //if we didn't stop because we found a :, lets get the next one
strbreak(Right, Left, 50, Right, 1500)
}
//we ran out of data
if(equali(Right,EMPTY))
return NewPlayerSettings(id, true);
strbreak(Right, Left, 50, Right, 1500)
if( !equal(Left, COLON, 1) ){ //we found the time, and not the next seperator
PlayersTime[id] = str_to_num(Left)
}
while( !equal(Left, COLON, 1) && !equali(Right,EMPTY)) //if we didn't stop because we found a :, lets get the next one
strbreak(Right, Left, 50, Right, 1500)
//strbreak(Right, Left, 50, Right, 1500)
if( equal(Left, COLON, 1) ){ //we found the seperator, now this will break it down in here
for( i = 0; i<MAX_SETS; i++)
{
strbreak(Right, Left, 50, Right, 1500)
if( equal(Left, COLON, 1) ) break //stop if this is the end of the data we want to look at
PlayersSet[id][i] = str_to_num(Left)
}
}
while( !equal(Left, COLON, 1) && !equali(Right,EMPTY)) //if we didn't stop because we found a :, lets get the next one
strbreak(Right, Left, 50, Right, 1500)
strbreak(Right, Left, 50, Right, 1500)
if( !equal(Left, COLON, 1) ){ //we found their catches
PlayersCatch[id] = str_to_num(Left)
}
if( is_user_bot(id) )
BotSelect(id);
return ConnectPlayer(id)
}
NewPlayerSettings(id, bool:had_pokemon=false)
{
PlayersSet[id][SET_HUD_Y] = -4;
if( !had_pokemon )
g_Connected[id] = -1;
else
return ConnectPlayer(id);
return true;
}
ConnectPlayer(id)
{
g_Connected[id] = 1
RefreshPoke(id)
return true
}
public load_all()
{
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for( new i=0; i<pnum; i++)
LoadXP(players[i])
#if POKERANK_SYSTEM==1
LoadRanks()
#endif
}
public save_all()
{
poke_print(0, print_center, "%s Saving All Data",PREFIX);
new players[MAX_PLAYERS], pnum;
poke_get_players(players, pnum);
for( new i=0; i<pnum; i++)
set_task( 1.5*(i+1), "delayed_save", players[i]);
#if POKERANK_SYSTEM==1
SaveRanks();
#endif
}
public delayed_save(id)
SaveXP(id, -1);
SaveXP(id, forced=1)
{
if(g_isWild[id]>0)
return false;
static key[35]
static Float:last_save[MAX_PLAYERS+1], Float:time_left, Float:current_time;
if( id ){
current_time = get_gametime();
time_left = current_time - last_save[id];
if( forced < 1 && time_left < SAVE_SPAM){
if( !forced )
poke_print(id, print_chat, "You must wait %0.1f seconds before saving again.", SAVE_SPAM-time_left);
return false;
}
last_save[id] = current_time;
}
if( g_Connected[id] && getSaveKey(id, key) && SaveXPon() )
{
RefreshPoke(id)
new Data[1501], iLen = 0, i
//save their pokemon and xp
for(i = 0; i<MAX_POKES; i++)
iLen += formatex(Data[iLen],(1501-iLen),"%d %d ", PlayersPoke[id][i], PlayersXP[id][i])
//save the time
iLen += copy(Data[iLen],(1501-iLen),": ")
iLen += formatex(Data[iLen],(1501-iLen),"%d ",get_systime())
iLen += copy(Data[iLen],(1501-iLen),": ")
//save their settings
for(i = 0; i<MAX_SETS; i++)
iLen += formatex(Data[iLen],(1501-iLen),"%d ", PlayersSet[id][i])
//save their pokerank crap
iLen += formatex(Data[iLen],(1501-iLen),": %d",PlayersCatch[id])
writeData(id, key, Data)
debugMessage(id,5,"saved data with save key %s", key)
return true;
}
return false;
}
//thanks to SHmod
getSaveKey(id, key[35]="", bool:update=false)
{
static player_key[MAX_PLAYERS+1][35];
if( update ) {
if(is_user_bot(id)) {
new botname[32]
get_user_name(id,botname,31)
//Get Rid of BOT Tag
//PODBot
replace(botname,31,"[POD]",EMPTY)
replace(botname,31,"[P*D]",EMPTY)
replace(botname,31,"[P0D]",EMPTY)
//CZ Bots
replace(botname,31,"[BOT] ",EMPTY)
//Attempt to get rid of the skill tag so we save with bots true name
new lastchar = strlen(botname) - 1
if ( equal(botname[lastchar],")",1) ) {
new x
for ( x = lastchar - 1; x > 0; x--) {
if ( equal(botname[x],"(",1) ) {
botname[x - 1] = 0
break
}
if ( !isdigit(botname[x]) ) break
}
}
if (strlen(botname) > 0 ) {
#if SAVE==SAVE_MYSQL || SAVE==SAVE_SQLX
replace_all(botname,31,"`","\\`")
replace_all(botname,31,"'","\\'")
#endif
replace_all(botname,31," ","_")
formatex( player_key[id], 34, "[BOT]%s", botname )
}
}
//Hack for STEAM's retardedness with listen servers
else if (!is_dedicated_server() && id == 1) {
copy( player_key[id], 34, "loopback" )
}
else {
if (get_pcvar_num(sv_lan) == 1) {
get_user_ip( id, player_key[id], 34, 1 ) // by ip without port
}
else {
get_user_authid( id, player_key[id], 34 ) // by steamid
if( equali(player_key[id],"STEAM_ID_LAN") || equali(player_key[id],"4294967295") ){
get_user_ip( id, player_key[id], 34, 1 ) // by ip without port
}
}
}
debugMessage(id,5,"updated savekey");
}
//Check to make sure we got something useable
if( equali(player_key[id], "STEAM_ID_PENDING") || equali(player_key[id], EMPTY) ){
debugMessage(id,5,"does not have a valid savekey ('%s')", player_key[id]);
return false;
}
copy( key, 34, player_key[id] );
return true;
}
///////////////////////////
// Levels a pokemon up //
///////////////////////////
LevelUpPokemon(id, num, levels=1, take_item=MAX_ITEMS)
{
new pastlevel = PlayersLevel(id, num)
new pname[NAME_LENGTH]
PokeToName(PlayersPoke[id][num], pname, NAME_LENGTH)
if( take_item != MAX_ITEMS ){
if(pastlevel == TotalLevels){
poke_print(id, print_chat, "%s ma maksymalny poziom.",pname)
return false
}
PlayersItem[id][take_item]--
}
new newlevel = pastlevel+levels
if(newlevel > TotalLevels)
newlevel = TotalLevels
PlayersXP[id][num] = PokeLevels[newlevel-1]
poke_print(id, print_chat, "%s ma teraz poziom %d",pname,newlevel)
Check_Evolve(id, PlayersPoke[id][num], newlevel)
return true
}
///////////////////////////////////////
// Returns what level a players is //
///////////////////////////////////////
PlayersLevel(id, num=-1 )
{
if(0>id || id>MAX_PLAYERS)
return 0;
if(Safari())
return SafariLevel(Pokemon[id]);
if( num == -1 )
num = PlayersActive[id];
if(MAX_POKES<=num || num<0)
return 0;
static i;
i = 1;
if(g_isWild[id]<1){
while(PlayersXP[id][num]>=PokeLevels[i]){
i++;
if(i==TotalLevels)
break;
}
}
else{
while(PlayersXP[id][num]>=PokeLevels[i]/2){
i++;
if(i==TotalLevels)
break;
}
}
#if RARE_CANDY_MODE == 1 || RARE_CANDY_MODE == 3
static k;
for(k=0; k<ItemsCreated; k++)
if( ItemInfo[k] & II_LEVEL )
i += PlayersItem[id][k];
#endif
return i;
}
/////////////////////////////////////////////
// Returns what players average level is //
/////////////////////////////////////////////
AverageLevel(id)
{
if(Safari())
return SafariLevel(Pokemon[id]);
if(g_isWild[id]>0)
return PlayersLevel(id, 0);
new pokes, total
for(new i = 0; i<MAX_ACTIVE_POKES; i++)
{
if(PlayersPoke[id][i]){
pokes++;
total += PlayersLevel(id, i);
}
}
if(pokes){
new average = total/pokes;
return average;
}
return 0
}
/////////////////////////////////////
// Adds a pokemon to playerspoke //
/////////////////////////////////////
bool:AddPoke(id, pid, xp=1, giver=0)
{
RefreshPoke(id);
if(!ValidPoke(pid) || AvailableSlot(id, pid)!=AS_OK || Safari())
return false;
#if RCON_POKEADMINS == 1
if( giver && SpecialPoke(pid) && !(get_user_flags(giver)&ADMIN_RCON) )
return false;
#endif
if(!xp)
xp = 1;
new i = Slot(id);
PlayersPoke[id][i] = pid;
PlayersXP[id][i] = xp;
ShowPokeInfo(id, pid);
SaveXP(id);
return true;
}
////////////////
// Gives XP //
////////////////
GiveXP(id, poke, amount)
{
if(Safari())
return
if(MAX_POKES<=poke || poke<0 || !PlayersPoke[id][poke])
return
new oldlevel, newlevel
oldlevel = PlayersLevel(id, poke)
PlayersXP[id][poke] += amount
newlevel = PlayersLevel(id, poke)
if(PlayersXP[id][poke]<1)
PlayersXP[id][poke] = 1
if(oldlevel<newlevel){
new oldmax = PlayerStat[id][STAT_MAXHP]
new name[32]
get_user_name(id, name, 31)
poke_print(0, print_chat, "Gratulacje %s! %s ma teraz poziom %d!",name,PokeToName(PlayersPoke[id][poke]),newlevel)
//ding for level up
poke_sound(id, CHAN_AUTO, SND_BELL)
if(is_user_alive(id)){
get_user_origin(id, origin[id])
//sprites to show level up (only once)
message_begin(MSG_BROADCAST ,SVC_TEMPENTITY) //message begin
write_byte(TE_LARGEFUNNEL)
write_coord(origin[id][0]) // funnel position
write_coord(origin[id][1])
write_coord(origin[id][2]-32)
write_short(SPRITE_INDEX[SPR_MUZZLEFLASH1]) // sprite index
write_short(8) // flags
message_end()
}
Check_Evolve(id, PlayersPoke[id][poke], newlevel)
#if POKERANK_SYSTEM==1
PlayersCatch[id] += newlevel
CheckMaxHP(id)
if(oldmax!=PlayerStat[id][STAT_MAXHP]){
poke_print(id, print_chat, "Twoje max HP to %d! Twoj PokeRank to: %d",PlayerStat[id][STAT_MAXHP],PlayersCatch[id])
}
else
poke_print(id, print_chat, "Twoj PokeRank to %d",PlayersCatch[id])
#else
CheckMaxHP(id)
if(oldmax!=PlayerStat[id][STAT_MAXHP]){
poke_print(id, print_chat, "Twoje max HP to %d!",PlayerStat[id][STAT_MAXHP])
}
#endif
}
else if(oldlevel>newlevel){
new oldmax = PlayerStat[id][STAT_MAXHP]
new name[32]
get_user_name(id, name, 31)
poke_print(id, print_chat, "%s, %s ma teraz poziom %d.",name,PokeToName(PlayersPoke[id][poke]),newlevel)
#if POKERANK_SYSTEM==1
PlayersCatch[id] -= oldlevel
CheckMaxHP(id)
if(oldmax!=PlayerStat[id][STAT_MAXHP]){
poke_print(id, print_chat, "Twoje max HP to %d. Twoj PokeRank to: %d",PlayerStat[id][STAT_MAXHP],PlayersCatch[id])
}
else
poke_print(id, print_chat, "Twoj PokeRank to: %d",PlayersCatch[id])
#else
CheckMaxHP(id)
if(oldmax!=PlayerStat[id][STAT_MAXHP]){
poke_print(id, print_chat, "Twoje max HP to %d.",PlayerStat[id][STAT_MAXHP])
}
#endif
#if POKEMON_UNEVOLVE==1
Check_UnEvolve(id, PlayersPoke[id][poke])
#endif
}
#if POKERANK_SYSTEM==1
if(oldlevel != newlevel){
if(SpecialRank(id)!=-1) //update their thing, and check if they went higher
UpdateSpecialRank(id)
else
CheckUpdateRank(id) //only check if they went higher than the last person in Elite Four
}
#endif
}
/////////////////////
// Gives Kill XP //
/////////////////////
KillXP(attacker, victim)
{
if(attacker==victim)
return
new xp_to_give = PlayersLevel(victim)
if( Team(attacker) == Team(victim) ){
GiveXP(attacker, PlayersActive[attacker], -1*xp_to_give)
poke_print(attacker, print_chat, "You lost %d experience for killing a teamate.",xp_to_give)
}
else
GiveXP(attacker, PlayersActive[attacker], xp_to_give)
}
/////////////////////////
// Adds level to num //
/////////////////////////
AddLvl(id, num)
{
num += PlayersLevel(id);
return true;
}
///////////////////////////
// Adds level to float //
///////////////////////////
f_AddLvl(id, Float:num)
{
num += PlayersLevel(id);
return true;
}
////////////////////////////////
// Switches a users pokemon //
////////////////////////////////
SwitchPoke(id, pid, bool:force=true)
{
if( !ValidPoke(pid) )
return false;
if( pid == Pokemon[id] )
return true;
#if ADMIN_SPECIAL == 1
if( SpecialPoke(pid) && !poke_access(id) ){
poke_print(id, print_chat, "This server is restricting who can use %s.",PokeToName(pid));
return false;
}
#endif
if(Safari()){
if(SafariLevel(pid)){
ResetSkills(id, false)
Pokemon[id] = pid
SetSpeed(id)
return true
}
return false
}
#if CHANGE_POKES > 0
if( !force && ChangedPoke[id] < 1 && is_user_alive(id) ){
#if CHANGE_POKES > 1
poke_print(id, print_chat, "This server is only allowing you to change pokemon %d times while you are alive.",CHANGE_POKES)
#else
poke_print(id, print_chat, "This server is only allowing you to change pokemon 1 time while you are alive.")
#endif
return false
}
#else
#if CHANGE_POKES == -1
if( is_user_bot(id) && ChangedPoke[id] == 0 )
return false
#endif
#endif
for(new i=0; i<MAX_ACTIVE_POKES; i++){
if(PlayersPoke[id][i]==pid){
ResetSkills(id, false)
Pokemon[id] = pid
PlayersActive[id] = i
SetSpeed(id)
#if CHANGE_POKES > 0
ChangedPoke[id]--
#endif
if( !force && CHANGE_DELAY > 0.0 )
bind_used(id, _, CHANGE_DELAY);
return true
}
}
return false
}
////////////////////////////////
// Releases a users pokemon //
////////////////////////////////
ReleasePoke(id, pid, bool:allow_cancel=true)
{
if( !ValidPoke(pid) )
return
new slot = Slot(id, pid, CHECK_ALL)
if(slot!=-1){
if(allow_cancel){
if( slot == PlayersActive[id] ){
poke_print(id, print_chat, "Nie mozesz wypuscic swojego aktywnego Pokemona.");
return;
}
if( task_exists(id+RELEASE_TASK) ){
poke_print(id, print_chat, "Mozesz wypuszczac tylko 1 Pokemon naraz.");
return;
}
new parm[2]
parm[0] = id
parm[1] = pid
set_task(RELEASE_TIME/2, "ReleaseRemind", id+RELEASE2_TASK, parm, 2)
set_task(RELEASE_TIME, "FinalRelease", id+RELEASE_TASK, parm, 2)
poke_print(id, print_chat, "Masz %.1f seconds by napisac /cancel i nie wypuscic %s. Albo napisz /finalrelease do natychmiastowego wypusczenia.",RELEASE_TIME,PokeToName(pid))
}
else{
PlayersPoke[id][slot] = 0
PlayersXP[id][slot] = 0
SaveXP(id)
if( !SwitchPoke(id, Pokemon[id]) )
SwitchPoke(id, PlayersPoke[id][PlayersActive[id]])
}
}
}
public ReleaseRemind(parm[])
{
poke_print(parm[0], print_chat, "%s zostanie wypuszczony w ciagu %.1f sekund. Napisz /cancel by anulowac wypuszczenie.",PokeToName(parm[1]),RELEASE_TIME/2)
}
public FinalRelease(parm[])
{
new id = parm[0], poke = parm[1];
new slot = Slot(id, poke, CHECK_ALL)
if( slot != -1 ){
poke_print(id, print_chat, "%s zostal wypuszczony.",PokeToName(poke))
PlayersPoke[id][slot] = 0
PlayersXP[id][slot] = 0
SaveXP(id)
}
}
////////////////////////////
// Trades users pokemon //
////////////////////////////
TradePoke(id, pid, nid)
{
if( !g_Connected[id] || !ValidPoke(pid) || !g_Connected[nid] )
return false
#if RCON_POKEADMINS == 1
if( SpecialPoke(pid) && !(get_user_flags(id)&ADMIN_RCON) ){
poke_print(id, print_chat, "Nie mozesz dac swojego specjalnego Pokemona.");
return false;
}
#endif
new pnum = HasPokemon(id, pid, CHECK_ALL)
if( pnum >= 0 ){
if( pnum == PlayersActive[id] ){
poke_print(id, print_chat, "Nie mozesz dac swojego aktywnego Pokemona.");
return false;
}
new name[32], Nname[32], pname[NAME_LENGTH]
get_user_name(id, name, 31)
get_user_name(nid, Nname, 31)
PokeToName(pid, pname, NAME_LENGTH)
switch(AvailableSlot(nid, pid))
{
case AS_OK:{
new i = Slot(nid)
PlayersPoke[nid][i] = PlayersPoke[id][pnum]
PlayersXP[nid][i] = PlayersXP[id][pnum]
#if POKE_POPULATION!=2
ReleasePoke(id, pid, false);
#endif
poke_print(nid, print_chat, "%s dales %s.", name, pname)
poke_print(id, print_chat, "Dales %s swojego %s.", Nname, pname)
Check_Trade_Evolve(nid, pid);
return true;
}
case AS_NOGOOD:
poke_print(id, print_chat, "Nie mozesz dac Pokemonow dzikim gracza.")
case AS_NOROOM:
poke_print(id, print_chat, "%s ma za duzo Pokemonow.", Nname)
case AS_DUPLICATE:
poke_print(id, print_chat, "%s ma na razie %s.", Nname, pname)
}
}
else
poke_print(id, print_chat, "Nie masz %s do dania.", PokeToName(pid))
return false
}
////////////////////////////////
// Gets rid of Pokemod info ///////////// TY SHmod ///////////
////////////////////////////////
cleanXP(bool:clear_all=false)
{
#if SAVE==SAVE_VAULT
// Open up the vault file - read line by line
// Use vault to delete to any data over a certain age
if ( !file_exists(g_VaultFile) ) return
// Read through the file looking for pokemod entries
new lengthRead, nextLine = 0, last_time = (get_ppcvar_num(pm_xpsavedays) * SECONDS_IN_DAY)
new data[1501], key[35]
// This is an imperfect clean - but gets the job done
// Vault needs to have a way to walk it
// Deleting a Key can actually reorder the vault.ini file
while ((nextLine = read_file(g_VaultFile,nextLine,data,1500,lengthRead)) != 0) {
if ( lengthRead > 0 && equali(data, "PokeMod", 7) ) {
parse(data, key, 34)
if ( clear_all ) {
remove_vaultdata( key )
// since remove_vaultdata can reorder the whole file - we will go back some lines
nextLine = max(nextLine - 1, 0)
}
else {
HandleLoad(0, data)
if( PlayersTime[0] + last_time < get_systime() ){
remove_vaultdata( key )
// since remove_vaultdata can reorder the whole file - we will go back some lines
nextLine = max(nextLine - 1, 0)
}
}
}
}
#endif
#if SAVE==SAVE_NVAULT
if(clear_all)
nvault_prune(nvault_db, 0, get_systime())
else
nvault_prune(nvault_db, 0, get_systime() - (SECONDS_IN_DAY*get_ppcvar_num(pm_xpsavedays)) )
#endif
#if SAVE==SAVE_MYSQL
new error[127], sql[255]
new Result:retval
mySQLConnect()
if( gMySQL <= SQL_FAILED ) return
if(clear_all){
copy(sql, 254, "TRUNCATE TABLE `pm_save`")
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Couldn't Erase XP: '%s' - '%s' - %d", error, sql, gMySQL)
return
}
}
else{
if ( SQL_TYPE == SQL_SQLITE )
formatex( sql, 254, "DELETE FROM `pm_save` WHERE ((julianday(`time`) + %d) < julianday('now'))", get_ppcvar_num(pm_xpsavedays) );
else
formatex(sql, 254, "DELETE FROM `pm_save` WHERE pm_save.`LAST_PLAY_DATE` < (SYSDATE() - INTERVAL '%d' DAY)", get_ppcvar_num(pm_xpsavedays) )
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Couldn't Erase XP: '%s' - '%s' - %d", error, sql, gMySQL)
return
}
// Vacuum the SQL LITE DB Table
if ( SQL_TYPE == SQL_SQLITE )
{
copy( sql, 254, "VACUUM `pm_save`" );
dbi_query( gMySQL, sql );
}
}
//Closes the connection if set not to be persistent
close_mysql()
#endif
#if SAVE==SAVE_SQLX
new sql[512]
new data[2]
data[0] = 0
data[1] = 0
if(SqlConnection == Empty_Handle)
return
if(clear_all)
copy(sql, 511, "TRUNCATE TABLE `pm_save`")
else
formatex(sql, 511, "DELETE FROM `pm_save` WHERE pm_save.`LAST_PLAY_DATE` < (SYSDATE() - INTERVAL '%d' DAY)", get_ppcvar_num(pm_xpsavedays) )
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
#endif
}
SafariLevel(poke)
return SafariLevels[poke]
public SetSafariLevels()
{
new PokeFile[128];
Poke_FileName( F_Safari, PokeFile);
new Data[256]
new Left[NAME_LENGTH], Right[151], LeftN, RightN
new f = fopen(PokeFile, "rt");
while( !feof(f) ){
fgets(f, Data, 255);
if( !ValidData( Data ) )
continue;
strbreak(Data, Left, NAME_LENGTH-1, Right, 150)
LeftN = NameToPoke(Left)
if( !LeftN )
continue
strbreak(Right, Left, NAME_LENGTH-1, Right, 150)
RightN = str_to_num(Left)
if( RightN ){
SafariLevels[LeftN] = RightN
}
}
fclose(f);
}
#if ALLOW_WILD==1
AssignWild(id, bool:first_time=false)
{
new poke;
do poke = random_num(1,PokesCreated);
while( !BasePoke(poke)
|| ( random_num(1,PokesCreated) != poke && !poke_access(id) && SpecialPoke(poke) )
|| PokeDisabled(poke)
)
if(first_time){
new name[32]
get_user_name(id, name, 31)
poke_print(0, print_chat, "%s opuscil mape.",name)
SaveXP(id)
for(new i=0; i<MAX_POKES; i++){
PlayersPoke[id][i] = 0
PlayersXP[id][i] = 0
}
}
Pokemon[id] = poke
PlayersActive[id] = 0
PlayersPoke[id][0] = poke
PlayersXP[id][0] = PokeLevels[random_num(1, get_ppcvar_num(pm_wild_level))-1]/2
new pname[NAME_LENGTH]
PokeToName(poke, pname, NAME_LENGTH)
poke_print(0, print_chat, "A wild %s has appeared on the map.",pname)
poke_print(id, print_center, "Jestes dzikim %s",pname)
}
UnAssignWild(id)
{
if(WildCount()<=get_ppcvar_num(pm_wild) && get_ppcvar_num(pm_wild)>0){
poke_print(id, print_chat, "Nie jestes wystarczojaco dzikim Pokemonem by dojsc do Trenera.(%d/%d)", WildCount(), get_ppcvar_num(pm_wild))
return
}
new name[32]
get_user_name(id, name, 31)
if(is_user_alive(id))
poke_print(0, print_chat, "Dziki %s opuscil mape.",PokeToName(Pokemon[id]))
poke_print(0, print_chat, "%s has joined the map.",name)
LoadXP(id)
}
WildCount()
{
new count
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for(new i=0; i<pnum; i++){
if(g_isWild[players[i]]>0)
count++
}
return count
}
public WildMessage()
{
if(!Safari() && get_ppcvar_num(pm_wild)>0){
poke_print(0, print_chat, "Ten serwer potrzebuje %d dzikich pokemonow. Napisz /trainer albo /wild do zmiany.", get_ppcvar_num(pm_wild))
}
}
#endif
// Use this to create the table in MySQL
CREATE TABLE IF NOT EXISTS `pm_save` (
`SAVE_KEY` varchar(34) binary NOT NULL default '',
`XPS` varchar(255) binary NOT NULL default '',
`LAST_PLAY_DATE` timestamp(14) NOT NULL,
PRIMARY KEY (`SAVE_KEY`)
) TYPE=MyISAM COMMENT='PokeMod Saving Table';
// now it should work fine
//if using MySQL and are updating from v1.2.0 Beta J2 or lower, run these queries
ALTER TABLE `pm_save` ADD `LAST_PLAY_DATE` timestamp(14) NOT NULL;
ALTER TABLE `pm_save` MODIFY `XPS` varchar(255) binary NOT NULL default '';
//if using MySQL and are updating from v1.2.0 Beta K2 or lower, run this query
UPDATE `pm_save` SET `LAST_PLAY_DATE`=SYSDATE()
*/
// This makes sure theres no gaps in PlayersPoke
// Example:
// From: 5 390 0 0 10 200 16 1000
// To: 5 390 10 200 16 1000 0 0
public RefreshPoke(id)
{
if(Safari() || !id || !g_Connected[id])
return
new PlaceHolder[2][MAX_POKES]
new i, p = 0;
for(i = 0; i<MAX_ACTIVE_POKES; i++){
if( ValidPoke( PlayersPoke[id][i] ) ){
PlaceHolder[0][p] = PlayersPoke[id][i];
PlaceHolder[1][p] = PlayersXP[id][i];
p++;
}
}
for(i = p; i<MAX_ACTIVE_POKES; i++){
PlayersPoke[id][i] = 0;
PlayersXP[id][i] = 0;
}
p = MAX_ACTIVE_POKES;
for(i = MAX_ACTIVE_POKES; i<MAX_POKES; i++){
if( ValidPoke( PlayersPoke[id][i] ) ){
PlaceHolder[0][p] = PlayersPoke[id][i];
PlaceHolder[1][p] = PlayersXP[id][i];
p++;
}
}
for(i = p; i<MAX_POKES; i++){
PlayersPoke[id][i] = 0;
PlayersXP[id][i] = 0;
}
for(i = 0; i<MAX_POKES; i++){
PlayersPoke[id][i] = PlaceHolder[0][i];
PlayersXP[id][i] = PlaceHolder[1][i];
}
if(!SwitchPoke(id, Pokemon[id])){
for(i=0; i<MAX_ACTIVE_POKES; i++){
if(SwitchPoke(id, PlayersPoke[id][i]))
break;
}
}
}
///////////////////////////////////////////
// For MYSQL, find the database to use //
///////////////////////////////////////////
#if SAVE==SAVE_SQLX
public saving_init()
{
new host[64],user[32],pass[32],db[32]
get_ppcvar_string(pm_mysql_host,host,63)
get_ppcvar_string(pm_mysql_user,user,31)
get_ppcvar_string(pm_mysql_pass,pass,31)
get_ppcvar_string(pm_mysql_db,db,31)
register_pokeadmincmd("vault_to_sql","adminCopyVault", ADMIN_RCON,"- Copies vault XP to MySQL, should only be done once.")
// we tell the API that this is the information we want to connect to,
// just not yet. basically it's like storing it in global variables
SqlConnection = SQL_MakeDbTuple(host,user,pass,db)
if(!SqlConnection){
debugMessage( 0,0,"SQLx Connection Error. Check your cvars.")
return
}
else {
new data[2]
data[0] = 0
data[1] = 0
new sql[512]
copy(sql, 511, "CREATE TABLE IF NOT EXISTS `pm_save` ( `SAVE_KEY` varchar(34) binary NOT NULL default '', `XPS` varchar(255) binary NOT NULL default '', `LAST_PLAY_DATE` timestamp(14) NOT NULL, PRIMARY KEY (`SAVE_KEY`) ) TYPE=MyISAM COMMENT='PokeMod Saving Table'")
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
}
debugMessage( 0,7,"SQLx registering done" )
}
public adminCopyVault(id)
{
if (!(get_user_flags(id)&ADMIN_RCON ) && id!=0) return PLUGIN_HANDLED
if ( SqlConnection == Empty_Handle ) return PLUGIN_HANDLED
// Open up the vault file - read line by line
if ( !file_exists(g_VaultFile) ) return PLUGIN_HANDLED
console_print(id,"Please wait while the XP data is copied")
// Read through the file looking for shinfo entries
new parm[2]
parm[0] = id
parm[1] = 0
adminCopyVHelper(parm)
//Rest of this is done in the helper function
return PLUGIN_HANDLED
}
public adminCopyVHelper(parm[])
{
//Get data from parm
new id = parm[0]
new nextLine = parm[1]
// Read through the file looking for shinfo entries
new lengthRead
new data[512], Right[401], Left[111]
g_Connected[0] = -1
while ((nextLine = read_file(g_VaultFile,nextLine,data,511,lengthRead)) != 0) {
if ( lengthRead > 0 && equali(data, "PokeMod", 7) ) {
strbreak(data, Left, 110, Right, 400)
replace(Left,110,"PokeMod-",EMPTY)
replace_all(Left,34,"`","\\`")
replace_all(Left,34,"'","\\'")
writeData(0, Left, Right)
if (nextLine % 200 == 0) {
parm[1] = nextLine
console_print(id,"Delaying a few seconds before copying the next set of entries")
set_task(3.0, "adminCopyVHelper",0,parm,2)
return
}
}
}
//If it makes it this far it must be done copying
// OK now load the XP for any players playing
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for( new x=0; x < pnum; x++ )
LoadXP(players[x])
console_print(id,"Saved XP has been copied from the vault to the MySQL Database Successfully")
}
public SQLX_Handler(failstate, Handle:query, error[], errnum, data[], size)
{
new mode = data[0]
new id = data[1]
if(failstate){
if(failstate==TQUERY_QUERY_FAILED){
debugMessage(id,0,"SQLx Query Failed(%d): %s:'%d'",mode,error,errnum)
return
}
else{
debugMessage(id,0,"SQLx Connect Failed(%d): %s:'%d'",mode,error,errnum)
return
}
}
switch(mode)
{
case SQLX_LOADXP:{
if(SQL_NumResults(query)){
new Right[1501]
SQL_ReadResult(query, 0, Right, 500)
HandleLoad(id,Right)
}
else {
g_Connected[id] = -1
return
}
}
case SQLX_LOADRANK:{
if(SQL_NumResults(query)){
new Right[151]
SQL_ReadResult(query, 0, Right, 150)
HandleRanks(id, Right)
}
else
g_PokeRanksLoaded = -1
}
}
}
writeData(x, key[], xps_to_save[])
{
debugMessage(x, 8,"Trying to save XP data: '%s' - '%s'", key, xps_to_save)
new sql[512]
new data[2]
data[0] = 0
data[1] = x
if(!g_Connected[x])
return
else if(g_Connected[x]==-1){ //they didn't have xp already, g_Connected was -1
formatex(sql, 511, "INSERT INTO `pm_save` (SAVE_KEY) VALUES ('%s')", key )
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
g_Connected[x] = 1
}
formatex(sql, 511, "UPDATE `pm_save` SET `XPS`='%s' WHERE (SAVE_KEY='%s')",xps_to_save,key)
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
formatex(sql, 511, "UPDATE `pm_save` SET `LAST_PLAY_DATE`='%d' WHERE (SAVE_KEY='%s')",get_systime(),key)
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
}
public saving_end()
SQL_FreeHandle(SqlConnection)
#endif
#if SAVE==SAVE_MYSQL
public adminCopyVault(id)
{
if (!(get_user_flags(id)&ADMIN_RCON ) && id!=0) return PLUGIN_HANDLED
mySQLConnect()
if ( gMySQL <= SQL_FAILED ) return PLUGIN_HANDLED
//Turn Persistant on for this function
gPersistentTemp = true
// Open up the vault file - read line by line
if ( !file_exists(g_VaultFile) ) return PLUGIN_HANDLED
console_print(id,"Please wait while the XP data is copied")
// Read through the file looking for shinfo entries
new parm[2]
parm[0] = id
parm[1] = 0
adminCopyVHelper(parm)
//Rest of this is done in the helper function
return PLUGIN_HANDLED
}
public adminCopyVHelper(parm[])
{
//Get data from parm
new id = parm[0]
new nextLine = parm[1]
// Read through the file looking for shinfo entries
new lengthRead
new data[512], Right[401], Left[111]
while ((nextLine = read_file(g_VaultFile,nextLine,data,511,lengthRead)) != 0) {
if ( lengthRead > 0 && equali(data, "PokeMod", 7) ) {
strbreak(data, Left, 110, Right, 400)
replace(Left,110,"PokeMod-",EMPTY)
replace_all(Left,34,"`","\\`")
replace_all(Left,34,"'","\\'")
writeData(0, Left, Right)
if (nextLine % 200 == 0) {
parm[1] = nextLine
console_print(id,"Delaying a few seconds before copying the next set of entries")
set_task(3.0, "adminCopyVHelper",0,parm,2)
return
}
}
}
//If it makes it this far it must be done copying
// OK now load the XP for any players playing
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for( new x=0; x < pnum; x++ )
LoadXP(players[x])
console_print(id,"Saved XP has been copied from the vault to the MySQL Database Successfully")
//Set Persistent back how it was
gPersistentTemp = false
//Closes the connection if set not to be persistent
close_mysql()
}
public saving_init()
{
register_pokeadmincmd("vault_to_sql","adminCopyVault", ADMIN_RCON,"- Copies vault XP to MySQL, should only be done once.")
// Verify the type of DBI module that is loaded is supported
dbi_type(SQLtype, 15);
if (equali(SQLtype, g_MySQL))
{
SQL_TYPE = SQL_MYSQL;
}
else if (equali(SQLtype, g_SQLite))
{
SQL_TYPE = SQL_SQLITE;
}
else
{
SQL_TYPE = SQL_NONE;
debugMessage(_,_,"Unsupported database type found (%s), the supported databases are %s or %s", SQLtype, g_MySQL, g_SQLite);
return;
}
debugMessage( 0,7,"MYSQL registering done" )
}
public mySQLConnect()
{
gPersistent = get_ppcvar_num(pm_mysql_persistent)
if ( gMySQL >= SQL_OK ) {
if (!gPersistent && !gPersistentTemp) close_mysql()
else return
}
new host[64],user[32],pass[32],db[32],error[128]
get_ppcvar_string(pm_mysql_host,host,63)
get_ppcvar_string(pm_mysql_user,user,31)
get_ppcvar_string(pm_mysql_pass,pass,31)
get_ppcvar_string(pm_mysql_db,db,31)
if ( !strlen(host) && !strlen(user) && !strlen(db) ) {
get_cvar_string("amx_mysql_host",host,63)
get_cvar_string("amx_mysql_user",user,31)
get_cvar_string("amx_mysql_pass",pass,31)
get_cvar_string("amx_mysql_db",db,31)
}
// Set a default DB if it's SQLite and the user didn't supply one
if ( SQL_TYPE == SQL_SQLITE && strlen(db) < 1 )
copy( db, 127, "addons/amxmodx/data/amxx.db" );
gMySQL = dbi_connect(host,user,pass,db,error,127)
if (gMySQL <= SQL_FAILED) {
debugMessage(0,0,"MySQL connect error: '%s' (%s,%s,%s)",error,host,user,db)
return
}
//Only try to create the tables once
else if (CreateTables) {
new sql[512]
new Result:retval
if ( SQL_TYPE == SQL_SQLITE ){
if ( !sqlite_table_exists( gMySQL, "pm_save" ) ){
copy(sql, 511, "CREATE TABLE `pm_save` ( `SAVE_KEY` varchar(34) binary NOT NULL default '', `XPS` varchar(255) binary NOT NULL default '', `LAST_PLAY_DATE` timestamp(14) NOT NULL, PRIMARY KEY (`SAVE_KEY`) ) TYPE=MyISAM COMMENT='PokeMod Saving Table'")
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Making Tables: '%s' - '%s'", error, sql)
return
}
if ( SQL_TYPE == SQL_SQLITE )
{
new IntegrityCheck[64];
copy(sql, 511, "PRAGMA integrity_check");
new Result:res = dbi_query(gMySQL, sql);
// Check for an error
if ( res < RESULT_NONE )
{
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Making Tables: '%s' - '%s'", error, sql)
return;
}
// Get the integrity check value
while ( res && dbi_nextrow(res) > 0 )
{
dbi_result(res, "integrity_check", IntegrityCheck, 63);
}
// Free the result
dbi_free_result(res);
// Check to make sure the integrity check passed
if ( !equali(IntegrityCheck, "ok") )
{
// Should we disable saving here?
debugMessage(_,_,"SQL Lite integrity check failed");
return;
}
// Do some synchronous crap
format(sql, 511, "PRAGMA synchronous = %d", SQLITE_SYNC_OFF);
dbi_query(gMySQL, sql);
}
}
}
else {
copy(sql, 511, "CREATE TABLE IF NOT EXISTS `pm_save` ( `SAVE_KEY` varchar(34) binary NOT NULL default '', `XPS` varchar(255) binary NOT NULL default '', `LAST_PLAY_DATE` timestamp(14) NOT NULL, PRIMARY KEY (`SAVE_KEY`) ) TYPE=MyISAM COMMENT='PokeMod Saving Table'")
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Making Tables: '%s' - '%s'", error, sql)
return
}
}
CreateTables = false
}
}
writeData(x, key[], xps_to_save[])
{
mySQLConnect()
if ( gMySQL <= SQL_FAILED ) return
debugMessage( x, 8,"Trying to save XP data: '%s' - '%s'", key, xps_to_save)
new error[128],sql[512]
new Result:retval, Result:retvalins
//Thanks to HC for help with writing more efficient queries
//Check if this user has an entry already, if not make one
formatex(sql, 511, "SELECT * FROM `pm_save` WHERE `SAVE_KEY` = '%s'", key)
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Querying MySQL DB for %s: '%s' - '%s'", key, error, sql)
return
}
else if (!dbi_nextrow(retval)) {
formatex(sql, 511, "INSERT INTO `pm_save` (SAVE_KEY) VALUES ('%s')", key )
retvalins = dbi_query(gMySQL,sql)
if (retvalins <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Writing MySQL XP for %s: '%s' - '%s'", key, error, sql)
return
}
}
if (retval >= RESULT_OK) dbi_free_result(retval)
//Update users entry with current data
formatex(sql, 511, "UPDATE `pm_save` SET `XPS`='%s' WHERE (SAVE_KEY='%s')",xps_to_save,key)
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Error Writing MySQL XP for %s: '%s' - '%s'", key, error, sql)
return
}
//Closes the connection if set not to be persistent
close_mysql()
}
public close_mysql()
{
if (gMySQL <= SQL_FAILED || gPersistent || gPersistentTemp) return
dbi_close(gMySQL)
}
public saving_end()
{
if ( gMySQL <= SQL_FAILED ) return
dbi_close(gMySQL)
}
#endif
#if SAVE==SAVE_VAULT
writeData(x, key[], xps_to_save[])
{
debugMessage(x, 8,"Trying to save XP data: '%s' - '%s'", key, xps_to_save)
new vaultSaveKey[40]
//Make the key to save to
formatex(vaultSaveKey,39,"PokeMod-%s",key)
set_vaultdata(vaultSaveKey, xps_to_save)
}
#endif
#if SAVE==SAVE_NVAULT
public saving_init()
{
register_pokeadmincmd("vault_to_nvault","adminCopyVault", ADMIN_RCON,"- Copies vault XP to NVault, should only be done once.")
nvault_db = nvault_open("pm_save")
debugMessage( 0,7,"NVault registering done" )
}
writeData(x, key[], xps_to_save[])
{
debugMessage( x, 8,"Trying to save XP data: '%s' - '%s'", key, xps_to_save)
new vaultSaveKey[40]
//Make the key to save to
formatex(vaultSaveKey,39,"PokeMod-%s",key)
nvault_set(nvault_db, key, xps_to_save)
}
public adminCopyVault(id)
{
if (!(get_user_flags(id)&ADMIN_RCON ) && id!=0) return PLUGIN_HANDLED
// Open up the vault file - read line by line
if ( !file_exists(g_VaultFile) ) return PLUGIN_HANDLED
console_print(id,"Please wait while the XP data is copied")
// Read through the file looking for shinfo entries
new parm[2]
parm[0] = id
parm[1] = 0
adminCopyVHelper(parm)
//Rest of this is done in the helper function
return PLUGIN_HANDLED
}
public adminCopyVHelper(parm[])
{
//Get data from parm
new id = parm[0]
new nextLine = parm[1]
// Read through the file looking for shinfo entries
new lengthRead
new data[512], Right[401], Left[111]
while ((nextLine = read_file(g_VaultFile,nextLine,data,511,lengthRead)) != 0) {
if ( lengthRead > 0 && equali(data, "PokeMod", 7) ) {
strbreak(data, Left, 110, Right, 400)
replace(Left,110,"PokeMod-",EMPTY)
writeData(0, Left, Right)
if (nextLine % 200 == 0) {
parm[1] = nextLine
console_print(id,"Delaying a few seconds before copying the next set of entries")
set_task(3.0, "adminCopyVHelper",0,parm,2)
return
}
}
}
//If it makes it this far it must be done copying
// OK now load the XP for any players playing
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for( new x=0; x < pnum; x++ )
LoadXP(players[x])
console_print(id,"Saved XP has been copied from the vault to the NVault Database Successfully")
}
#endif
public LoadXP(id)
{
if( !PM_Loaded ){
g_Connected[id] = 0;
return false;
}
if( g_isWild[id] > 0 )
return true
if( !SaveXPon() )
return true
new key[35]
if( getSaveKey(id, key, true) )
{
#if SAVE==SAVE_NVAULT
new Right[1501]
new vaultSaveKey[40], time
formatex(vaultSaveKey,39,"PokeMod-%s",key)
nvault_lookup(nvault_db, key, Right, 1500, time)
#endif
#if SAVE==SAVE_VAULT
new Right[1501]
new vaultSaveKey[40]
formatex(vaultSaveKey,39,"PokeMod-%s",key)
get_vaultdata(vaultSaveKey, Right, 1500)
#endif
#if SAVE==SAVE_MYSQL
new Right[1501]
new sql[512], error[128]
new Result:retvalxp
mySQLConnect()
if ( gMySQL <= SQL_FAILED ) return false
formatex(sql, 511, "SELECT `XPS` FROM `pm_save` WHERE `SAVE_KEY` = '%s'", key)
retvalxp = dbi_query(gMySQL,sql)
if(retvalxp <= RESULT_FAILED){
dbi_error(gMySQL,error,127)
debugMessage(id,0,"Error Querying MySQL DB for %s: '%s' - '%s'", key, error, sql)
//Closes the connection if set not to be persistent
close_mysql()
return false
}
else if (!dbi_nextrow(retvalxp)) {
dbi_error(gMySQL,error,127)
debugMessage(id,3,"No Saved XP Loaded for %s: '%s'", key, error)
if (retvalxp >= RESULT_OK) dbi_free_result(retvalxp)
//Closes the connection if set not to be persistent
close_mysql()
g_Connected[id] = -1
return true
}
dbi_field(retvalxp, 1, Right, 500)
#endif
#if SAVE==SAVE_SQLX
if(SqlConnection == Empty_Handle)
return false
new sql[512]
new data[2]
data[0] = SQLX_LOADXP
data[1] = id
formatex(sql, 511, "SELECT `XPS` FROM `pm_save` WHERE `SAVE_KEY` = '%s'", key)
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
return true
#else //Only SQLx won't be handling it straight from here
return HandleLoad(id,Right)
#endif
}
g_Connected[id] = 0;
return false;
}
HandleLoad(id, Right[1501])
{
debugMessage(id,8,"loading %s",Right );
//we don't have any saved data
if(equali(Right,EMPTY))
return NewPlayerSettings(id);
new Left[51], i;
for( i = 0; i<MAX_POKES; i++)
{
strbreak(Right, Left, 50, Right, 1500)
if( equal(Left, COLON, 1) ) break //stop if this is the end of the data we want to look at
PlayersPoke[id][i] = str_to_num(Left)
strbreak(Right, Left, 50, Right, 1500)
if( equal(Left, COLON, 1) ) break //stop if this is the end of the data we want to look at
PlayersXP[id][i] = str_to_num(Left)
}
while( !equal(Left, COLON, 1) && !equali(Right,EMPTY)){ //if we didn't stop because we found a :, lets get the next one
strbreak(Right, Left, 50, Right, 1500)
}
//we ran out of data
if(equali(Right,EMPTY))
return NewPlayerSettings(id, true);
strbreak(Right, Left, 50, Right, 1500)
if( !equal(Left, COLON, 1) ){ //we found the time, and not the next seperator
PlayersTime[id] = str_to_num(Left)
}
while( !equal(Left, COLON, 1) && !equali(Right,EMPTY)) //if we didn't stop because we found a :, lets get the next one
strbreak(Right, Left, 50, Right, 1500)
//strbreak(Right, Left, 50, Right, 1500)
if( equal(Left, COLON, 1) ){ //we found the seperator, now this will break it down in here
for( i = 0; i<MAX_SETS; i++)
{
strbreak(Right, Left, 50, Right, 1500)
if( equal(Left, COLON, 1) ) break //stop if this is the end of the data we want to look at
PlayersSet[id][i] = str_to_num(Left)
}
}
while( !equal(Left, COLON, 1) && !equali(Right,EMPTY)) //if we didn't stop because we found a :, lets get the next one
strbreak(Right, Left, 50, Right, 1500)
strbreak(Right, Left, 50, Right, 1500)
if( !equal(Left, COLON, 1) ){ //we found their catches
PlayersCatch[id] = str_to_num(Left)
}
if( is_user_bot(id) )
BotSelect(id);
return ConnectPlayer(id)
}
NewPlayerSettings(id, bool:had_pokemon=false)
{
PlayersSet[id][SET_HUD_Y] = -4;
if( !had_pokemon )
g_Connected[id] = -1;
else
return ConnectPlayer(id);
return true;
}
ConnectPlayer(id)
{
g_Connected[id] = 1
RefreshPoke(id)
return true
}
public load_all()
{
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for( new i=0; i<pnum; i++)
LoadXP(players[i])
#if POKERANK_SYSTEM==1
LoadRanks()
#endif
}
public save_all()
{
poke_print(0, print_center, "%s Saving All Data",PREFIX);
new players[MAX_PLAYERS], pnum;
poke_get_players(players, pnum);
for( new i=0; i<pnum; i++)
set_task( 1.5*(i+1), "delayed_save", players[i]);
#if POKERANK_SYSTEM==1
SaveRanks();
#endif
}
public delayed_save(id)
SaveXP(id, -1);
SaveXP(id, forced=1)
{
if(g_isWild[id]>0)
return false;
static key[35]
static Float:last_save[MAX_PLAYERS+1], Float:time_left, Float:current_time;
if( id ){
current_time = get_gametime();
time_left = current_time - last_save[id];
if( forced < 1 && time_left < SAVE_SPAM){
if( !forced )
poke_print(id, print_chat, "You must wait %0.1f seconds before saving again.", SAVE_SPAM-time_left);
return false;
}
last_save[id] = current_time;
}
if( g_Connected[id] && getSaveKey(id, key) && SaveXPon() )
{
RefreshPoke(id)
new Data[1501], iLen = 0, i
//save their pokemon and xp
for(i = 0; i<MAX_POKES; i++)
iLen += formatex(Data[iLen],(1501-iLen),"%d %d ", PlayersPoke[id][i], PlayersXP[id][i])
//save the time
iLen += copy(Data[iLen],(1501-iLen),": ")
iLen += formatex(Data[iLen],(1501-iLen),"%d ",get_systime())
iLen += copy(Data[iLen],(1501-iLen),": ")
//save their settings
for(i = 0; i<MAX_SETS; i++)
iLen += formatex(Data[iLen],(1501-iLen),"%d ", PlayersSet[id][i])
//save their pokerank crap
iLen += formatex(Data[iLen],(1501-iLen),": %d",PlayersCatch[id])
writeData(id, key, Data)
debugMessage(id,5,"saved data with save key %s", key)
return true;
}
return false;
}
//thanks to SHmod
getSaveKey(id, key[35]="", bool:update=false)
{
static player_key[MAX_PLAYERS+1][35];
if( update ) {
if(is_user_bot(id)) {
new botname[32]
get_user_name(id,botname,31)
//Get Rid of BOT Tag
//PODBot
replace(botname,31,"[POD]",EMPTY)
replace(botname,31,"[P*D]",EMPTY)
replace(botname,31,"[P0D]",EMPTY)
//CZ Bots
replace(botname,31,"[BOT] ",EMPTY)
//Attempt to get rid of the skill tag so we save with bots true name
new lastchar = strlen(botname) - 1
if ( equal(botname[lastchar],")",1) ) {
new x
for ( x = lastchar - 1; x > 0; x--) {
if ( equal(botname[x],"(",1) ) {
botname[x - 1] = 0
break
}
if ( !isdigit(botname[x]) ) break
}
}
if (strlen(botname) > 0 ) {
#if SAVE==SAVE_MYSQL || SAVE==SAVE_SQLX
replace_all(botname,31,"`","\\`")
replace_all(botname,31,"'","\\'")
#endif
replace_all(botname,31," ","_")
formatex( player_key[id], 34, "[BOT]%s", botname )
}
}
//Hack for STEAM's retardedness with listen servers
else if (!is_dedicated_server() && id == 1) {
copy( player_key[id], 34, "loopback" )
}
else {
if (get_pcvar_num(sv_lan) == 1) {
get_user_ip( id, player_key[id], 34, 1 ) // by ip without port
}
else {
get_user_authid( id, player_key[id], 34 ) // by steamid
if( equali(player_key[id],"STEAM_ID_LAN") || equali(player_key[id],"4294967295") ){
get_user_ip( id, player_key[id], 34, 1 ) // by ip without port
}
}
}
debugMessage(id,5,"updated savekey");
}
//Check to make sure we got something useable
if( equali(player_key[id], "STEAM_ID_PENDING") || equali(player_key[id], EMPTY) ){
debugMessage(id,5,"does not have a valid savekey ('%s')", player_key[id]);
return false;
}
copy( key, 34, player_key[id] );
return true;
}
///////////////////////////
// Levels a pokemon up //
///////////////////////////
LevelUpPokemon(id, num, levels=1, take_item=MAX_ITEMS)
{
new pastlevel = PlayersLevel(id, num)
new pname[NAME_LENGTH]
PokeToName(PlayersPoke[id][num], pname, NAME_LENGTH)
if( take_item != MAX_ITEMS ){
if(pastlevel == TotalLevels){
poke_print(id, print_chat, "%s ma maksymalny poziom.",pname)
return false
}
PlayersItem[id][take_item]--
}
new newlevel = pastlevel+levels
if(newlevel > TotalLevels)
newlevel = TotalLevels
PlayersXP[id][num] = PokeLevels[newlevel-1]
poke_print(id, print_chat, "%s ma teraz poziom %d",pname,newlevel)
Check_Evolve(id, PlayersPoke[id][num], newlevel)
return true
}
///////////////////////////////////////
// Returns what level a players is //
///////////////////////////////////////
PlayersLevel(id, num=-1 )
{
if(0>id || id>MAX_PLAYERS)
return 0;
if(Safari())
return SafariLevel(Pokemon[id]);
if( num == -1 )
num = PlayersActive[id];
if(MAX_POKES<=num || num<0)
return 0;
static i;
i = 1;
if(g_isWild[id]<1){
while(PlayersXP[id][num]>=PokeLevels[i]){
i++;
if(i==TotalLevels)
break;
}
}
else{
while(PlayersXP[id][num]>=PokeLevels[i]/2){
i++;
if(i==TotalLevels)
break;
}
}
#if RARE_CANDY_MODE == 1 || RARE_CANDY_MODE == 3
static k;
for(k=0; k<ItemsCreated; k++)
if( ItemInfo[k] & II_LEVEL )
i += PlayersItem[id][k];
#endif
return i;
}
/////////////////////////////////////////////
// Returns what players average level is //
/////////////////////////////////////////////
AverageLevel(id)
{
if(Safari())
return SafariLevel(Pokemon[id]);
if(g_isWild[id]>0)
return PlayersLevel(id, 0);
new pokes, total
for(new i = 0; i<MAX_ACTIVE_POKES; i++)
{
if(PlayersPoke[id][i]){
pokes++;
total += PlayersLevel(id, i);
}
}
if(pokes){
new average = total/pokes;
return average;
}
return 0
}
/////////////////////////////////////
// Adds a pokemon to playerspoke //
/////////////////////////////////////
bool:AddPoke(id, pid, xp=1, giver=0)
{
RefreshPoke(id);
if(!ValidPoke(pid) || AvailableSlot(id, pid)!=AS_OK || Safari())
return false;
#if RCON_POKEADMINS == 1
if( giver && SpecialPoke(pid) && !(get_user_flags(giver)&ADMIN_RCON) )
return false;
#endif
if(!xp)
xp = 1;
new i = Slot(id);
PlayersPoke[id][i] = pid;
PlayersXP[id][i] = xp;
ShowPokeInfo(id, pid);
SaveXP(id);
return true;
}
////////////////
// Gives XP //
////////////////
GiveXP(id, poke, amount)
{
if(Safari())
return
if(MAX_POKES<=poke || poke<0 || !PlayersPoke[id][poke])
return
new oldlevel, newlevel
oldlevel = PlayersLevel(id, poke)
PlayersXP[id][poke] += amount
newlevel = PlayersLevel(id, poke)
if(PlayersXP[id][poke]<1)
PlayersXP[id][poke] = 1
if(oldlevel<newlevel){
new oldmax = PlayerStat[id][STAT_MAXHP]
new name[32]
get_user_name(id, name, 31)
poke_print(0, print_chat, "Gratulacje %s! %s ma teraz poziom %d!",name,PokeToName(PlayersPoke[id][poke]),newlevel)
//ding for level up
poke_sound(id, CHAN_AUTO, SND_BELL)
if(is_user_alive(id)){
get_user_origin(id, origin[id])
//sprites to show level up (only once)
message_begin(MSG_BROADCAST ,SVC_TEMPENTITY) //message begin
write_byte(TE_LARGEFUNNEL)
write_coord(origin[id][0]) // funnel position
write_coord(origin[id][1])
write_coord(origin[id][2]-32)
write_short(SPRITE_INDEX[SPR_MUZZLEFLASH1]) // sprite index
write_short(8) // flags
message_end()
}
Check_Evolve(id, PlayersPoke[id][poke], newlevel)
#if POKERANK_SYSTEM==1
PlayersCatch[id] += newlevel
CheckMaxHP(id)
if(oldmax!=PlayerStat[id][STAT_MAXHP]){
poke_print(id, print_chat, "Twoje max HP to %d! Twoj PokeRank to: %d",PlayerStat[id][STAT_MAXHP],PlayersCatch[id])
}
else
poke_print(id, print_chat, "Twoj PokeRank to %d",PlayersCatch[id])
#else
CheckMaxHP(id)
if(oldmax!=PlayerStat[id][STAT_MAXHP]){
poke_print(id, print_chat, "Twoje max HP to %d!",PlayerStat[id][STAT_MAXHP])
}
#endif
}
else if(oldlevel>newlevel){
new oldmax = PlayerStat[id][STAT_MAXHP]
new name[32]
get_user_name(id, name, 31)
poke_print(id, print_chat, "%s, %s ma teraz poziom %d.",name,PokeToName(PlayersPoke[id][poke]),newlevel)
#if POKERANK_SYSTEM==1
PlayersCatch[id] -= oldlevel
CheckMaxHP(id)
if(oldmax!=PlayerStat[id][STAT_MAXHP]){
poke_print(id, print_chat, "Twoje max HP to %d. Twoj PokeRank to: %d",PlayerStat[id][STAT_MAXHP],PlayersCatch[id])
}
else
poke_print(id, print_chat, "Twoj PokeRank to: %d",PlayersCatch[id])
#else
CheckMaxHP(id)
if(oldmax!=PlayerStat[id][STAT_MAXHP]){
poke_print(id, print_chat, "Twoje max HP to %d.",PlayerStat[id][STAT_MAXHP])
}
#endif
#if POKEMON_UNEVOLVE==1
Check_UnEvolve(id, PlayersPoke[id][poke])
#endif
}
#if POKERANK_SYSTEM==1
if(oldlevel != newlevel){
if(SpecialRank(id)!=-1) //update their thing, and check if they went higher
UpdateSpecialRank(id)
else
CheckUpdateRank(id) //only check if they went higher than the last person in Elite Four
}
#endif
}
/////////////////////
// Gives Kill XP //
/////////////////////
KillXP(attacker, victim)
{
if(attacker==victim)
return
new xp_to_give = PlayersLevel(victim)
if( Team(attacker) == Team(victim) ){
GiveXP(attacker, PlayersActive[attacker], -1*xp_to_give)
poke_print(attacker, print_chat, "You lost %d experience for killing a teamate.",xp_to_give)
}
else
GiveXP(attacker, PlayersActive[attacker], xp_to_give)
}
/////////////////////////
// Adds level to num //
/////////////////////////
AddLvl(id, num)
{
num += PlayersLevel(id);
return true;
}
///////////////////////////
// Adds level to float //
///////////////////////////
f_AddLvl(id, Float:num)
{
num += PlayersLevel(id);
return true;
}
////////////////////////////////
// Switches a users pokemon //
////////////////////////////////
SwitchPoke(id, pid, bool:force=true)
{
if( !ValidPoke(pid) )
return false;
if( pid == Pokemon[id] )
return true;
#if ADMIN_SPECIAL == 1
if( SpecialPoke(pid) && !poke_access(id) ){
poke_print(id, print_chat, "This server is restricting who can use %s.",PokeToName(pid));
return false;
}
#endif
if(Safari()){
if(SafariLevel(pid)){
ResetSkills(id, false)
Pokemon[id] = pid
SetSpeed(id)
return true
}
return false
}
#if CHANGE_POKES > 0
if( !force && ChangedPoke[id] < 1 && is_user_alive(id) ){
#if CHANGE_POKES > 1
poke_print(id, print_chat, "This server is only allowing you to change pokemon %d times while you are alive.",CHANGE_POKES)
#else
poke_print(id, print_chat, "This server is only allowing you to change pokemon 1 time while you are alive.")
#endif
return false
}
#else
#if CHANGE_POKES == -1
if( is_user_bot(id) && ChangedPoke[id] == 0 )
return false
#endif
#endif
for(new i=0; i<MAX_ACTIVE_POKES; i++){
if(PlayersPoke[id][i]==pid){
ResetSkills(id, false)
Pokemon[id] = pid
PlayersActive[id] = i
SetSpeed(id)
#if CHANGE_POKES > 0
ChangedPoke[id]--
#endif
if( !force && CHANGE_DELAY > 0.0 )
bind_used(id, _, CHANGE_DELAY);
return true
}
}
return false
}
////////////////////////////////
// Releases a users pokemon //
////////////////////////////////
ReleasePoke(id, pid, bool:allow_cancel=true)
{
if( !ValidPoke(pid) )
return
new slot = Slot(id, pid, CHECK_ALL)
if(slot!=-1){
if(allow_cancel){
if( slot == PlayersActive[id] ){
poke_print(id, print_chat, "Nie mozesz wypuscic swojego aktywnego Pokemona.");
return;
}
if( task_exists(id+RELEASE_TASK) ){
poke_print(id, print_chat, "Mozesz wypuszczac tylko 1 Pokemon naraz.");
return;
}
new parm[2]
parm[0] = id
parm[1] = pid
set_task(RELEASE_TIME/2, "ReleaseRemind", id+RELEASE2_TASK, parm, 2)
set_task(RELEASE_TIME, "FinalRelease", id+RELEASE_TASK, parm, 2)
poke_print(id, print_chat, "Masz %.1f seconds by napisac /cancel i nie wypuscic %s. Albo napisz /finalrelease do natychmiastowego wypusczenia.",RELEASE_TIME,PokeToName(pid))
}
else{
PlayersPoke[id][slot] = 0
PlayersXP[id][slot] = 0
SaveXP(id)
if( !SwitchPoke(id, Pokemon[id]) )
SwitchPoke(id, PlayersPoke[id][PlayersActive[id]])
}
}
}
public ReleaseRemind(parm[])
{
poke_print(parm[0], print_chat, "%s zostanie wypuszczony w ciagu %.1f sekund. Napisz /cancel by anulowac wypuszczenie.",PokeToName(parm[1]),RELEASE_TIME/2)
}
public FinalRelease(parm[])
{
new id = parm[0], poke = parm[1];
new slot = Slot(id, poke, CHECK_ALL)
if( slot != -1 ){
poke_print(id, print_chat, "%s zostal wypuszczony.",PokeToName(poke))
PlayersPoke[id][slot] = 0
PlayersXP[id][slot] = 0
SaveXP(id)
}
}
////////////////////////////
// Trades users pokemon //
////////////////////////////
TradePoke(id, pid, nid)
{
if( !g_Connected[id] || !ValidPoke(pid) || !g_Connected[nid] )
return false
#if RCON_POKEADMINS == 1
if( SpecialPoke(pid) && !(get_user_flags(id)&ADMIN_RCON) ){
poke_print(id, print_chat, "Nie mozesz dac swojego specjalnego Pokemona.");
return false;
}
#endif
new pnum = HasPokemon(id, pid, CHECK_ALL)
if( pnum >= 0 ){
if( pnum == PlayersActive[id] ){
poke_print(id, print_chat, "Nie mozesz dac swojego aktywnego Pokemona.");
return false;
}
new name[32], Nname[32], pname[NAME_LENGTH]
get_user_name(id, name, 31)
get_user_name(nid, Nname, 31)
PokeToName(pid, pname, NAME_LENGTH)
switch(AvailableSlot(nid, pid))
{
case AS_OK:{
new i = Slot(nid)
PlayersPoke[nid][i] = PlayersPoke[id][pnum]
PlayersXP[nid][i] = PlayersXP[id][pnum]
#if POKE_POPULATION!=2
ReleasePoke(id, pid, false);
#endif
poke_print(nid, print_chat, "%s dales %s.", name, pname)
poke_print(id, print_chat, "Dales %s swojego %s.", Nname, pname)
Check_Trade_Evolve(nid, pid);
return true;
}
case AS_NOGOOD:
poke_print(id, print_chat, "Nie mozesz dac Pokemonow dzikim gracza.")
case AS_NOROOM:
poke_print(id, print_chat, "%s ma za duzo Pokemonow.", Nname)
case AS_DUPLICATE:
poke_print(id, print_chat, "%s ma na razie %s.", Nname, pname)
}
}
else
poke_print(id, print_chat, "Nie masz %s do dania.", PokeToName(pid))
return false
}
////////////////////////////////
// Gets rid of Pokemod info ///////////// TY SHmod ///////////
////////////////////////////////
cleanXP(bool:clear_all=false)
{
#if SAVE==SAVE_VAULT
// Open up the vault file - read line by line
// Use vault to delete to any data over a certain age
if ( !file_exists(g_VaultFile) ) return
// Read through the file looking for pokemod entries
new lengthRead, nextLine = 0, last_time = (get_ppcvar_num(pm_xpsavedays) * SECONDS_IN_DAY)
new data[1501], key[35]
// This is an imperfect clean - but gets the job done
// Vault needs to have a way to walk it
// Deleting a Key can actually reorder the vault.ini file
while ((nextLine = read_file(g_VaultFile,nextLine,data,1500,lengthRead)) != 0) {
if ( lengthRead > 0 && equali(data, "PokeMod", 7) ) {
parse(data, key, 34)
if ( clear_all ) {
remove_vaultdata( key )
// since remove_vaultdata can reorder the whole file - we will go back some lines
nextLine = max(nextLine - 1, 0)
}
else {
HandleLoad(0, data)
if( PlayersTime[0] + last_time < get_systime() ){
remove_vaultdata( key )
// since remove_vaultdata can reorder the whole file - we will go back some lines
nextLine = max(nextLine - 1, 0)
}
}
}
}
#endif
#if SAVE==SAVE_NVAULT
if(clear_all)
nvault_prune(nvault_db, 0, get_systime())
else
nvault_prune(nvault_db, 0, get_systime() - (SECONDS_IN_DAY*get_ppcvar_num(pm_xpsavedays)) )
#endif
#if SAVE==SAVE_MYSQL
new error[127], sql[255]
new Result:retval
mySQLConnect()
if( gMySQL <= SQL_FAILED ) return
if(clear_all){
copy(sql, 254, "TRUNCATE TABLE `pm_save`")
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Couldn't Erase XP: '%s' - '%s' - %d", error, sql, gMySQL)
return
}
}
else{
if ( SQL_TYPE == SQL_SQLITE )
formatex( sql, 254, "DELETE FROM `pm_save` WHERE ((julianday(`time`) + %d) < julianday('now'))", get_ppcvar_num(pm_xpsavedays) );
else
formatex(sql, 254, "DELETE FROM `pm_save` WHERE pm_save.`LAST_PLAY_DATE` < (SYSDATE() - INTERVAL '%d' DAY)", get_ppcvar_num(pm_xpsavedays) )
retval = dbi_query(gMySQL,sql)
if (retval <= RESULT_FAILED) {
dbi_error(gMySQL,error,127)
debugMessage(0,0,"Couldn't Erase XP: '%s' - '%s' - %d", error, sql, gMySQL)
return
}
// Vacuum the SQL LITE DB Table
if ( SQL_TYPE == SQL_SQLITE )
{
copy( sql, 254, "VACUUM `pm_save`" );
dbi_query( gMySQL, sql );
}
}
//Closes the connection if set not to be persistent
close_mysql()
#endif
#if SAVE==SAVE_SQLX
new sql[512]
new data[2]
data[0] = 0
data[1] = 0
if(SqlConnection == Empty_Handle)
return
if(clear_all)
copy(sql, 511, "TRUNCATE TABLE `pm_save`")
else
formatex(sql, 511, "DELETE FROM `pm_save` WHERE pm_save.`LAST_PLAY_DATE` < (SYSDATE() - INTERVAL '%d' DAY)", get_ppcvar_num(pm_xpsavedays) )
SQL_ThreadQuery(SqlConnection, "SQLX_Handler", sql, data, 2);
#endif
}
SafariLevel(poke)
return SafariLevels[poke]
public SetSafariLevels()
{
new PokeFile[128];
Poke_FileName( F_Safari, PokeFile);
new Data[256]
new Left[NAME_LENGTH], Right[151], LeftN, RightN
new f = fopen(PokeFile, "rt");
while( !feof(f) ){
fgets(f, Data, 255);
if( !ValidData( Data ) )
continue;
strbreak(Data, Left, NAME_LENGTH-1, Right, 150)
LeftN = NameToPoke(Left)
if( !LeftN )
continue
strbreak(Right, Left, NAME_LENGTH-1, Right, 150)
RightN = str_to_num(Left)
if( RightN ){
SafariLevels[LeftN] = RightN
}
}
fclose(f);
}
#if ALLOW_WILD==1
AssignWild(id, bool:first_time=false)
{
new poke;
do poke = random_num(1,PokesCreated);
while( !BasePoke(poke)
|| ( random_num(1,PokesCreated) != poke && !poke_access(id) && SpecialPoke(poke) )
|| PokeDisabled(poke)
)
if(first_time){
new name[32]
get_user_name(id, name, 31)
poke_print(0, print_chat, "%s opuscil mape.",name)
SaveXP(id)
for(new i=0; i<MAX_POKES; i++){
PlayersPoke[id][i] = 0
PlayersXP[id][i] = 0
}
}
Pokemon[id] = poke
PlayersActive[id] = 0
PlayersPoke[id][0] = poke
PlayersXP[id][0] = PokeLevels[random_num(1, get_ppcvar_num(pm_wild_level))-1]/2
new pname[NAME_LENGTH]
PokeToName(poke, pname, NAME_LENGTH)
poke_print(0, print_chat, "A wild %s has appeared on the map.",pname)
poke_print(id, print_center, "Jestes dzikim %s",pname)
}
UnAssignWild(id)
{
if(WildCount()<=get_ppcvar_num(pm_wild) && get_ppcvar_num(pm_wild)>0){
poke_print(id, print_chat, "Nie jestes wystarczojaco dzikim Pokemonem by dojsc do Trenera.(%d/%d)", WildCount(), get_ppcvar_num(pm_wild))
return
}
new name[32]
get_user_name(id, name, 31)
if(is_user_alive(id))
poke_print(0, print_chat, "Dziki %s opuscil mape.",PokeToName(Pokemon[id]))
poke_print(0, print_chat, "%s has joined the map.",name)
LoadXP(id)
}
WildCount()
{
new count
new players[MAX_PLAYERS], pnum
poke_get_players(players, pnum)
for(new i=0; i<pnum; i++){
if(g_isWild[players[i]]>0)
count++
}
return count
}
public WildMessage()
{
if(!Safari() && get_ppcvar_num(pm_wild)>0){
poke_print(0, print_chat, "Ten serwer potrzebuje %d dzikich pokemonow. Napisz /trainer albo /wild do zmiany.", get_ppcvar_num(pm_wild))
}
}
#endif
Użytkownik Szyfrant edytował ten post 30.08.2010 22:20
Taka ilośc lini w załączniku