Raised This Month: $12 Target: $400
 3% 

[TUT] nVault Top 15


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 05-13-2018 , 13:01   [TUT] nVault Top 15
Reply With Quote #1

nVault Top 15

Over the years I've seen many scripters ask how to create a top 15 for data that is stored in nVault. Since the nVault module has no retrieve-all or sorting functionality this is not possible without the use of nVault Utility. While not required to complete this, I am providing an example using the nVault Array include since I think this is a cleaner approach than storing all data as a string and then parsing components of the string for the calculation.

High-level explanation for how nVault Utility works:
nVault Utility uses the file natives to read data from the vault file in binary format. Each item (key:data) in nVault is stored at an offset within the file, with 0 being the position of the first record, the next record is positioned based off of the size of the previous record, etc. This offset, or location of player data, will be used as a reference to the player data to make this top 15 possible.

Steps for creating a Top 15:
  1. Read all records in the vault file and store the player-data offset and XP value to a 2-dimension array.
  2. Sort this array using the XP value as the sort value.
  3. Loop through this sorted array to build the top 15. With each iteration, the players data offset will be used to re-read their data from the vault. Any piece of data that is stored in the nVault array record can be used in the top 15 (name, steam id, xp, etc).
Requirements:Note: You must delete your vault file or prune all data before implementing this since nvault_read_array() will fail if you try to read data that was not stored using nvault_set_array().

Plugin chat commands:
  • top15 - Display the top 15.
  • loadtestdata - Loads 100 test records to the vault in 'Player_# [XP]' format. The players name includes their stored XP value so you can confirm it is sorting accurately.
PHP Code:

#include <amxmodx>
#include <nvault>
#include <nvault_util>
#include <nvault_array>

//Allocate additional memory to plugin to prevent stack error
#pragma dynamic 16384

new const Version[] = "0.1";

new const 
VaultName[] = "XP_Top15_Example";

//This determines the max number of players that will be included in your top 15 calculation. It is best to keep this at a 
//value <= the max players that you expect to have data saved in the vault. If the number of player data saved exceeds this
//value then your top 15 will not be accurate since some players will be left out.
const Max_Player_Support 3000;

//Components of data that will be saved for each player.
enum PlayerData
{
    
PlayerName32 ],
    
XP
}

new 
pdDataMAX_PLAYERS ][ PlayerData ];
new 
g_AuthIDMAX_PLAYERS ][ 34 ];
new 
bool:g_BotOrHLTVMAX_PLAYERS ];
new 
g_Vault;

//In your plugin, you set a players XP using the below:
//pdData[ id ][ XP ] = 12345;
    
public plugin_init() 
{
    
register_plugin"nVault Top 15" Version "bugsy" );
    
    
register_clcmd"say top15" "ShowTop15" );
    
register_clcmd"say loadtestdata" "LoadTestData" );
    
    if ( ( 
g_Vault nvault_openVaultName ) ) == INVALID_HANDLE )
    {
        
set_fail_state"Failed to open vault" );
    }
}

public 
plugin_end() 
{
    
nvault_closeg_Vault );
}

public 
client_authorizedid )
{
    if ( !( 
g_BotOrHLTVid ] = bool:( is_user_botid ) || is_user_hltvid ) ) ) )
    {
        
//Get players' steam-id so it can be used to retrieve their data from the vault.
        
get_user_authidid g_AuthIDid ] , charsmaxg_AuthID[] ) );
        
        
//Retrieve player data from vault. 
        
nvault_get_arrayg_Vault g_AuthIDid ] , pdDataid ][ PlayerData:] , sizeofpdData[] ) );
    }
}

public 
client_disconnectid )
{
    if ( !
g_BotOrHLTVid ] )
    {
        
//To avoid having to monitor for name changes in-game, the players name is retrieved and saved when disconnecting.
        
get_user_nameid pdDataid ][ PlayerName ] , charsmaxpdData[][ PlayerName ] ) );
        
        
//Save player data to vault.
        
nvault_set_arrayg_Vault g_AuthIDid ] , pdDataid ][ PlayerData:] , sizeofpdData[] ) );
    }
}

public 
ShowTop15id )
{
    
enum _:Top15Info
    
{
        
nVault_Offset,
        
XP_Value
    
}
    
    static 
iSortDataMax_Player_Support ][ Top15Info ];
    
    new 
iVault iRow iCount iNextOffset iCurrentOffset szKey45 ] , iAvailablePlayers pdValPlayerData ];
    new 
szMOTD1501 ] , iPos;
    
    
//Close and re-open vault so the journal writes to the vault so nvault_util gets most up to date data.
    
nvault_closeg_Vault );
    
g_Vault nvault_openVaultName );
    
    
//Open vault for nvault utility usage.
    
iVault nvault_util_openVaultName );
    
    
//Get count of total number of records in the vault.
    
iCount nvault_util_countiVault );
    
    
//Loop through all records in the vault.
    
