---
title: User Created Functions
slug: gpc/gpc-scripting-user-created-functions
description: As well as having a significant number of built in functions, GPC allows the user to create their own custom functions. A function can run any code valid in the main section and code is also executed in the order it is written.
docTags: 
createdAt: 2022-02-05T14:52:01.000Z
---

As well as having a significant number of built-in functions, GPC allows a user to create their own custom functions. A function can run any code valid in the main section and code is also executed in the order it is written.

:::CodeblockTabs
GPC

```apex
main {
    
    if (get_val(PS4_CROSS)) {                    // If PS4_CROSS is held
        if (myfunction(10, 20) == 30) {          // If myfunction returns a value of 30
            combo_run(mycombo);                  // run combo mycombo
        }
        else if (myfunction(10, 20) == -10) {    // If myfunction returns a value of -10
            combo_stop(mycombo);                 // stop mycombo if it is running
        }
    }

}

combo mycombo {
    set_val(PS4_TRIANGLE, 100);
    wait(1000);
    wait(1000);
}

function myfunction(_1stvalue, _2ndvalue) {      // myfunction start

    if (get_val(PS4_CIRCLE)) {                   // If PS4_CIRCLE is held
        return _1stvalue + _2ndvalue;            // return _1stvalue plus _2ndvalue
    }
    return _1stvalue - _2ndvalue;                // return _1stvalue minus _2ndvalue
}
```
:::

# Calling a Function

:::CodeblockTabs
GPC

```apex
myfunction(10, 20);
```
:::

To call (or run) a **function**, you simply type its name and put any parameters it requires in between ( and ).&#x20;
When a function is called, the code within it is executed and the **return&#x20;**&#x76;alue is sent back to where it was called from. &#x20;
User **functions&#x20;**&#x61;re what is known as global scope, this means they can be called from the **init, main&#x20;**&#x61;nd **combo** sections.  They can even be called from within another **function**, however, GPC does not support recursive calls of functions.  This means a **function&#x20;**&#x63;annot be called from within itself.

## Function Name and Declaration

:::CodeblockTabs
GPC

```apex
function myfunction() {}
```
:::

To declare a function type `function` followed by a name and ().  Within the parenthesis () you place the names of any parameters you would like the function to have if any. Function names and parameters follow the same rules as a variable, they can start with either an underscore ( \_ ) or a letter and can be followed by any combination of letters, digits or underscores.


🔴 **Syntax**

function \<name> ( \<Parameter(s) >);

⚪  **Parameters**

\<name>: The name of the function
\<Parameter(s) > : Optional parameters. You can use as many as you wish or none at all. Each one must be separated with a comma (,)

## Function Parameters

:::CodeblockTabs
GPC

```apex
function myfunction() {}
```
:::

Function parameters can be thought of as local variables as they cannot be accessed outside of the function they are defined within. A value can be passed to them and they can be used within the function just like a variable could.

As GPC only supports one data type (16bit Integers) you do not need to specify the data type of parameters within a function and the name of a parameter follows the same rules as a function or variable, they can start with either an underscore ( \_ ) or a letter and can be followed by any combination of letters, digits or underscores.
Function parameters are optional. You are not required to have any at all. The example above is perfectly valid.

# Returning from a function

**return&#x20;**&#x69;s a command unique to functions.  It is not mandatory for each user **function&#x20;**&#x74;o have a **return** value though. If there is no return in a function, then 0 (zero) will be automatically returned.
You can have multiple **return&#x20;**&#x70;oints within a function.  Once the first **return&#x20;**&#x63;ommand is executed, the function returns a value to where it was called and the **function&#x20;**&#x69;s terminated.  The code beyond that point in the function will not be run.
Returning a value is one of the single most useful commands within a **function&#x20;**&#x61;s it can be used as a boolean value to enable or disable sections of code, to set parameters in other functions, or to set a variable to the desired value.  In the following example, you will see a couple of uses for the **return&#x20;**&#x63;ommand;

:::CodeblockTabs
GPC

```apex
int RF_HOLD = 40;
int RF_NULL = 30;
main {
    if(myfunction()) {
        if(get_val(XB1_RT)) {
            combo_run(Rapid_Fire); 
        }
    }
}
combo Rapid_Fire {
    set_val(XB1_RT, 100);
    wait(RF_HOLD);
    set_val(XB1_RT, 0);
    wait(RF_NULL);
    set_val(XB1_RT, 0);
}
function myfunction() {
    if(get_val(XB1_VIEW)) {
        if(get_val(XB1_A))
            RF_HOLD = adjust_speed(RF_HOLD, 10, 1000, 10);
        if(get_val(XB1_B))
            RF_NULL = adjust_speed(RF_NULL, 10, 1000, 10);
        set_val(XB1_A, 0);
        set_val(XB1_B, 0);
        set_val(XB1_LB, 0);
        set_val(XB1_RB, 0);
        set_val(XB1_VIEW, 0);
        set_val(TRACE_1, RF_HOLD / 10);
        set_val(TRACE_2, RF_NULL / 10);
        return 0;           //Return a value of 0
    }
    return 1;               //Return a value of 1
}
function adjust_speed(var, min_value, max_value, adjustment_increment) {
    if(event_press(XB1_RB) && var < max_value)
        var = var + adjustment_increment;
    if(event_press(XB1_LB) && var > min_value)
        var = var - adjustment_increment;
    return var;
}
```
:::

