AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Code Snippets/Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=83)
-   -   Dynamic number of arguments in functions (https://forums.alliedmods.net/showthread.php?t=133196)

ot_207 07-22-2010 20:15

Dynamic number of arguments in functions
 
Well we all know how to create a function but what about a function that uses dynamic number of parameters.
I recommend not reading if you do not have basic scripting knowledge.


PHP Code:

public function_add(num1num2result)
{
    
result num1 num2


But how can we create a function that uses a dynamic set of parameters?
Well the answer is simple you just need to use these functions:
For example for the function that we made above we can do something like this:

PHP Code:

public function_add( ... )
{
    
// For reading the first argument you must always use getarg(0)
    // It starts with 0
    
setarg(2getarg(0)+getarg(1))


As you see this function does not contain any arguments at all just dots.
That means that the number of parameters can vary.

Is this limited only to integer values?
No you can also copy vectors, strings, and Float values.
Here is a basic example

Float example:
PHP Code:

public function_mean( ... )
{
    
// You need to pass the first 2 arguments as float values or else this calculation
    // Will be messed up
    // Also the third parameter is a integer (normal value)
    
setarg(2floatround((Float:getarg(1)+Float:getarg(0)) / 2.0))


String example:
PHP Code:

// We think that the string is in the first argument
public function_copystring( ... )
{
    
// position is the index that allows us to copy each cell of the string or array
    // len is the maximum character capacity of the string
    // string represents the array where we store text messages
    // ch is the character, the place where we will hold the value (just to avoid more calls)
    
new positionchstring[100], len
    len 
charsmax(string)
    
    
// We are testing to see if we reached the maximum capacity of the string, and also see if we get a value from the string that we are trying to read.
    
while ( (position len) && (ch getarg(0position)) )
    {
        
// Store the ch value
        
string[position] = ch
        
// Increment the position for allowing the next cell to load
        
position++;
    }
    
    
// We need to do this because the string the ending character
    
string[position] = '^0';
    
position++;
    
    
// Now that we have the string copied, print it to the server
    
server_print(string)


How is this useful?
Well for example I used it to create a way for sending text messages more easily.

This is what my function looks like:
PHP Code:

/* This function uses a different system of getting arguments see funcwiki for details
*  Params:
*  - id, player id
*  - print_type (ex: print_chat, print_center, etc.) 
*  - string to send to player (ex: #Alias_Not_Avail)
*  - the rest, more strings, see cstrike_english.txt to see how much strings you need in this message (you need to count the "%s" parts coresponding a tag)

*  Return:
*  - None.
*/

sendTxtMsg(any: ...)
{
    new 
numstring numargs() - 2
    
new string[100]
    new 
poschtotalchars charsmax(string)
    
    
message_begin(MSG_ONEget_user_msgid("TextMsg"), _getarg(0))
    
write_byte(getarg(1))
    
    for (new 
i=0numstringi++)
    {
        
// Here we copy the sting that we want to send to a player
        
pos 0;
        while (
pos totalchars && (ch getarg(ipos))) 
        {
            
string[pos++] = ch
        
}
        
        
// Add ending to the string (necessary)
        
string[pos++] = '^0';
        
        
//server_print("STRING %s", string)
        // Send it!
        
write_string(string)
    }
    
    
// End the function chain
    
message_end()


And now I can easily transmit every client message easily.
For example instead of writing:
PHP Code:

    message_begin(MSG_ONEget_user_msgid("TextMsg"), _id);
    
write_byte(print_center);
    
write_string("#Alias_Not_Avail");
    
write_string("Item");
    
message_end(); 

I use it like this:
PHP Code:

sendTxtMsg(idprint_center"#Alias_Not_Avail""Item"

And the beauty of it is that it supports dynamic number of parameters. That means that I do not need to adapt my code for each text message type. I just need to add one more string to the function parameters. So more readable and easier.
Example:
PHP Code:

// For "Cstrike_TitlesTXT_Game_radio"        
// "%s1 (RADIO): %s2"
sendTxtMsg(idprint_center"#Cstrike_TitlesTXT_Game_radio""Youpii""Having fun mate!"

And I do not need to create another function specially for this.

Hawk552 07-22-2010 22:37

Re: Dynamic number of arguments in functions
 
This is one of the most incomplete tutorials I've ever seen. You should really cover topics such as the vformat() and format_args() functions, which basically do half of the work for you that this tutorial teaches you how to do manually (and unnecessarily except for demonstration).

Alucard^ 07-22-2010 23:29

Re: Dynamic number of arguments in functions
 
Good job OT, this is usefull for me.

ConnorMcLeod 07-23-2010 01:55

Re: Dynamic number of arguments in functions
 
For TextMsg i guess something like HLSDK would be more efficient.
Your tut is still usefull though.

PHP Code:

// Based on HLSDK ClientPrint and UTIL_ClientPrintAll from util.cpp
Util_ClientPrint(idiMsgDestszMessage[], szSubMessage1[] = ""szSubMessage2[] = ""szSubMessage3[] = ""szSubMessage4[] = "")
{
    
message_begin(id MSG_ONE_UNRELIABLE MSG_BROADCASTg_iTextMsg, .player=id)
    {
        
write_byte(iMsgDest)
        
write_string(szMessage)
        if( 
szSubMessage1[0] )
        {
            
write_string(szSubMessage1)
        }
        if( 
szSubMessage2[0] )
        {
            
write_string(szSubMessage2)
        }
        if( 
szSubMessage3[0] )
        {
            
write_string(szSubMessage3)
        }
        if( 
szSubMessage4[0] )
        {
            
write_string(szSubMessage4)
        }
    }
    
message_end()


Code:

void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 )
{
        MESSAGE_BEGIN( MSG_ONE, gmsgTextMsg, NULL, client );
                WRITE_BYTE( msg_dest );
                WRITE_STRING( msg_name );

                if ( param1 )
                        WRITE_STRING( param1 );
                if ( param2 )
                        WRITE_STRING( param2 );
                if ( param3 )
                        WRITE_STRING( param3 );
                if ( param4 )
                        WRITE_STRING( param4 );

        MESSAGE_END();
}


Arkshine 07-23-2010 05:53

Re: Dynamic number of arguments in functions
 
I'm using such natives in Server Cvars Unlocker plugin, it helps nicely to have a code more easy and more readable.

Good job, though like Hawk, it's quite short.

ot_207 07-23-2010 07:27

Re: Dynamic number of arguments in functions
 
Quote:

Originally Posted by Hawk552 (Post 1248624)
This is one of the most incomplete tutorials I've ever seen. You should really cover topics such as the vformat() and format_args() functions, which basically do half of the work for you that this tutorial teaches you how to do manually (and unnecessarily except for demonstration).

Will add those functions.

@all:
Thank you! And will update it sooner with more stuff. I wrote it when I was tired. :P

abdul-rehman 07-24-2010 03:36

Re: Dynamic number of arguments in functions
 
cool tut thnx :D

ehha 07-27-2010 13:22

Re: Dynamic number of arguments in functions
 
How can i do this?
PHP Code:

public function_meansome_intsome_float, ... ) 
{
    
//bla


What index would the other parameters have?

Emp` 07-27-2010 13:26

Re: Dynamic number of arguments in functions
 
Quote:

Originally Posted by ehha (Post 1253215)
How can i do this?
PHP Code:

public function_meansome_intsome_float, ... ) 
{
    
//bla


What index would the other parameters have?

PHP Code:

public function_meansome_intFloat:some_float, ... ) 
{
    
//some_int is considered parameter 0
    //some_float is considered parameter 1
    //therefore the next parameter would start at 2


It should also be noted that you can tag the dynamic arguments in order to prevent tag mismatch warnings.
PHP Code:

public function_meanFloat:... )
{
    
// You need to pass the first 2 arguments as float values or else this calculation
    // Will be messed up
    // Also the third parameter is a integer (normal value)
    
setarg(2floatround((Float:getarg(1)+Float:getarg(0)) / 2.0))



ehha 07-27-2010 14:18

Re: Dynamic number of arguments in functions
 
Thank you both :)
One more thing, can i pass any type of data with func( any: ... ) as long as it is handled properly inside the function without tagging it again when i handle it?
For example if i pass a float, int and a bool, to i always have to tag it like this?
PHP Code:

funcany: ... )
{
    if( 
bool:getarg(2))
        return 
floatroundFloat:getarg(0) + getarg(1) / 2.0 );
    else
        return 
getarg(1)


The short main question: do i need the bool and Float tags if i use the tag "any"?


All times are GMT -4. The time now is 07:24.

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