2018-12-22 11:01:10 +00:00
/*
* Irresistible Gaming (c) 2018
* Developed by Lorenc
* Module: cnr\vip\redeem_code.pwn
* Purpose: code redemption system for newly donating donors
*/
/* ** Includes ** */
#include < YSI\y_hooks >
2018-12-22 23:58:03 +00:00
/* ** Error Checking ** */
#if !defined __cnr__irresistiblecoins
#endinput
#endif
2018-12-22 11:01:10 +00:00
/* ** Definitions ** */
#define szRedemptionSalt "7resta#ecacakumedeM=yespawr!d@et"
/* ** Variables ** */
enum E_DONATION_DATA
{
E_TRANSACTION_ID[ 17 ],
E_NAME[ 24 ],
E_AMOUNT[ 11 ],
E_PURPOSE[ 64 ],
E_DATE
};
static stock g_redeemVipWait = 0;
static stock g_TopDonorWall = INVALID_OBJECT_ID;
stock Text: g_TopDonorTD = Text: INVALID_TEXT_DRAW;
/* ** Forwards ** */
forward OnDonationRedemptionResponse( index, response_code, data[ ] );
/* ** Hooks ** */
hook OnScriptInit( )
{
2019-01-12 11:27:45 +00:00
// Server Variables
AddServerVariable( "donation_goal_amount", "250.0", GLOBAL_VARTYPE_FLOAT );
2018-12-22 11:01:10 +00:00
// Wall of Donors
SetDynamicObjectMaterialText( CreateDynamicObject( 3074, -1574.3559, 885.1296, 28.4690, 0.0000, 0.0000, -0.0156 ), 0, "Thx Monthly Donors", 130, "Times New Roman", 64, 1, -65536, 0, 1 );
SetDynamicObjectMaterialText( ( g_TopDonorWall = CreateDynamicObject( 3074, -1574.3559, 885.1296, 14.0153, 0.0000, 0.0000, -0.0156 ) ), 0, "Nobody donated :(", 130, "Arial", 48, 0, -65536, 0, 1 );
// Latest Donor TD
2019-05-29 13:05:13 +00:00
g_TopDonorTD = TextDrawCreate(320.000000, 2.000000, "Top Donor " SERVER_OPERATOR " - $0.00, ~w~~h~~h~Latest Donor " SERVER_OPERATOR " - $0.00");
2018-12-22 11:01:10 +00:00
TextDrawAlignment(g_TopDonorTD, 2);
TextDrawBackgroundColor(g_TopDonorTD, 0);
TextDrawFont(g_TopDonorTD, 1);
TextDrawLetterSize(g_TopDonorTD, 0.139999, 0.799999);
TextDrawColor(g_TopDonorTD, -2347265);
TextDrawSetOutline(g_TopDonorTD, 1);
TextDrawSetProportional(g_TopDonorTD, 1);
2019-02-23 08:11:33 +00:00
return 1;
}
2018-12-22 11:01:10 +00:00
2019-02-23 08:11:33 +00:00
hook OnServerVariablesLoaded( )
{
2018-12-22 11:01:10 +00:00
UpdateGlobalDonated( );
2019-01-06 01:06:01 +00:00
return 1;
2018-12-22 11:01:10 +00:00
}
hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] )
{
if ( dialogid == DIALOG_VIP && response )
{
if ( strlen( inputtext ) != 16 )
{
cmd_donated( playerid, "" );
return SendError( playerid, "The transaction ID you entered is invalid." );
}
if ( g_redeemVipWait > g_iTime )
{
cmd_donated( playerid, "" );
return SendServerMessage( playerid, "Our anti-exploit system requires you to wait another %d seconds before redeeming.", g_redeemVipWait - g_iTime );
}
HTTP( playerid, HTTP_GET, sprintf( "donate.sfcnr.com/validate_code/%s", inputtext ), "", "OnDonationRedemptionResponse" );
SendServerMessage( playerid, "We're now looking up this transaction. Please wait." );
return 1;
}
else if ( dialogid == DIALOG_DONATED )
{
szLargeString[ 0 ] = '\0';
strcat( szLargeString, ""COL_WHITE"Thank you a lot for donating! :D In return for your dignity, you have received Irresistible Coins.\n\n"\
""COL_GREY" * What do I do with Irresistible Coins?"COL_WHITE" You can claim the V.I.P of your choice via "COL_GREY"/irresistiblecoins market"COL_WHITE".\n" );
strcat( szLargeString, ""COL_GREY" * How many do I have?"COL_WHITE" You can see how many Irresistible Coins you have via "COL_GREY"/irresistiblecoins"COL_WHITE".\n" \
2019-05-29 13:05:13 +00:00
""COL_GREY" * I'm unsure, help?"COL_WHITE" If you have any questions, please /ask otherwise enquire " SERVER_OPERATOR " via the forums!\n\nThank you once again for your contribution to our community! :P" );
2018-12-22 11:01:10 +00:00
return ShowPlayerDialog( playerid, DIALOG_FINISHED_DONATING, DIALOG_STYLE_MSGBOX, ""COL_GOLD"SF-CNR Donation", szLargeString, "Got it!", "" );
}
else if ( dialogid == DIALOG_FINISHED_DONATING )
{
return ShowPlayerDialog( playerid, DIALOG_LATEST_DONOR, DIALOG_STYLE_MSGBOX, ""COL_GOLD"SF-CNR Donation", ""COL_WHITE"Would you like to be shown as the latest donor?", "Yes", "No" );
}
else if ( dialogid == DIALOG_LATEST_DONOR )
{
if ( GetPVarType( playerid, "just_donated" ) != PLAYER_VARTYPE_FLOAT )
2019-05-29 13:05:13 +00:00
return SendError( playerid, "Seems to be an issue where we couldn't find how much you donated. Report to " SERVER_OPERATOR "." );
2018-12-22 11:01:10 +00:00
new
Float: fAmount = GetPVarFloat( playerid, "just_donated" );
DeletePVar( playerid, "just_donated" );
return UpdateGlobalDonated( playerid, fAmount, !response );
}
return 1;
}
/* ** Callbacks ** */
public OnDonationRedemptionResponse( index, response_code, data[ ] )
{
if ( response_code == 200 )
{
if ( strmatch( data, "{FFFFFF}Unable to identify transaction." ) ) ShowPlayerDialog( index, DIALOG_NULL, DIALOG_STYLE_MSGBOX, ""COL_GOLD"SF-CNR Donation", data, "Okay", "" );
else
{
static aDonation[ E_DONATION_DATA ];
sscanf( data, "p<|>e<s[17]s[24]s[11]s[64]d>", aDonation );
// printf("donation {id:%s, name:%s, amount:%s, purpose:%s, date:%d}", aDonation[ E_TRANSACTION_ID ],aDonation[ E_NAME ],aDonation[ E_AMOUNT ],aDonation[ E_PURPOSE ],aDonation[ E_DATE ]);
if ( strfind( aDonation[ E_PURPOSE ], "San Fierro: Cops And Robbers" ) == -1 ) {
ShowPlayerDialog( index, DIALOG_NULL, DIALOG_STYLE_MSGBOX, ""COL_GOLD"SF-CNR Donation", ""COL_WHITE"This donation is not specifically for this server thus you are unable to retrieve anything.", "Okay", "" );
return 0;
}
// SELECT * FROM `REDEEMED` WHERE `ID` = MD5('%s7resta#ecacakumedeM=yespawr!d@et') LIMIT 0,1
mysql_format( dbHandle, szNormalString, sizeof( szNormalString ), "SELECT * FROM `REDEEMED` WHERE `ID` = MD5('%e%s') LIMIT 0,1", aDonation[ E_TRANSACTION_ID ], szRedemptionSalt );
mysql_tquery( dbHandle, szNormalString, "OnCheckForRedeemedVIP", "is", index, data );
}
}
else
{
return ShowPlayerDialog( index, DIALOG_NULL, DIALOG_STYLE_MSGBOX, ""COL_GOLD"SF-CNR Donation", ""COL_WHITE"Unable to connect to the donation database. Please try again later.", "Okay", "" );
}
return 1;
}
/* ** SQL Threads ** */
thread OnCheckForRedeemedVIP( playerid, data[ ] )
{
static
aDonation[ E_DONATION_DATA ],
rows, fields
;
cache_get_data( rows, fields );
if ( rows )
{
static
szName[ MAX_PLAYER_NAME ];
cache_get_field_content( 0, "REDEEMER", szName );
ShowPlayerDialog( playerid, DIALOG_NULL, DIALOG_STYLE_MSGBOX, ""COL_GOLD"SF-CNR Donation", sprintf( ""COL_WHITE"Sorry this transaction ID has already been redeemed by %s.", szName ), "Okay", "" );
}
else
{
g_redeemVipWait = g_iTime + 10;
sscanf( data, "p<|>e<s[17]s[24]s[11]s[64]d>", aDonation );
mysql_format( dbHandle, szNormalString, sizeof( szNormalString ), "INSERT INTO `REDEEMED`(`ID`, `REDEEMER`) VALUES (MD5('%e%s'), '%e')", aDonation[ E_TRANSACTION_ID ], szRedemptionSalt, ReturnPlayerName( playerid ) );
mysql_single_query( szNormalString );
//printf( "%s\n%s | %s | %f | %s | %d", data, aDonation[ E_TRANSACTION_ID ], aDonation[ E_EMAIL ], floatstr( aDonation[ E_AMOUNT ] ), aDonation[ E_PURPOSE ], aDonation[ E_DATE ]);
new
Float: fAmount = floatstr( aDonation[ E_AMOUNT ] ),
Float: iCoins = fAmount * ( 1 + GetGVarFloat( "vip_bonus" ) ) * 100.0
;
if ( p_Uptime[ playerid ] > 604800 )
{
if ( fAmount < 1.99999 )
return SendError( playerid, "Thanks for donating! As this donation was under $2.00 USD, no coin has been issued." );
}
else
{
if ( fAmount < 4.99999 )
return SendError( playerid, "Thanks for donating! As this donation was under $5.00 USD, no coins have been issued." );
}
2019-01-01 13:19:17 +00:00
GivePlayerIrresistibleCoins( playerid, iCoins );
2018-12-22 11:01:10 +00:00
SetPVarFloat( playerid, "just_donated", fAmount );
SendClientMessageFormatted( playerid, -1, ""COL_GOLD"[VIP PACKAGE]"COL_WHITE" You have received %0.0f Irresistible Coins! Thanks for donating %s!!! :D", iCoins, ReturnPlayerName( playerid ) );
format( szBigString, 256, ""COL_GREY"Transaction ID:\t"COL_WHITE"%s\n"COL_GREY"Donor Name:\t"COL_WHITE"%s\n"COL_GREY"Amount:\t"COL_WHITE"$%0.2f\n"COL_GREY"Total Coins:\t"COL_WHITE"%0.0f\n"COL_GREY"Time Ago:\t"COL_WHITE"%s",
aDonation[ E_TRANSACTION_ID ], aDonation[ E_NAME ], floatstr( aDonation[ E_AMOUNT ] ), iCoins, secondstotime( g_iTime - aDonation[ E_DATE ] ) );
ShowPlayerDialog( playerid, DIALOG_DONATED, DIALOG_STYLE_MSGBOX, ""COL_GOLD"SF-CNR Donation", szBigString, "Continue", "" );
}
return 1;
}
thread OnGrabLatestDonor( hidden )
{
new
2019-01-06 01:06:01 +00:00
rows = cache_get_row_count( );
2018-12-22 11:01:10 +00:00
if ( rows )
{
static
2019-01-06 01:06:01 +00:00
szName[ MAX_PLAYER_NAME ];
2018-12-22 11:01:10 +00:00
cache_get_field_content( 0, "NAME", szName );
2019-01-06 01:06:01 +00:00
new Float: last_donation = cache_get_field_content_float( 0, "LAST_AMOUNT", dbHandle );
new Float: total_donations = cache_get_field_content_float( 0, "TOTAL_DONATIONS", dbHandle );
2018-12-22 11:01:10 +00:00
2019-05-31 09:53:49 +00:00
new Float: funding_goal = GetServerVariableFloat( "donation_goal_amount" );
// make this optional
if ( funding_goal <= 0.0 ) {
2019-05-31 10:11:39 +00:00
new Float: funding_goal_percent = total_donations / funding_goal * 100.0;
2019-05-31 09:53:49 +00:00
// Prevents total revenue for the month being disclosed mathematically
if ( funding_goal_percent >= 100.0 ) {
TextDrawSetString( g_TopDonorTD, sprintf( "Latest Donor %s - $%0.2f, ~g~Month Is Fully %0.2f%% Funded!", szName, last_donation, 100.0 ) );
} else {
TextDrawSetString( g_TopDonorTD, sprintf( "Latest Donor %s - $%0.2f, ~r~Month Is Only %0.2f%% Funded!", szName, last_donation, funding_goal_percent ) );
}
2019-01-06 01:06:01 +00:00
} else {
2019-05-31 09:53:49 +00:00
TextDrawSetString( g_TopDonorTD, sprintf( "Latest Donor %s - $%0.2f", szName, last_donation ) );
2018-12-22 11:01:10 +00:00
}
2019-01-06 01:06:01 +00:00
// Play song!
if ( ! hidden ) {
GameTextForAll( sprintf( "~y~~h~~h~New Donor!~n~~w~%s", szName ), 6000, 3 );
// Play sound
foreach(new p : Player) if ( !IsPlayerUsingRadio( p ) ) {
PlayAudioStreamForPlayer( p, "http://files.sfcnr.com/game_sounds/donated.mp3" );
}
}
2018-12-22 11:01:10 +00:00
}
else
{
TextDrawSetString( g_TopDonorTD, "Nobody Donated :(" );
}
return 1;
}
thread OnUpdateWallOfDonors( )
{
new
rows;
cache_get_data( rows, tmpVariable );
if( rows )
{
new
szString[ 600 ],
iLine = 1,
iPosition = 0;
for( new row = 0; row < rows; row++ )
{
new
szName[ MAX_PLAYER_NAME ];
cache_get_field_content( row, "NAME", szName );
new
iOldLength = strlen( szString ) + 4; // 4 is an offset
if( iOldLength - iPosition > 24 ) {
iPosition = iOldLength;
strcat( szString, "\n" ), iLine ++;
}
// The wall of donors
format( szString, sizeof( szString ), "%s%s, ", szString, szName );
}
// The wall of donors formatting
new
iLength = strlen( szString );
strdel( szString, iLength - 2, iLength );
// Develop a size and format
SetDynamicObjectMaterialText( g_TopDonorWall, 0, szString, 130, "Arial", floatround( 48.0 * floatpower( 0.925, iLine - 1 ), floatround_ceil ), 0, -65536, 0, 1 );
}
else
{
SetDynamicObjectMaterialText( g_TopDonorWall, 0, "Nobody Donated :(", 130, "Arial", 48, 0, -65536, 0, 1 );
}
return 1;
}
/* ** Commands ** */
CMD:redeemvip( playerid, params[ ] ) return cmd_donated( playerid, params );
CMD:donated( playerid, params[ ] )
{
ShowPlayerDialog( playerid, DIALOG_VIP, DIALOG_STYLE_INPUT, ""COL_GOLD"SF-CNR Donation", ""COL_WHITE"Enter the transaction ID of your donation below.\n\n"COL_GREY"See http://forum.sfcnr.com/showthread.php?10125 for details.", "Redeem", "Close" );
return 1;
}
/* ** RCON Commands ** */
2019-01-12 11:27:45 +00:00
CMD:updatedonategoal( playerid, params[ ] )
{
new
Float: donation_goal;
if ( ! IsPlayerAdmin( playerid ) && ! IsPlayerLeadMaintainer( playerid ) ) return 0;
else if ( sscanf( params, "f", donation_goal ) ) return SendUsage( playerid, "/updatedonationreq [DONATION_GOAL_AMOUNT]" );
else if ( ! ( 1.0 <= donation_goal < 10000.0 ) ) return SendError( playerid, "Donation goal amount must be between $1 and $10,000." );
else
{
new
Float: previous_goal = GetServerVariableFloat( "donation_goal_amount" );
UpdateGlobalDonated( .hidden = 1 );
SendServerMessage( playerid, "Updating donation goal from $%s to $%s!", number_format( previous_goal, .decimals = 2 ), number_format( donation_goal, .decimals = 2 ) );
UpdateServerVariableFloat( "donation_goal_amount", donation_goal );
}
return 1;
}
2018-12-22 11:01:10 +00:00
CMD:updatedonortd( playerid, params[ ] )
{
new
targetid, Float: amount, reset;
2019-01-12 11:27:45 +00:00
if ( ! IsPlayerAdmin( playerid ) && ! IsPlayerLeadMaintainer( playerid ) ) return 0;
2018-12-22 11:01:10 +00:00
else if ( sscanf( params, "D(0)D(65535)F(0.0)", reset, targetid, amount ) ) return SendUsage( playerid, "/updatedonortd [RESET] [PLAYER_ID] [AMOUNT]" );
else
{
// Reset the top donor
if ( reset ) {
TextDrawSetString( g_TopDonorTD, "Nobody Donated :(" );
}
// Update it incase
UpdateGlobalDonated( targetid, amount );
SendServerMessage( playerid, "Updating latest donor now (player id %d, amount %f)", targetid, amount );
}
return 1;
}
/* ** Functions ** */
static stock UpdateGlobalDonated( playerid = INVALID_PLAYER_ID, Float: amount = 0.0, hidden = 0 )
{
if ( playerid != INVALID_PLAYER_ID && amount > 0.0 ) {
format( szBigString, sizeof( szBigString ), "INSERT INTO `TOP_DONOR` (`USER_ID`,`AMOUNT`,`LAST_AMOUNT`,`TIME`,`HIDE`) VALUES(%d,%f,%f,%d,%d) ON DUPLICATE KEY UPDATE `AMOUNT`=`AMOUNT`+%f,`LAST_AMOUNT`=%f,`TIME`=%d,`HIDE`=%d;", p_AccountID[ playerid ], amount, amount, g_iTime, hidden, amount, amount, g_iTime, hidden );
mysql_single_query( szBigString );
}
// top donor
2019-01-06 01:06:01 +00:00
mysql_tquery( dbHandle, "SELECT `NAME`,`LAST_AMOUNT`,(SELECT SUM(`AMOUNT`) FROM `TOP_DONOR`) AS `TOTAL_DONATIONS` FROM `TOP_DONOR` LEFT JOIN `USERS` ON `TOP_DONOR`.`USER_ID`=`USERS`.`ID` WHERE `LAST_AMOUNT` > 0 AND `HIDE` < 1 ORDER BY `TIME` DESC LIMIT 1", "OnGrabLatestDonor", "d", hidden );
2018-12-22 11:01:10 +00:00
// wall of donors
mysql_tquery( dbHandle, "SELECT `USERS`.`NAME` FROM `TOP_DONOR` INNER JOIN `USERS` ON `TOP_DONOR`.`USER_ID`=`USERS`.`ID` WHERE `HIDE` < 1 ORDER BY `AMOUNT` DESC, `TIME` DESC", "OnUpdateWallOfDonors", "" );
return 1;
}