diff --git a/gamemodes/irresistible/cnr/dialog_ids.pwn b/gamemodes/irresistible/cnr/dialog_ids.pwn index 5638974..0b04cb6 100644 --- a/gamemodes/irresistible/cnr/dialog_ids.pwn +++ b/gamemodes/irresistible/cnr/dialog_ids.pwn @@ -39,7 +39,7 @@ #define DIALOG_GANG_COLOR 1027 #define DIALOG_GANG_COLOR_INPUT 1028 #define DIALOG_RADIO 1029 -//#define DIALOG_XPMARKET 1030 +#define DIALOG_XPMARKET 1030 #define DIALOG_PAINTBALL 1031 #define DIALOG_GPS 1032 #define DIALOG_VIP_LOCKER 1033 @@ -211,6 +211,7 @@ #define DIALOG_HOUSE_SELL 1201 #define DIALOG_BUSINESS_SELL_CONFIRM 1202 #define DIALOG_NEXT_PAGE_VIP 1204 +#define DIALOG_XPMARKET_SELL 1205 /* ** Hooks ** */ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) diff --git a/gamemodes/irresistible/cnr/features/perks.pwn b/gamemodes/irresistible/cnr/features/perks.pwn index f3993be..20df771 100644 --- a/gamemodes/irresistible/cnr/features/perks.pwn +++ b/gamemodes/irresistible/cnr/features/perks.pwn @@ -67,28 +67,24 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) { switch( listitem ) { - case 0: ShowPlayerDialog( playerid, DIALOG_PERKS_P, DIALOG_STYLE_TABLIST_HEADERS, "{FFFFFF}Game Perks", ""COL_WHITE"Item Name\t"COL_WHITE"Total Level Req.\t"COL_WHITE"Cost ($)\nHide From Radar\t"COL_GOLD"75\t"COL_GREEN"$25,000\nUnlimited Ammunition\t"COL_GOLD"50\t"COL_GREEN"$9,900", "Select", "Back" ); - case 1: ShowPlayerDialog( playerid, DIALOG_PERKS_V, DIALOG_STYLE_TABLIST_HEADERS, "{FFFFFF}Game Perks", ""COL_WHITE"Item Name\t"COL_WHITE"Total Level Req.\t"COL_WHITE"Cost ($)\nFix & Flip vehicle\t"COL_GOLD"75\t"COL_GREEN"$9,900\nRepair Vehicle\t"COL_GOLD"75\t"COL_GREEN"$7,500\nAdd NOS\t"COL_GOLD"50\t"COL_GREEN"$3,000\nFlip vehicle\t"COL_GOLD"40\t"COL_GREEN"$2,500", "Select", "Back" ); + case 0: ShowPlayerDialog( playerid, DIALOG_PERKS_P, DIALOG_STYLE_TABLIST_HEADERS, "{FFFFFF}Deathmatch Perks", ""COL_WHITE"Item Name\t"COL_WHITE"Cost (XP)\nHide From Radar\t"COL_GREEN"250 XP\nUnlimited Ammunition\t"COL_GREEN"100 XP", "Select", "Back" ); + case 1: ShowPlayerDialog( playerid, DIALOG_PERKS_V, DIALOG_STYLE_TABLIST_HEADERS, "{FFFFFF}Robbery Perks", ""COL_WHITE"Item Name\t"COL_WHITE"Cost (XP)\nFix & Flip vehicle\t"COL_GREEN"180 XP\nRepair Vehicle\t"COL_GREEN"120 XP\nAdd NOS\t"COL_GREEN"80 XP\nFlip vehicle\t"COL_GREEN"50 XP", "Select", "Back" ); } } else if ( dialogid == DIALOG_PERKS_P ) { if ( !response ) - return ShowPlayerDialog( playerid, DIALOG_PERKS, DIALOG_STYLE_LIST, "{FFFFFF}Game Perks", "Player Perks\nVehicle Perks", "Select", "Cancel" ); + return ShowPlayerDialog( playerid, DIALOG_PERKS, DIALOG_STYLE_LIST, "{FFFFFF}Game Perks", "Deathmatch Perks\nRobbery Perks", "Select", "Cancel" ); new - total_level = GetPlayerTotalLevel( playerid ); + Float: total_dm_xp = GetPlayerExperience( playerid, E_DEATHMATCH ); switch( listitem ) { case 0: { - if ( total_level < 75 ) { - return SendError( playerid, "Your total level must be at least 75 to use this (/level)." ); - } - - if ( GetPlayerCash( playerid ) < 25000 ) { - return SendError( playerid, "You do not have enough money for this item ($25,000)." ); + if ( total_dm_xp < 250 ) { + return SendError( playerid, "You need at least 250 Deathmatch XP for this item." ); } if ( GetPlayerClass( playerid ) != CLASS_CIVILIAN ) { @@ -98,9 +94,9 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) p_OffRadar{ playerid } = true; p_OffRadarTimestamp[ playerid ] = GetServerTime( ) + 180; - GivePlayerCash( playerid, -25000 ); + GivePlayerExperience( playerid, E_DEATHMATCH, -250, .with_dilation = false ); - SendServerMessage( playerid, "You have hidden yourself from the radar (3 minutes) for $25,000." ); + SendServerMessage( playerid, "You have hidden yourself from the radar (3 minutes) for 250 Deathmatch XP." ); ShowPlayerHelpDialog( playerid, 3000, "~g~~h~Hide from radar ~w~will be deactivate in 3 minutes." ); SetPlayerColor( playerid, setAlpha( GetPlayerColor( playerid ), 0x00 ) ); @@ -109,12 +105,8 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) case 1: { - if ( total_level < 50 ) { - return SendError( playerid, "Your total level must be at least 50 to use this (/level)." ); - } - - if ( GetPlayerCash( playerid ) < 9900 ) { - return SendError( playerid, "You do not have enough money for this item ($9,900)." ); + if ( total_dm_xp < 100 ) { + return SendError( playerid, "You need at least 100 Deathmatch XP for this item." ); } for ( new i = 0; i < MAX_WEAPONS; i++ ) @@ -125,8 +117,9 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) } } - GivePlayerCash( playerid, -9900 ); - SendServerMessage( playerid, "You have bought unlimited ammunition for $9,900." ); + GivePlayerExperience( playerid, E_DEATHMATCH, -100, .with_dilation = false ); + + SendServerMessage( playerid, "You have bought unlimited ammunition for 100 Deathmatch XP." ); SetPlayerArmedWeapon( playerid, 0 ); Beep( playerid ); } @@ -135,78 +128,62 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) else if ( dialogid == DIALOG_PERKS_V ) { if ( !response ) - return ShowPlayerDialog( playerid, DIALOG_PERKS, DIALOG_STYLE_LIST, "{FFFFFF}Game Perks", "Player Perks\nVehicle Perks", "Select", "Cancel" ); + return ShowPlayerDialog( playerid, DIALOG_PERKS, DIALOG_STYLE_LIST, "{FFFFFF}Game Perks", "Deathmatch Perks\nRobbery Perks", "Select", "Cancel" ); if ( !IsPlayerInAnyVehicle( playerid ) || GetPlayerState( playerid ) != PLAYER_STATE_DRIVER ) return SendError( playerid, "You are not in any vehicle as a driver." ); - new - total_level = GetPlayerTotalLevel( playerid ); + new + Float: total_robbery_xp = GetPlayerExperience( playerid, E_ROBBERY ); switch( listitem ) { case 0: { - if ( total_level < 75 ) { - return SendError( playerid, "Your total level must be at least 75 to use this (/level)." ); - } - - if ( GetPlayerCash( playerid ) < 9900 ) { - return SendError( playerid, "You do not have enough money for this item ($9,900)." ); + if ( total_robbery_xp < 180 ) { + return SendError( playerid, "You need at least 180 Robbery XP for this item." ); } new Float: vZ, vehicleid = GetPlayerVehicleID( playerid ); GetVehicleZAngle( vehicleid, vZ ), SetVehicleZAngle( vehicleid, vZ ); RepairVehicle( vehicleid ); - GivePlayerCash( playerid, -9900 ); - SendServerMessage( playerid, "You have fixed and flipped your vehicle for $9,900." ); + GivePlayerExperience( playerid, E_ROBBERY, -180, .with_dilation = false ); + SendServerMessage( playerid, "You have fixed and flipped your vehicle for 180 Robbery XP." ); PlayerPlaySound( playerid, 1133, 0.0, 0.0, 5.0 ); } case 1: { - if ( total_level < 75 ) { - return SendError( playerid, "Your total level must be at least 75 to use this (/level)." ); - } - - if ( GetPlayerCash( playerid ) < 7500 ) { - return SendError( playerid, "You do not have enough money for this item ($7,500)." ); + if ( total_robbery_xp < 120 ) { + return SendError( playerid, "You need at least 120 Robbery XP for this item." ); } new vehicleid = GetPlayerVehicleID( playerid ); PlayerPlaySound( playerid, 1133, 0.0, 0.0, 5.0 ); RepairVehicle( vehicleid ); - GivePlayerCash( playerid, -7500 ); - SendServerMessage( playerid, "You have repaired your car for $7,500." ); + GivePlayerExperience( playerid, E_ROBBERY, -120, .with_dilation = false ); + SendServerMessage( playerid, "You have repaired your car for 120 Robbery XP." ); } case 2: { - if ( total_level < 50 ) { - return SendError( playerid, "Your total level must be at least 50 to use this (/level)." ); - } - - if ( GetPlayerCash( playerid ) < 3000 ) { - return SendError( playerid, "You do not have enough money for this item ($3,000)." ); + if ( total_robbery_xp < 80 ) { + return SendError( playerid, "You need at least 80 Robbery XP for this item." ); } AddVehicleComponent( GetPlayerVehicleID( playerid ), 1010 ); - GivePlayerCash( playerid, -3000 ); - SendServerMessage( playerid, "You have installed nitro on your car for $3,000." ); + GivePlayerExperience( playerid, E_ROBBERY, -80, .with_dilation = false ); + SendServerMessage( playerid, "You have repaired your car for 80 Robbery XP." ); PlayerPlaySound( playerid, 1133, 0.0, 0.0, 5.0 ); } case 3: { - if ( total_level < 40 ) { - return SendError( playerid, "Your total level must be at least 40 to use this (/level)." ); - } - - if ( GetPlayerCash( playerid ) < 2500 ) { - return SendError( playerid, "You do not have enough money for this item ($2,500)." ); + if ( total_robbery_xp < 50 ) { + return SendError( playerid, "You need at least 50 Robbery XP for this item." ); } new Float: vZ, vehicleid = GetPlayerVehicleID( playerid ); GetVehicleZAngle( vehicleid, vZ ), SetVehicleZAngle( vehicleid, vZ ); - GivePlayerCash( playerid, -2500 ); - SendServerMessage( playerid, "You have flipped your vehicle for $2,500." ); + GivePlayerExperience( playerid, E_ROBBERY, -50, .with_dilation = false ); + SendServerMessage( playerid, "You have repaired your car for 50 Robbery XP." ); PlayerPlaySound( playerid, 1133, 0.0, 0.0, 5.0 ); } } @@ -219,11 +196,11 @@ CMD:perks( playerid, params[ ] ) { if ( IsPlayerInEvent( playerid ) || IsPlayerInBattleRoyale( playerid ) ) return SendError( playerid, "You cannot use this command since you're in an event." ); - + if ( IsPlayerInArmyVehicle( playerid ) ) return SendError( playerid, "You cannot use this command while in an army vehicle." ); - return ShowPlayerDialog( playerid, DIALOG_PERKS, DIALOG_STYLE_LIST, "{FFFFFF}Game Perks", "Player Perks\nVehicle Perks", "Select", "Cancel" ); + return ShowPlayerDialog( playerid, DIALOG_PERKS, DIALOG_STYLE_LIST, "{FFFFFF}Game Perks", "Deathmatch Perks\nRobbery Perks", "Select", "Cancel" ); } /* ** Functions ** */ diff --git a/gamemodes/irresistible/cnr/features/player/experience.pwn b/gamemodes/irresistible/cnr/features/player/experience.pwn index f8cfb00..3978b9a 100644 --- a/gamemodes/irresistible/cnr/features/player/experience.pwn +++ b/gamemodes/irresistible/cnr/features/player/experience.pwn @@ -34,7 +34,7 @@ enum E_LEVELS { enum E_LEVEL_DATA { E_NAME[ 16 ], E_COLOUR, - Float: E_MAX_UNITS, Float: E_XP_DILATION + Float: E_MAX_UNITS, Float: E_XP_DILATION, Float: E_SELL_VALUE }; enum E_RANK_DATA @@ -49,10 +49,10 @@ static const static const g_levelData [ ] [ E_LEVEL_DATA ] = { - // Level Name Bar Color Level 100 Req. XP Dilation (just to confuse user) - { "Police", 0x3E7EFFFF, 7500.0, 20.0 }, // 7.5k arrests - { "Robbery", 0xF83245FF, 30000.0, 15.0 }, // 30K robberies - { "Deathmatch", 0xFF9233FF, 75000.0, 10.0 } // 75K kills + // Level Name Bar Color Level 100 Req. XP Dilation Sell Value + { "Police", 0x3E7EFFFF, 7500.0, 20.0, 10.0 }, // 7.5k arrests + { "Robbery", 0xF83245FF, 30000.0, 15.0, 10.0 }, // 30K robberies + { "Deathmatch", 0xFF9233FF, 75000.0, 10.0, 5.0 } // 75K kills /* { "Fireman", 10000.0, 9.0 }, // 10k fires { "Hitman", 1500.0, 4.5 }, // 1.5k contracts @@ -106,6 +106,41 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) if ( dialogid == DIALOG_VIEW_LEVEL && response ) { return cmd_level( playerid, sprintf( "%d", GetPVarInt( playerid, "experience_watchingid" ) ) ), 1; } + else if ( dialogid == DIALOG_XPMARKET && response ) + { + return ShowPlayerSellXPDialog( playerid, listitem ); + } + else if ( dialogid == DIALOG_XPMARKET_SELL ) + { + if ( ! response ) { + return cmd_xpmarket( playerid, "" ); + } + + new level = GetPVarInt( playerid, "selling_xp_level" ); + new total_xp = floatround( g_playerExperience[ playerid ] [ E_LEVELS: level ], floatround_floor ); + new xp_amount = strval( inputtext ); + + if ( ! ( 0 < xp_amount < 10000000 ) ) + { + SendError( playerid, "You have specified an invalid amount of %s XP.", g_levelData[ level ] [ E_NAME ] ); + return ShowPlayerSellXPDialog( playerid, level ); + } + else if ( xp_amount > total_xp ) + { + SendError( playerid, "You do not have this much %s XP.", g_levelData[ level ] [ E_NAME ] ); + return ShowPlayerSellXPDialog( playerid, level ); + } + else + { + new + credit = floatround( float( xp_amount ) * g_levelData[ level ] [ E_SELL_VALUE ], floatround_floor ); + + GivePlayerCash( playerid, credit ); + GivePlayerExperience( playerid, E_LEVELS: level, -xp_amount, .with_dilation = false ); + SendServerMessage( playerid, "You have sold %s %s XP for "COL_GOLD"%s"COL_WHITE".", g_levelData[ level ] [ E_NAME ], number_format( xp_amount ), cash_format( credit ) ); + } + return 1; + } return 1; } @@ -205,7 +240,7 @@ CMD:level( playerid, params[ ] ) new player_total_lvl = 0; - szLargeString = ""COL_GREY"Skill\t"COL_GREY"Current Level\t"COL_GREY"XP Till Next Level\n"; + szLargeString = ""COL_GREY"Skill\t"COL_GREY"Current Level\t"COL_GREY"XP Till Next Level\t"COL_GREY"Total XP\n"; for ( new level_id; level_id < sizeof( g_levelData ); level_id ++ ) { @@ -214,7 +249,7 @@ CMD:level( playerid, params[ ] ) new Float: next_lvl_xp = ( g_levelData[ level_id ] [ E_MAX_UNITS ] * g_levelData[ level_id ] [ E_XP_DILATION ] ) / ( EXP_MAX_PLAYER_LEVEL * EXP_MAX_PLAYER_LEVEL ) * ( next_lvl * next_lvl ); player_total_lvl += floatround( current_rank, floatround_floor ); - format( szLargeString, sizeof( szLargeString ), "%s%s Level\t%s%0.0f / %0.0f\t"COL_PURPLE"%0.0f XP\n", szLargeString, g_levelData[ level_id ] [ E_NAME ], current_rank >= 100.0 ? ( COL_GREEN ) : ( COL_GREY ), current_rank, EXP_MAX_PLAYER_LEVEL, next_lvl_xp - g_playerExperience[ watchingid ] [ E_LEVELS: level_id ] ); + format( szLargeString, sizeof( szLargeString ), "%s%s Level\t%s%0.0f / %0.0f\t"COL_PURPLE"%0.0f XP\t"COL_GREY"%s\n", szLargeString, g_levelData[ level_id ] [ E_NAME ], current_rank >= 100.0 ? ( COL_GREEN ) : ( COL_GREY ), current_rank, EXP_MAX_PLAYER_LEVEL, next_lvl_xp - g_playerExperience[ watchingid ] [ E_LEVELS: level_id ], number_format( g_playerExperience[ playerid ] [ E_LEVELS: level_id ], .decimals = 0 ) ); } SetPVarInt( playerid, "experience_watchingid", watchingid ); @@ -237,6 +272,19 @@ CMD:rank( playerid, params[ ] ) return 1; } +CMD:xpmarket( playerid, params[ ] ) +{ + // header + szBigString = ""COL_GREY"Skill\t"COL_GREY"Total XP\t"COL_GREY"Value ($)\n"; + + // level with user xp + for ( new level_id; level_id < sizeof( g_levelData ); level_id ++ ) { + new value = floatround( g_playerExperience[ playerid ] [ E_LEVELS: level_id ] * g_levelData[ level_id ] [ E_SELL_VALUE ] ); + format( szBigString, sizeof( szBigString ), "%s%s Level\t"COL_PURPLE"%s XP\t"COL_GREEN"%s\n", szBigString, g_levelData[ level_id ] [ E_NAME ], number_format( g_playerExperience[ playerid ] [ E_LEVELS: level_id ], .decimals = 0 ), cash_format( value ) ); + } + return ShowPlayerDialog( playerid, DIALOG_XPMARKET, DIALOG_STYLE_TABLIST_HEADERS, "{FFFFFF}XP Market", szBigString, "Select", "Close" ), 1; +} + /* ** SQL Threads ** */ thread Experience_OnLoad( playerid ) { @@ -279,13 +327,18 @@ thread currentUserRank( playerid, watchingid ) } /* ** Functions ** */ +stock Float: GetPlayerExperience( playerid, E_LEVELS: level ) +{ + return g_playerExperience[ playerid ] [ level ]; +} + stock GivePlayerExperience( playerid, E_LEVELS: level, Float: default_xp = 1.0, bool: with_dilation = true ) { if ( ! IsPlayerLoggedIn( playerid ) || ! ( 0 <= _: level < sizeof( g_levelData ) ) ) return 0; // dilation is there so people see +3 when they arrest ... could trigger dopamine levels instead of constantly +1 lol - new Float: xp_earned = default_xp * ( IsDoubleXP( ) ? 2.0 : 1.0 ) * ( with_dilation ? ( g_levelData[ _: level ] [ E_XP_DILATION ] ) : 1.0 ); + new Float: xp_earned = default_xp * ( IsDoubleXP( ) && default_xp > 0.0 ? 2.0 : 1.0 ) * ( with_dilation ? ( g_levelData[ _: level ] [ E_XP_DILATION ] ) : 1.0 ); // when a player ranks up new next_lvl = floatround( GetPlayerLevel( playerid, level ), floatround_floor ) + 1; @@ -310,7 +363,7 @@ stock GivePlayerExperience( playerid, E_LEVELS: level, Float: default_xp = 1.0, } // seasonal - GivePlayerSeasonalXP( playerid, xp_earned ); + if ( default_xp ) GivePlayerSeasonalXP( playerid, xp_earned ); // alert user KillTimer( p_playerExpHideTimer[ playerid ] ); @@ -318,7 +371,7 @@ stock GivePlayerExperience( playerid, E_LEVELS: level, Float: default_xp = 1.0, PlayerTextDrawShow( playerid, p_playerExpTitle[ playerid ] ); SetPlayerProgressBarColour( playerid, p_playerExpProgress[ playerid ], g_levelData[ _: level ] [ E_COLOUR ] ); ShowPlayerProgressBar( playerid, p_playerExpProgress[ playerid ] ); - PlayerTextDrawSetString( playerid, p_playerExpAwardTD[ playerid ], sprintf( "+%0.0f XP", xp_earned ) ); + PlayerTextDrawSetString( playerid, p_playerExpAwardTD[ playerid ], sprintf( "%s%0.0f XP", xp_earned < 0.0 ? ( "~r~" ) : ( "+" ), xp_earned ) ); PlayerTextDrawShow( playerid, p_playerExpAwardTD[ playerid ] ); p_playerExpHideTimer[ playerid ] = SetTimerEx( "Experience_HideIncrementTD", 3500, false, "d", playerid ); @@ -443,6 +496,25 @@ stock GivePlayerSeasonalXP( playerid, Float: default_xp ) mysql_single_query( sprintf( "UPDATE `USERS` SET `RANK` = %f WHERE `ID` = %d", current_season_xp, GetPlayerAccountID( playerid ) ) ); } +stock ShowPlayerSellXPDialog( playerid, level ) +{ + new value = floatround( g_playerExperience[ playerid ] [ E_LEVELS: level ] * g_levelData[ level ] [ E_SELL_VALUE ] ); + + format( szBigString, sizeof( szBigString ), + ""COL_WHITE"Please input how much %s XP you want to sell.\n\n"\ + "Exchange Rate is "COL_GOLD"1 XP"COL_WHITE" for %s\n\n"\ + "You have %s XP that can be sold for %s\n\n"\ + ""COL_RED"Warning: this action will result in a reduced level.", + g_levelData[ level ] [ E_NAME ], + cash_format( g_levelData[ level ] [ E_SELL_VALUE ], .decimals = 0 ), + number_format( g_playerExperience[ playerid ] [ E_LEVELS: level ], .decimals = 0 ), + cash_format( value, .decimals = 0 ) + ); + + SetPVarInt( playerid, "selling_xp_level", level ); + return ShowPlayerDialog( playerid, DIALOG_XPMARKET_SELL, DIALOG_STYLE_INPUT, "{FFFFFF}XP Market", szBigString, "Sell", "Cancel"); +} + /* ** Macros ** */ stock GetSeasonalRankName( rankid, dest[ ], dest_size = sizeof( dest ) ) { return format( dest, dest_size, "%s", g_seasonalRanks[ rankid ] [ E_NAME ] );