## Putting it all together

When the GPC script is first loaded, the two variables **RF\_HOLD** and **RF\_NULL** are created with a value of 40 and 30 respectively.
The main section then starts its first iteration (run).   When it gets to the line below the myfunction() function is executed.

:::CodeblockTabs
GPC

```apex
if(myfunction()) {
```
:::

The code in **myfunction()** is then run.  If **XB1\_VIEW** is not being pressed, the code nested in the statement:

:::CodeblockTabs
GPC

```apex
if(get_val(XB1_VIEW)) { //If we get a value from View other than 0
```
:::

**XB1\_VIEW&#x20;**&#x69;s ignored as the **if&#x20;**&#x73;tatement is **FALSE**. So the next line executed in the **function&#x20;**&#x69;s:

:::CodeblockTabs
GPC

```apex
return 1; //If we do not get a value from View, return 1
```
:::

at which point the value of 1 is returned to the statement;

:::CodeblockTabs
GPC

```apex
if(myfunction()) {
```
:::

Thus making the above statement **TRUE** and the code;

:::CodeblockTabs
GPC

```apex
if(get_val(XB1_RT)) { //If we get a value from RT / R2 other than 0
   combo_run(Rapid_Fire);  //Run combo Rapid_Fire
}
```
:::

which is nested within that statement is ignored and not executed.
If **XB1\_VIEW** and **XB1\_A** are both held when **myfunction()** is executed, then the following line of code is reached and run;

:::CodeblockTabs
GPC

```apex
if(get_val(XB1_A))
            RF_HOLD = adjust_speed(RF_HOLD, 10, 1000, 10);
 
        if(get_val(XB1_B))
            RF_NULL = adjust_speed(RF_NULL, 10, 1000, 10);
 
        set_val(XB1_A, 0);
        set_val(XB1_B, 0);
        set_val(XB1_LB, 0);
        set_val(XB1_RB, 0);
        set_val(XB1_VIEW, 0);
        set_val(TRACE_1, RF_HOLD / 10);
        set_val(TRACE_2, RF_NULL / 10);
 
        return 0; //Return 0
```
:::

As you can see, if **XB1\_A** or **XB1\_B** is not also held down, the code set a few buttons to 0, writes the value of our two variables to TRACE values, and then most importantly, reaches the line:

:::CodeblockTabs
GPC

```apex
return 0; //Return 0
```
:::

at which point a value of 0 is returned to the statement;

:::CodeblockTabs
GPC

```apex
if(myfunction()) {
```
:::

making it **FALSE**, so the code;

:::CodeblockTabs
GPC

```apex
if(get_val(XB1_RT)) { //If we get a value from RT / R2 other than 0
    combo_run(Rapid_Fire);  //Run combo Rapid_Fire
}
```
:::

which is nested within that statement is ignored and not executed.
If **XB1\_VIEW** and **XB1\_A** are both held when **myfunction()** is executed, then the following line of code is reached and run;

:::CodeblockTabs
GPC

```apex
RF_HOLD = adjust_speed(RF_HOLD, 10, 1000, 10);
```
:::

what the above line means is the variable RF\_HOLD equals the return value of the **function&#x20;**'adjust\_speed' or you could say the return value from 'adjust\_speed' is stored in RF\_HOLD.  So let's take a look at how that function **returns&#x20;**&#x61; value.
As you can see above, four values are being sent to the **function&#x20;**'adjust\_speed'.  The value of RF\_HOLD, 10, 1000, and 10. So let's take a look at the declaration of the **function&#x20;**'adjust\_speed';

:::CodeblockTabs
GPC

```apex
function adjust_speed(var, min_value, max_value, adjustment_increment) {
```
:::

**function** 'adjust\_speed' requires 4 arguments, the variable to be adjusted, the minimum value you want it to be, the maximum value you wish for it to be and how much to adjust it by each increment.&#x20;
To manipulate the variable, the function executes the following code;

:::CodeblockTabs
GPC

```apex
if(event_press(XB1_RB) && var < max_value)
        var = var + adjustment_increment;
 
    if(event_press(XB1_LB) && var > min_value)
        var = var - adjustment_increment;
 
    return var;
```
:::

In the first part of this code, if **XB1\_RB** is pressed and the variable value passed to the **function&#x20;**&#x69;s less than the maximum value allowed, the value passed in the fourth parameter (10 in this case) is added to the value of var.  The value of var is returned to where the **function&#x20;**&#x69;s called.  Therefore making RF\_HOLD equal 10 more than it did before.
I&#x66;**&#x20;XB1\_LB&#x20;**&#x69;s pressed and the variable value passed to the function is greater than the minimum value allowed, the value passed in the fourth parameter is subtracted from the value of var.  The value of var is returned to where the **function&#x20;**&#x69;s called.  Therefore making RF\_HOLD equal 10 less than it did before.
An identical process is carried out if **XB1\_VIEW** an&#x64;**&#x20;XB1\_B** are pressed when 'myfunction()' is executed with the exception being that RF\_NULL is adjusted rather than RF\_HOLD.