for ( iRow iRow iCount && iRow Max_Player_Support iRow++ )
    {
        
//Read record from vault. iNextOffset will hold the position of the next record in the vault.
        
iNextOffset nvault_util_read_arrayiVault iNextOffset szKey charsmaxszKey ) , pdValPlayerData:] , sizeofpdVal ) );
        
        
//Set nVault_Offset to the byte offset for this players data. This will allow for retrieving any data for this player that needs to appear in the top 15 (name, steam id, etc.)
        //iPrevOffset is used since iOffset holds the position of the NEXT record, not current.
        
iSortDataiRow ][ nVault_Offset ] = iCurrentOffset;
        
        
//Set Player_XP value in array to his XP value. This will be used for sorting.
        
iSortDataiRow ][ XP_Value ] = pdValXP ];
        
        
//Since nvault_util_read_array() holds the position of the next record, we have to hold the current offset separately.
        
iCurrentOffset iNextOffset;
    }
    
    
//Sort the array.
    
SortCustom2DiSortData miniCount Max_Player_Support ) , "CompareXP" );

    
//Prepare top 15 MOTD.
    
iPos formatexszMOTD charsmaxszMOTD ) , "<body bgcolor=#000000><font color=#98f5ff><pre>" );
    
iPos += formatexszMOTDiPos ] , charsmaxszMOTD ) - iPos "%2s %-22.22s %3s^n" "#" "Name" "XP" );
    
    
//This will account for if the vault has less than 15 player data records stored.
    
iAvailablePlayers miniCount 15 );
    
    
//Build the top 15. iAvailablePlayers is set to the smaller of 15 or the total records in the vault.
    
for ( iRow iRow iAvailablePlayers iRow++ )
    {
        
//Get nVault player data offset value which was set in the above loop.
        
iCurrentOffset iSortDataiRow ][ nVault_Offset ];
        
        
//Read data at the players offset so we can retrieve their name to be displayed in the top 15.
        
nvault_util_read_arrayiVault iCurrentOffset szKey charsmaxszKey ) , pdValPlayerData:] , sizeofpdVal ) );
        
        
//Format line in MOTD.
        
iPos += formatexszMOTDiPos ] , charsmaxszMOTD ) - iPos ,"%2d %-22.22s %3d^n", ( iRow ) , pdValPlayerName ] , pdValXP ] );
    }
    
    
//Close nvault utility file.
    
nvault_util_closeiVault );
    
    
formatexszMOTDiPos ], charsmaxszMOTD ) - iPos "</body></font></pre>" );
    
    
show_motdid szMOTD "XP Top 15" );
    
    return 
PLUGIN_HANDLED;
}

public 
LoadTestData()
{
    new 
szAuthID10 ] , pdDataPlayerData ] , iRow iXP;
    
    for ( 
iRow iRow 100 iRow++ )
    {
        
formatexszAuthID charsmaxszAuthID ) , "STEAM_%d" iRow );
        
        
iXP random9999 );
        
        
formatexpdDataPlayerName ] , charsmaxpdDataPlayerName ] ) , "Player_%d [%d]" iRow iXP );
        
pdDataXP ] = iXP;
        
        
nvault_set_arrayg_Vault szAuthID pdDataPlayerData:] , sizeofpdData ) );
    }
    
    return 
PLUGIN_HANDLED;
}

public 
CompareXPelem1[] , elem2[] ) 

    if ( 
elem1] > elem2] ) 
        return -
1
    else if(
elem1] < elem2] ) 
        return 
1
    
    return 
0

__________________

Last edited by Bugsy; 06-28-2019 at 21:48.
Bugsy is offline
soumyadip77
Senior Member
Join Date: Jul 2017
Location: INDIA,KOLKATA
Old 05-14-2018 , 11:18   Re: [TUT] nVault Top 15
Reply With Quote #2

Thanks
i need this from 4 months finally you make it i will make new xp mod with it <3 u bugsy
soumyadip77 is offline
Send a message via Skype™ to soumyadip77
ksaju
New Member
Join Date: Dec 2018
Old 12-28-2018 , 13:41   Re: [TUT] nVault Top 15
Reply With Quote #3

How i can read my xp from my exp mod. I have new gExp[PLAYERS+1];

Code:
enum PlayerData
{
    PlayerName[ 32 ],
    gExp[PLAYERS+1]
}
I can't use that cuz error

Please help me.

Last edited by ksaju; 12-28-2018 at 13:42.
ksaju is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 12-28-2018 , 15:43   Re: [TUT] nVault Top 15
Reply With Quote #4

new gExp[ PLAYERS + 1 ][ PlayerData ]

Then you can use gExp[ id ][ gExp ]
__________________
Bugsy is offline
ksaju
New Member
Join Date: Dec 2018
Old 12-29-2018 , 06:38   Re: [TUT] nVault Top 15
Reply With Quote #5

