From 268a575fe7d83a1191a2bfcefd74d25bfbd77c3d Mon Sep 17 00:00:00 2001 From: Lorenc Pekaj Date: Sat, 8 Sep 2018 00:20:26 +1000 Subject: [PATCH] add in-game crowdfunding feature (/crowdfund) --- .../irresistible/features/crowdfund.inc | 284 ++++++++++++++++++ pawno/include/irresistible/main.inc | 1 + 2 files changed, 285 insertions(+) create mode 100644 pawno/include/irresistible/features/crowdfund.inc diff --git a/pawno/include/irresistible/features/crowdfund.inc b/pawno/include/irresistible/features/crowdfund.inc new file mode 100644 index 0000000..2a0292b --- /dev/null +++ b/pawno/include/irresistible/features/crowdfund.inc @@ -0,0 +1,284 @@ +/* + * Irresistible Gaming (c) 2018 + * Developed by Lorenc Pekaj + * Module: + * Purpose: + */ + +/* ** Includes ** */ +#include < YSI\y_hooks > + +/* ** Definitions ** */ +#define MAX_CROWDFUNDS 10 // dont bother editing + +#define DIALOG_CROWDFUNDS 9383 +#define DIALOG_CROWDFUND_OPTIONS 9384 +#define DIALOG_CROWDFUND_INFO 9385 +#define DIALOG_CROWDFUND_DONATE 9386 + +/* ** Hooks ** */ +hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) +{ + if ( dialogid == DIALOG_CROWDFUNDS && response ) + { + new crowdfund_ids_string[ MAX_CROWDFUNDS * 3 ]; + new crowdfunds_ids[ MAX_CROWDFUNDS ]; + + GetPVarString( playerid, "crowdfunds_shown", crowdfund_ids_string, sizeof( crowdfund_ids_string ) ); + + if ( sscanf( crowdfund_ids_string, "a[" # MAX_CROWDFUNDS "]", crowdfunds_ids ) ) { + return SendError( playerid, "There was an error reading the crowdfunds, try again later." ); + } + + for ( new i = 0, x = 0; i < sizeof( crowdfunds_ids ); i ++ ) if ( crowdfunds_ids[ i ] != 0 ) + { + if ( x == listitem ) + { + SetPVarInt( playerid, "viewing_crowdfund", crowdfunds_ids[ i ] ); + break; + } + x ++; + } + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_OPTIONS, DIALOG_STYLE_LIST, ""COL_GOLD"Feature Crowdfunding", "View Crowdfund Details\nView Crowdfund Patreons\n"COL_GOLD"Contribute To Crowdfund <3", "Select", "Close" ); + } + else if ( dialogid == DIALOG_CROWDFUND_OPTIONS ) + { + if ( ! response ) + return ShowPlayerCrowdfunds( playerid ); + + new + viewing_crowdfund = GetPVarInt( playerid, "viewing_crowdfund" ); + + switch ( listitem ) + { + case 0: + { + mysql_tquery( + dbHandle, + sprintf( "SELECT CROWDFUND_PACKAGES.*, CROWDFUNDS.DESCRIPTION AS CF_DESCRIPTION FROM CROWDFUND_PACKAGES INNER JOIN CROWDFUNDS ON CROWDFUNDS.ID = CROWDFUND_PACKAGES.CROWDFUND_ID WHERE CROWDFUND_ID = %d ORDER BY REQUIRED_AMOUNT DESC", viewing_crowdfund ), + "OnDisplayCrowdfundInfo", "ii", playerid, viewing_crowdfund + ); + } + case 1: + { + mysql_tquery( + dbHandle, + sprintf( "SELECT USERS.NAME, SUM(AMOUNT) AS TOTAL FROM CROWDFUND_PATREONS INNER JOIN USERS ON USERS.ID = CROWDFUND_PATREONS.USER_ID WHERE CROWDFUND_PATREONS.CROWDFUND_ID = %d GROUP BY CROWDFUND_PATREONS.USER_ID ORDER BY TOTAL DESC", viewing_crowdfund ), + "OnDisplayCrowdfundPatreons", "ii", playerid, viewing_crowdfund + ); + } + case 2: + { + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_DONATE, DIALOG_STYLE_INPUT, ""COL_GOLD"Feature Crowdfunding", ""COL_WHITE"Please specify the amount of IC you wish to contribute:\n\n"COL_ORANGE"Warning: There is no confirmation dialog.", "Contribute", "Back" ); + } + } + } + else if ( dialogid == DIALOG_CROWDFUND_INFO && ! response ) { + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_OPTIONS, DIALOG_STYLE_LIST, ""COL_GOLD"Feature Crowdfunding", "View Crowdfund Details\nView Crowdfund Patreons\n"COL_GOLD"Contribute To Crowdfund <3", "Select", "Close" ); + } + else if ( dialogid == DIALOG_CROWDFUND_DONATE ) + { + if ( ! response ) + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_OPTIONS, DIALOG_STYLE_LIST, ""COL_GOLD"Feature Crowdfunding", "View Crowdfund Details\nView Crowdfund Patreons\n"COL_GOLD"Contribute To Crowdfund <3", "Select", "Close" ); + + new + viewing_crowdfund = GetPVarInt( playerid, "viewing_crowdfund" ); + + if ( ! viewing_crowdfund ) { + return SendError( playerid, "There was an error. Please attempt to contribute to the crowdfund again." ); + } + + new + Float: amount; + + if ( sscanf( inputtext, "f", amount ) ) { + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_DONATE, DIALOG_STYLE_INPUT, ""COL_GOLD"Feature Crowdfunding", ""COL_WHITE"Please specify the amount of IC you wish to contribute:\n\n"COL_RED"Please specify a decimal number!", "Contribute", "Close" ); + } else if ( amount < 10.0 ) { + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_DONATE, DIALOG_STYLE_INPUT, ""COL_GOLD"Feature Crowdfunding", ""COL_WHITE"Please specify the amount of IC you wish to contribute:\n\n"COL_RED"The minimum amount you can contribute is 10.00 IC!", "Contribute", "Close" ); + } else if ( amount > GetPlayerIrresistibleCoins( playerid ) ) { + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_DONATE, DIALOG_STYLE_INPUT, ""COL_GOLD"Feature Crowdfunding", ""COL_WHITE"Please specify the amount of IC you wish to contribute:\n\n"COL_RED"You do not have this many coins in your account!", "Contribute", "Close" ); + } else { + // check if expired/ended/valid before even submitting + mysql_tquery( dbHandle, sprintf( "SELECT FEATURE, UNIX_TIMESTAMP(RELEASE_DATE) AS `RELEASE`, UNIX_TIMESTAMP(END_DATE) AS `END` FROM CROWDFUNDS WHERE ID = %d", viewing_crowdfund ), "OnPlayerCrowdfundContribute", "ddf", playerid, viewing_crowdfund, amount ); + } + return 1; + } + return 1; +} + +/* ** Commands ** */ +CMD:crowdfunds( playerid, params[ ] ) { + return ShowPlayerCrowdfunds( playerid ); +} + +/* ** Functions ** */ +stock ShowPlayerCrowdfunds( playerid ) { + return mysql_tquery( dbHandle, + "SELECT CROWDFUNDS.ID, CROWDFUNDS.FEATURE, CROWDFUNDS.FUND_TARGET, SUM(CROWDFUND_PATREONS.AMOUNT) AS RAISED, UNIX_TIMESTAMP(RELEASE_DATE) AS RELASE, UNIX_TIMESTAMP(END_DATE) AS END FROM CROWDFUNDS " \ + "LEFT JOIN CROWDFUND_PATREONS on CROWDFUNDS.ID = CROWDFUND_PATREONS.CROWDFUND_ID " \ + "GROUP BY CROWDFUNDS.ID ORDER BY CROWDFUNDS.ID DESC LIMIT " # MAX_CROWDFUNDS, + "OnDisplayCrowdfunds", "i", playerid + ), 1; +} + +thread OnPlayerCrowdfundContribute( playerid, crowdfund_id, Float: amount ) +{ + new + rows = cache_get_row_count( ); + + if ( rows ) + { + new feature[ 64 ]; + new curr_timestamp = gettime( ); + new release_timestamp = cache_get_field_content_int( 0, "RELEASE", dbHandle ); + new end_timestamp = cache_get_field_content_int( 0, "END", dbHandle ); + + // check if released or ended + if ( ( curr_timestamp > release_timestamp && release_timestamp != 0 ) || ( curr_timestamp > end_timestamp ) ) { + SendError( playerid, "You can no longer contribute to this crowdfund as it is released or ended." ); + return ShowPlayerCrowdfunds( playerid ); + } + + // double check valid amounts again + if ( amount < 10.0 || amount > GetPlayerIrresistibleCoins( playerid ) ) { + SendError( playerid, "You can no longer contribute to this crowdfund as the contribution amount is invalid." ); + return ShowPlayerCrowdfunds( playerid ); + } + + // get feature name + cache_get_field_content( 0, "FEATURE", feature ); + + // notify and deduct ic + GivePlayerIrresistibleCoins( playerid, -amount ); + SendClientMessageToAllFormatted( -1, ""COL_GOLD"[CROWDFUND]"COL_WHITE" %s(%d) has donated %s IC to the %s Crowdfund! <3", ReturnPlayerName( playerid ), playerid, number_format( amount, .prefix = '\0', .decimals = 2 ), feature ); + SavePlayerData( playerid ); // force save just incase + + // insert into database + mysql_format( + dbHandle, szBigString, sizeof( szBigString ), + "INSERT INTO CROWDFUND_PATREONS (USER_ID, CROWDFUND_ID, AMOUNT) VALUES (%d, %d, %f)", + GetPlayerAccountID( playerid ), crowdfund_id, amount + ); + mysql_single_query( szBigString ); + return 1; + } + else + { + return SendError( playerid, "The crowdfund you are attempting to contribute to no longer exists." ); + } +} + +thread OnDisplayCrowdfundPatreons( playerid, crowdfund_id ) +{ + new + rows = cache_get_row_count( ); + + if ( ! rows ) { + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_INFO, DIALOG_STYLE_TABLIST_HEADERS, ""COL_GOLD"Feature Crowdfunding", ""COL_GREY"Contributor\t"COL_GREY"Amount (IC)\n"COL_RED"No-One\t"COL_RED"N/A", "Close", "Back" ), 1; + } + + new patreon[ MAX_PLAYER_NAME ]; + + szHugeString = ""COL_GREY"Contributor\t"COL_GREY"Amount (IC)\n"; + + for ( new row = 0; row < rows; row ++ ) + { + cache_get_field_content( row, "NAME", patreon ); + + new Float: contribution = cache_get_field_content_float( row, "TOTAL", dbHandle ); + + format( szHugeString, sizeof( szHugeString ), "%s%s\t%s IC\n", szHugeString, patreon, number_format( contribution, .prefix = '\0', .decimals = 2 ) ); + } + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_INFO, DIALOG_STYLE_TABLIST_HEADERS, ""COL_GOLD"Feature Crowdfunding", szHugeString, "Close", "Back" ), 1; +} + +thread OnDisplayCrowdfundInfo( playerid, crowdfund_id ) +{ + new + rows = cache_get_row_count( ); + + if ( ! rows ) { + return SendError( playerid, "There is no crowdfund information to show. Try again later." ); + } + + new cf_description[ 100 ]; + new description[ 100 ]; + new title[ 48 ]; + + cache_get_field_content( 0, "CF_DESCRIPTION", cf_description ); + + if ( strlen( cf_description ) < sizeof( cf_description ) - 1 ) { + format( szHugeString, sizeof( szHugeString ), ""COL_WHITE"%s\n\n", cf_description ); + } else { + format( szHugeString, sizeof( szHugeString ), ""COL_WHITE"%s"COL_GREY"... (read more on sfcnr.com)\n\n", cf_description ); + } + + for ( new row = 0; row < rows; row ++ ) + { + cache_get_field_content( row, "TITLE", title ); + cache_get_field_content( row, "DESCRIPTION", description ); + + new Float: req_amount = cache_get_field_content_float( row, "REQUIRED_AMOUNT", dbHandle ); + + if ( strlen( description ) < sizeof( description ) - 1 ) { + format( szHugeString, sizeof( szHugeString ), "%s"COL_GOLD"%s (%s IC+)"COL_WHITE"\n%s\n\n", szHugeString, title, number_format( req_amount, .prefix = '\0', .decimals = 2 ), description ); + } else { + format( szHugeString, sizeof( szHugeString ), "%s"COL_GOLD"%s (%s IC+)"COL_WHITE"\n%s"COL_GREY"... (read more on sfcnr.com)\n\n", szHugeString, title, number_format( req_amount, .prefix = '\0', .decimals = 2 ), description ); + } + } + return ShowPlayerDialog( playerid, DIALOG_CROWDFUND_INFO, DIALOG_STYLE_MSGBOX, ""COL_GOLD"Feature Crowdfunding", szHugeString, "Close", "Back" ), 1; +} + +thread OnDisplayCrowdfunds( playerid ) +{ + new + rows; + + cache_get_data( rows, tmpVariable ); + + if ( ! rows ) { + return SendError( playerid, "There is no crowdfund to show. Try again later." ); + } + + new feature[ 64 ]; + new crowdfund_ids[ MAX_CROWDFUNDS * 3 ]; + + // header + szLargeString = ""COL_WHITE"Feature\t"COL_WHITE"Raised (IC)\t"COL_WHITE"Goal (IC)\t"COL_WHITE"Completion (%)\n"; + + for ( new row = 0; row < MAX_CROWDFUNDS; row ++ ) + { + new + id = 0; + + if ( row < rows ) + { + id = cache_get_field_content_int( row, "ID" ); + cache_get_field_content( row, "FEATURE", feature ); + + new Float: amount_raised = cache_get_field_content_float( row, "RAISED", dbHandle ); + new Float: target_amount = cache_get_field_content_float( row, "FUND_TARGET", dbHandle ); + new Float: percent_raised = ( amount_raised / target_amount ) * 100.0; + + new curr_timestamp = gettime( ); + new release_timestamp = cache_get_field_content_int( row, "RELEASE", dbHandle ); + new end_timestamp = cache_get_field_content_int( row, "END", dbHandle ); + + format( szLargeString, sizeof( szLargeString ), + "%s%s%s\t%s IC\t%s IC\t%s%0.1f%\n", + szLargeString, + ( curr_timestamp > release_timestamp && release_timestamp != 0 ) || ( curr_timestamp > end_timestamp ) ? ( COL_GREY ) : ( COL_WHITE ), + feature, + number_format( amount_raised, .prefix = '\0', .decimals = 1 ), + number_format( target_amount, .prefix = '\0', .decimals = 1 ), + percent_raised >= 100.0 ? ( COL_GREEN ) : ( COL_WHITE ), + percent_raised + ); + } + format( crowdfund_ids, sizeof( crowdfund_ids ), "%s%d ", crowdfund_ids, id ); + } + + // save ids for response + SetPVarString( playerid, "crowdfunds_shown", crowdfund_ids ); + return ShowPlayerDialog( playerid, DIALOG_CROWDFUNDS, DIALOG_STYLE_TABLIST_HEADERS, ""COL_GOLD"Feature Crowdfunding", szLargeString, "Select", "Close" ), 1; +} diff --git a/pawno/include/irresistible/main.inc b/pawno/include/irresistible/main.inc index 3348318..9bfd8bb 100644 --- a/pawno/include/irresistible/main.inc +++ b/pawno/include/irresistible/main.inc @@ -37,6 +37,7 @@ #include < irresistible\features\weapon_drop > #include < irresistible\features\ammunation > #include < irresistible\features\duel > +#include < irresistible\features\crowdfund > // #include < irresistible\features\pilot > // #include < irresistible\features\fishing > // #include < irresistible\features\vote >