AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Code Snippets/Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=83)
-   -   [TUT] nVault Top 15 (https://forums.alliedmods.net/showthread.php?t=307518)

Bugsy 05-13-2018 13:01

[TUT] nVault Top 15
 
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



soumyadip77 05-14-2018 11:18

Re: [TUT] nVault Top 15
 
Thanks
i need this from 4 months :) finally you make it i will make new xp mod with it :) <3 u bugsy

ksaju 12-28-2018 13:41

Re: [TUT] nVault Top 15
 
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.

Bugsy 12-28-2018 15:43

Re: [TUT] nVault Top 15
 
new gExp[ PLAYERS + 1 ][ PlayerData ]

Then you can use gExp[ id ][ gExp ]

ksaju 12-29-2018 06:38

Re: [TUT] nVault Top 15
 
<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??

OciXCrom 12-29-2018 10:01

Re: [TUT] nVault Top 15
 
You have defined two variables named gExp.

Bugsy 12-29-2018 10:13

Re: [TUT] nVault Top 15
 
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.

quLeryuzz 06-12-2019 11:38

Re: [TUT] nVault Top 15
 
Thanks.
https://github.com/yek-ta/AMXX-PLUGI...sctf_stats.sma

https://i.ibb.co/hFMCD2d/20190612025113-1.jpg

Meelo 07-31-2019 15:37

Re: [TUT] nVault Top 15
 
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.

Bugsy 07-31-2019 20:52

Re: [TUT] nVault Top 15
 
Quote:

Originally Posted by Meelo (Post 2661333)
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;




All times are GMT -4. The time now is 12:45.

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