<56> error 021: symbol already defined: "gExp"
Code:
enum PlayerData
{
    PlayerName[ 32 ],
    gExp[PLAYERS+1]
}
new gMaxHealth[PLAYERS+1], gExp[PLAYERS+1][PlayerData], gLvl[PLAYERS+1], gPoint[PLAYERS+1], gKey[PLAYERS+1];
What I do wrong??
ksaju is offline
OciXCrom
Veteran Member
Join Date: Oct 2013
Location: Macedonia
Old 12-29-2018 , 10:01   Re: [TUT] nVault Top 15
Reply With Quote #6

You have defined two variables named gExp.
__________________
OciXCrom is offline
Send a message via Skype™ to OciXCrom
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 12-29-2018 , 10:13   Re: [TUT] nVault Top 15
Reply With Quote #7

If you are using an enumerator for XP then you may as well use it for all player data to keep things organized. This thread is not a scripting tutorial thread so please do not begin asking basic scripting questions. If you were able to write an XP plugin, you should be able to use my example in this thread to build a top 15.
__________________
Bugsy is offline
quLeryuzz
Member
Join Date: May 2010
Location: Istanbul
Old 06-12-2019 , 11:38   Re: [TUT] nVault Top 15
Reply With Quote #8

Thanks.
https://github.com/yek-ta/AMXX-PLUGI...sctf_stats.sma

__________________

csduragi.com
quLeryuzz is offline
Meelo
Member
Join Date: Aug 2010
Old 07-31-2019 , 15:37   Re: [TUT] nVault Top 15
Reply With Quote #9

How to check position in top? I want to make command like /rank but with this top and my own stats all works but i can't get player position.

Last edited by Meelo; 07-31-2019 at 15:37.
Meelo is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 07-31-2019 , 20:52   Re: [TUT] nVault Top 15
Reply With Quote #10

Quote:
Originally Posted by Meelo View Post
How to check position in top? I want to make command like /rank but with this top and my own stats all works but i can't get player position.
It's not very efficient, especially when you have a lot of records in your vault...I recommend SQL. Only quickly tested.
PHP Code:
public GetRankid )
{
    
enum _:Top15Info
    
{
        
nVault_Offset,
        
XP_Value
    
}
    
    static 
iSortDataMax_Player_Support ][ Top15Info ];
    
    new 
iVault iRow iCount iNextOffset iCurrentOffset szKey45 ] , pdValPlayerData ] , bool:bRanked;
    
    
//Close and re-open vault so the journal writes to the vault so nvault_util gets most up to date data.
    
nvault_closeg_Vault );
    
g_Vault nvault_openVaultName );
    
    
//Open vault for nvault utility usage.
    
iVault nvault_util_openVaultName );
    
    
//Get count of total number of records in the vault.
    
iCount nvault_util_countiVault );
    
    
//Loop through all records in the vault.
    
for ( iRow iRow iCount && iRow Max_Player_Support iRow++ )
    {
        
//Read record from vault. iNextOffset will hold the position of the next record in the vault.
        
iNextOffset nvault_util_read_arrayiVault iNextOffset szKey charsmaxszKey ) , pdValPlayerData:] , sizeofpdVal ) );
        
        
//Set nVault_Offset to the byte offset for this players data. This will allow for retrieving any data for this player that needs to appear in the top 15 (name, steam id, etc.)
        //iPrevOffset is used since iOffset holds the position of the NEXT record, not current.
        
iSortDataiRow ][ nVault_Offset ] = iCurrentOffset;
        
        
//Set Player_XP value in array to his XP value. This will be used for sorting.
        
iSortDataiRow ][ XP_Value ] = pdValXP ];
        
        
//Since nvault_util_read_array() holds the position of the next record, we have to hold the current offset separately.
        
iCurrentOffset iNextOffset;
    }
    
    
//Sort the array.
    
SortCustom2DiSortData miniCount Max_Player_Support ) , "CompareXP" );
    
    
//Cycle through all records in the vault to see where the player stands in ranking
    
for ( iRow iRow iCount iRow++ )
    {
        
//Get nVault player data offset value which was set in the above loop.
        
iCurrentOffset iSortDataiRow ][ nVault_Offset ];
        
        
//Read data at the players offset so we can get their steam id and compare to player requesting their rank.
        
nvault_util_read_arrayiVault iCurrentOffset szKey charsmaxszKey ) , pdValPlayerData:] , sizeofpdVal ) );
        
        if ( 
equalg_AuthIDid ] , szKey ) )
        {
            
client_printid print_chat "* Your rank is %d" iRow );
            
bRanked true;
            break;
        }
    
    }
    
    if ( !
bRanked )
    {
        
client_printid print_chat "* You are not yet ranked" );
    }
    
    
//Close nvault utility file.
    
nvault_util_closeiVault );
    
    return 
PLUGIN_HANDLED;

__________________

Last edited by Bugsy; 08-01-2019 at 19:01.
Bugsy is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 13:19.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode