diff --git a/gamemodes/irresistible/cnr/features/stocks/stocks.pwn b/gamemodes/irresistible/cnr/features/stocks/stocks.pwn index 6f8e89e..9c3e9ca 100644 --- a/gamemodes/irresistible/cnr/features/stocks/stocks.pwn +++ b/gamemodes/irresistible/cnr/features/stocks/stocks.pwn @@ -11,7 +11,7 @@ /* ** Definitions ** */ #define MAX_STOCKS ( 32 ) -#define STOCK_REPORTING_PERIOD ( 86400 ) // 1 day +#define STOCK_REPORTING_PERIOD ( 500 ) // 1 day #define STOCK_REPORTING_PERIODS ( 30 ) // last 30 periods (days) @@ -28,8 +28,8 @@ enum E_STOCK_MARKET_DATA enum E_STOCK_MARKET_PRICE_DATA { - E_CURRENT_PRICE, - E_CURRENT_EARNINGS, E_PREVIOUS_EARNINGS + E_SQL_ID, Float: E_PRICE, + Float: E_EARNINGS }; static stock @@ -41,7 +41,33 @@ static stock /* ** Hooks ** */ hook OnScriptInit( ) { - CreateStockMarket( 0, "The Mining Company", "MC", 10000000, 100 ); + // server variables + AddServerVariable( "stock_report_time", "0", GLOBAL_VARTYPE_INT ); + + // create markets + CreateStockMarket( 0, "The Mining Company", "MC", 50000000, 100 ); + return 1; +} + +hook OnServerUpdate( ) +{ + new current_time = GetServerTime( ); + new last_reporting = GetServerVariableInt( "stock_report_time" ); + + // check if its reporting time + if ( current_time > last_reporting ) + { + // reporting period + UpdateServerVariableInt( "stock_report_time", current_time + STOCK_REPORTING_PERIOD ); + + // create a new reporting period for every stock there + foreach ( new s : stockmarkets ) + { + StockMarket_CreateReport( s ); + } + + print( "Successfully created new reporting period for all online companies" ); + } return 1; } @@ -55,17 +81,23 @@ thread Stock_UpdateReportingPeriods( stockid ) { for ( new row = 0; row < rows; row ++ ) { - g_stockMarketPriceData[ stockid ] [ row ] [ E_CURRENT_PRICE ] = cache_get_field_content_int( row, "CURRENT_PRICE" ); - g_stockMarketPriceData[ stockid ] [ row ] [ E_CURRENT_EARNINGS ] = cache_get_field_content_int( row, "CURRENT_EARNINGS" ); - g_stockMarketPriceData[ stockid ] [ row ] [ E_PREVIOUS_EARNINGS ] = cache_get_field_content_int( row, "PREVIOUS_EARNINGS" ); + g_stockMarketPriceData[ stockid ] [ row ] [ E_SQL_ID ] = cache_get_field_content_int( row, "ID" ); + g_stockMarketPriceData[ stockid ] [ row ] [ E_PRICE ] = cache_get_field_content_float( row, "CURRENT_PRICE" ); + g_stockMarketPriceData[ stockid ] [ row ] [ E_EARNINGS ] = cache_get_field_content_float( row, "CURRENT_EARNINGS" ); } } return 1; } +thread StockMarket_InsertReport( stockid ) +{ + g_stockMarketPriceData[ stockid ] [ 0 ] [ E_SQL_ID ] = cache_insert_id( ); + return 1; +} + /* ** Command ** */ CMD:increase( playerid, params[ ] ) { - g_stockMarketPriceData[ 0 ] [ 0 ] [ E_CURRENT_EARNINGS ] += strval( params ); + StockMarket_UpdateEarnings( 0, strval( params ) ); return 1; } @@ -80,28 +112,23 @@ CMD:stockmarkets( playerid, params[ ] ) foreach ( new s : stockmarkets ) { - printf("%d %d\n", g_stockMarketPriceData[ s ] [ 0 ] [ E_CURRENT_EARNINGS ], g_stockMarketPriceData[ s ] [ 1 ] [ E_CURRENT_EARNINGS ]); - new Float: price_difference = ( ( float( g_stockMarketPriceData[ s ] [ 0 ] [ E_CURRENT_EARNINGS ] ) / float( g_stockMarketPriceData[ s ] [ 1 ] [ E_CURRENT_EARNINGS ] ) ) - 1.0 ) * 100.0; - new current_price = g_stockMarketPriceData[ s ] [ 0 ] [ E_CURRENT_PRICE ]; - - // prevent integer overflow (over 2.6B) - new Float: market_cap_millions = ( float( g_stockMarketData[ s ] [ E_MAX_SHARES ] ) / 1000000.0 ) * ( float( current_price ) / 1000000.0 ); - new Float: market_cap_billions = market_cap_millions / 1000.0; + printf("%f %f\n", g_stockMarketPriceData[ s ] [ 0 ] [ E_EARNINGS ], g_stockMarketPriceData[ s ] [ 1 ] [ E_EARNINGS ]); + new Float: price_difference = ( g_stockMarketPriceData[ s ] [ 1 ] [ E_EARNINGS ] / g_stockMarketPriceData[ s ] [ 2 ] [ E_EARNINGS ] - 1.0 ) * 100.0; + new Float: current_price = g_stockMarketPriceData[ s ] [ 1 ] [ E_PRICE ]; format( szLargeString, sizeof( szLargeString ), - "%s%s (%s)\t"COL_GREEN"%s\t$%s%s\t%s%s%%\n", + "%s%s (%s)\t"COL_GREEN"%s\t%s%s%%\n", szLargeString, g_stockMarketData[ s ] [ E_NAME ], g_stockMarketData[ s ] [ E_SYMBOL ], - cash_format( current_price ), - market_cap_billions > 1.0 ? number_format( market_cap_billions, .decimals = 2 ) : number_format( market_cap_millions, .decimals = 2 ), - market_cap_billions > 1.0 ? ( "B" ) : ( "M" ), + cash_format( current_price, .decimals = 0 ), price_difference >= 0.0 ? ( COL_GREEN ) : ( COL_RED ), number_format( price_difference, .decimals = 2 ) ); } + SendServerMessage( playerid, "The stock market will close in %s.", secondstotime( GetServerVariableInt( "stock_report_time" ) - GetServerTime( ) ) ); return ShowPlayerDialog( playerid, DIALOG_STOCK_MARKET, DIALOG_STYLE_TABLIST_HEADERS, ""COL_WHITE"Stock Market", szLargeString, "Select", "Close" ); } @@ -118,9 +145,8 @@ stock CreateStockMarket( stockid, const name[ 64 ], const symbol[ 4 ], max_share // reset stock price information for ( new r = 0; r < sizeof( g_stockMarketPriceData[ ] ); r ++ ) { - g_stockMarketPriceData[ stockid ] [ r ] [ E_CURRENT_PRICE ] = 0; - g_stockMarketPriceData[ stockid ] [ r ] [ E_CURRENT_EARNINGS ] = 0; - g_stockMarketPriceData[ stockid ] [ r ] [ E_PREVIOUS_EARNINGS ] = 0; + g_stockMarketPriceData[ stockid ] [ r ] [ E_PRICE ] = 0.0; + g_stockMarketPriceData[ stockid ] [ r ] [ E_EARNINGS ] = 0.0; } // load price information if there is @@ -134,8 +160,20 @@ stock CreateStockMarket( stockid, const name[ 64 ], const symbol[ 4 ], max_share stock StockMarket_CreateReport( stockid ) { - new old_earnings = g_stockMarketPriceData[ stockid ] [ 0 ] [ E_CURRENT_EARNINGS ]; - new old_price = g_stockMarketPriceData[ stockid ] [ 0 ] [ E_CURRENT_PRICE ]; + // limit a 20% loss for players + new Float: circuit_breaker = g_stockMarketPriceData[ stockid ] [ 1 ] [ E_EARNINGS ] * 0.8; + + if ( g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ] < circuit_breaker ) { + g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ] = circuit_breaker; + } + + // change stock price proportional to earnings increase/decrease + new Float: price_difference = g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ] / g_stockMarketPriceData[ stockid ] [ 1 ] [ E_EARNINGS ]; + printf("Earnings %f\n", price_difference ); + + if ( ( g_stockMarketPriceData[ stockid ] [ 0 ] [ E_PRICE ] = g_stockMarketPriceData[ stockid ] [ 1 ] [ E_PRICE ] * price_difference ) < 1.0 ) { + g_stockMarketPriceData[ stockid ] [ 0 ] [ E_PRICE ] = 1.0; + } // store temporary stock info new temp_stock_price_data[ MAX_STOCKS ] [ STOCK_REPORTING_PERIODS ] [ E_STOCK_MARKET_PRICE_DATA ]; @@ -143,58 +181,77 @@ stock StockMarket_CreateReport( stockid ) // shift all earnings by one for ( new r = 0; r < sizeof( g_stockMarketPriceData[ ] ) - 2; r ++ ) { - - g_stockMarketPriceData[ stockid ] [ r + 1 ] [ E_CURRENT_PRICE ] = temp_stock_price_data[ stockid ] [ r ] [ E_CURRENT_PRICE ]; - g_stockMarketPriceData[ stockid ] [ r + 1 ] [ E_CURRENT_EARNINGS ] = temp_stock_price_data[ stockid ] [ r ] [ E_CURRENT_EARNINGS ]; - g_stockMarketPriceData[ stockid ] [ r + 1 ] [ E_PREVIOUS_EARNINGS ] = temp_stock_price_data[ stockid ] [ r ] [ E_PREVIOUS_EARNINGS ]; + g_stockMarketPriceData[ stockid ] [ r + 1 ] [ E_PRICE ] = temp_stock_price_data[ stockid ] [ r ] [ E_PRICE ]; + g_stockMarketPriceData[ stockid ] [ r + 1 ] [ E_EARNINGS ] = temp_stock_price_data[ stockid ] [ r ] [ E_EARNINGS ]; } - // price difference - new Float: price_change = float( g_stockMarketPriceData[ stockid ] [ 0 ] [ E_CURRENT_EARNINGS ] ) / float( old_earnings ); + // set current price to previous reporting period price + g_stockMarketPriceData[ stockid ] [ 0 ] [ E_PRICE ] = g_stockMarketPriceData[ stockid ] [ 1 ] [ E_PRICE ]; - // circuit breaker ... max 20% loss - if ( price_change < 0.8 ) { - price_change = 0.8; - } + // reset earnings + g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ] = 0.0; // set to 0 - new new_price = floatround( float( old_price ) * price_change ); + // insert to database the old information + mysql_format( + dbHandle, szBigString, sizeof ( szBigString ), + "INSERT INTO `STOCK_REPORTS` (`STOCK_ID`, `CURRENT_PRICE`, `CURRENT_EARNINGS`) VALUES (%d, %f, %f)", + stockid, + g_stockMarketPriceData[ stockid ] [ 0 ] [ E_PRICE ], + g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ] + ); - // minimum stock price should be $10 - if ( new_price < 1 ) { - new_price = 1; - } - - // set information - g_stockMarketPriceData[ stockid ] [ 0 ] [ E_CURRENT_PRICE ] = new_price; - g_stockMarketPriceData[ stockid ] [ 0 ] [ E_CURRENT_EARNINGS ] = 0; // set to 0 - g_stockMarketPriceData[ stockid ] [ 0 ] [ E_PREVIOUS_EARNINGS ] = old_earnings; - - // insert to database - - - // - erase(szLargeString); - // shift all earnings by one - for ( new r = 0; r < sizeof( g_stockMarketPriceData[ ] ); r ++ ) { - format( szLargeString, 1024, "%s{%d,%d,%d}, ", szLargeString, g_stockMarketPriceData[ stockid ] [ r ] [ E_CURRENT_PRICE ], g_stockMarketPriceData[ stockid ] [ r ] [ E_CURRENT_EARNINGS ], g_stockMarketPriceData[ stockid ] [ r ] [ E_PREVIOUS_EARNINGS ] ); - } - - printf("%s\n",szLargeString); + mysql_tquery( dbHandle, szBigString, "StockMarket_InsertReport", "d", stockid ); return 1; } -stock StockMarket_GetCurrentPrice( stockid ) { - return g_stockMarketPriceData[ stockid ] [ 0 ] [ E_CURRENT_PRICE ]; +stock StockMarket_UpdateEarnings( stockid, amount ) +{ + if ( ! Iter_Contains( stockmarkets, stockid ) ) + return 0; + + printf( "Current Earnings: %f, Prior Earnings: %f", g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ], g_stockMarketPriceData[ stockid ] [ 1 ] [ E_EARNINGS ] ); + g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ] += amount; + mysql_single_query( sprintf( "UPDATE `STOCK_REPORTS` SET `CURRENT_EARNINGS` = `CURRENT_EARNINGS` + %d WHERE `ID` = %d", g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ], g_stockMarketPriceData[ stockid ] [ 0 ] [ E_SQL_ID ] ) ); + return 1; +} + +stock Float: StockMarket_GetEarnings( stockid ) { + return g_stockMarketPriceData[ stockid ] [ 0 ] [ E_EARNINGS ]; +} + +stock Float: StockMarket_GetCurrentPrice( stockid ) { + return g_stockMarketPriceData[ stockid ] [ 0 ] [ E_PRICE ]; +} + +stock StockMarket_MakeSellOrder( stockid, accountid, Float: shares, Float: price ) +{ + //INSERT INTO `STOCK_ORDERS` (`USER_ID`, `STOCK_ID`, ``) + return 1; } /* CREATE TABLE IF NOT EXISTS `STOCK_REPORTS` ( + `ID` int(11) primary key auto_increment, `STOCK_ID` int(11), - `CURRENT_PRICE` int(11), - `CURRENT_EARNINGS` int(11), - `PREVIOUS_EARNINGS` int(11), + `CURRENT_PRICE` float, + `CURRENT_EARNINGS` float, `REPORTING_TIME` TIMESTAMP default CURRENT_TIMESTAMP ); + CREATE TABLE IF NOT EXISTS `STOCK_OWNERS` ( + `ID` int(11) primary key auto_increment, + `USER_ID` int(11), + `STOCK_ID` int(11), + `SHARES` float, + `PRICE` float + ); + + CREATE TABLE IF NOT EXISTS `STOCK_ORDERS` ( + `ID` int(11) primary key auto_increment, + `USER_ID` int(11), + `STOCK_ID` int(11), + `SHARES` float, + `PRICE` float, + ); */ diff --git a/gamemodes/irresistible/servervars.pwn b/gamemodes/irresistible/servervars.pwn index 74c9d94..f135fde 100644 --- a/gamemodes/irresistible/servervars.pwn +++ b/gamemodes/irresistible/servervars.pwn @@ -12,6 +12,15 @@ /* ** Includes ** */ #include < YSI\y_hooks > +/* ** Macros ** */ +#define GetServerVariableInt GetGVarInt + +#define UpdateServerVariableString(%0,%1) \ + (UpdateServerVariable(%0, 0, 0, %1, GLOBAL_VARTYPE_STRING)) + +#define UpdateServerVariableInt(%0,%1) \ + (UpdateServerVariable(%0, %1, 0, "", GLOBAL_VARTYPE_INT)) + /* ** Hooks ** */ hook OnGameModeInit( ) {