> For the complete documentation index, see [llms.txt](https://officergalvindevelopment.gitbook.io/untitled/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://officergalvindevelopment.gitbook.io/untitled/sepura-sc20-radio/editable-server-functions.md).

# Editable Server Functions

Notes on the Editable Server Functions (sv\_functions.lua)

<mark style="color:yellow;">**Note**</mark> <mark style="color:yellow;"></mark><mark style="color:yellow;">-> There are three default functions in the</mark> `sv_functions.lua`<mark style="color:yellow;">. If you are unsure on how to change parts of them but want something different, please create a ticket and ask.</mark>

## GetPlayerIdentifier

This code defines the `playerIdentifier` variable based on the game framework being used (e.g., Standalone, FMS, ESX, ESX Legacy, QBCore) and specific configuration settings (e.g., `Config.FMS`, `Config.CMA`). The purpose is to obtain the player's identifier or name depending on the framework. Let's break down what each part of the code is doing:

1. The code initializes the `playerIdentifier` variable without assigning it a value at the beginning.
2. It checks the value of `Config.Framework`:
   * If it's equal to `'Standalone'`, then the code enters the first block.
   * If it's equal to `'ESX'` or `'ESX Legacy'`, the code enters the second block.
   * If it's equal to `'QBCore'`, the code enters the third block.
3. Within the first block (for `'Standalone'` framework):
   * It checks `Config.FMS`. If it's `true`, it enters the nested block.
   * In the nested block, it calls an exported function (`exports["fms"]:getPlayerFmsData`) to retrieve player data asynchronously. When the data is retrieved, it sets `playerIdentifier` to `pPlayerData.forcenumber`. This appears to be a unique identifier for the player.
4. In the first block, if `Config.CMA` is `true`, it enters another nested block. However, this block seems to be a placeholder as the comment suggests that documentation is not provided. The `playerIdentifier` is not set in this case.
5. The first block also has a final `else` condition, which sets `playerIdentifier` to the result of `GetPlayerName(pSource)`. This likely retrieves the player's name.
6. Within the second block (for `'ESX'` or `'ESX Legacy'` framework):
   * It retrieves the player's information using framework-specific functions (e.g., `pESX.GetPlayerFromId`) and sets `playerIdentifier` to the player's name using `xPlayer.getName()`.
7. Within the third block (for `'QBCore'` framework):
   * It retrieves the player's information using framework-specific functions (e.g., `pQBCore.Functions.GetPlayer`) and sets `playerIdentifier` to the player's name using `xPlayer.PlayerData.name`.
8. Finally, the code returns the `playerIdentifier`, which now holds the player's identifier or name, depending on the framework.

In summary, this code determines the player's identifier or name based on the game framework and specific configuration settings, and then returns that value in the `playerIdentifier` variable. The actual identifier or name depends on the chosen framework and how the player data is stored and retrieved in each framework.

## IsPlayerOnDuty

1. The code first checks the value of `Config.Framework`:
   * If it's equal to `'Standalone'`, then the code enters the first block.
   * If it's equal to `'ESX'` or `'ESX Legacy'`, the code enters the second block.
   * If it's equal to `'QBCore'`, the code enters the third block.
   * If none of these conditions are met, it enters the `else` block.
2. Within the first block (for `'Standalone'` framework):
   * It checks `Config.FMS`. If it's `true`, it enters the nested block.
   * In the nested block, it checks `Config.CanCivilianAccessRadio`. If true, it sets `isPlayerOnDuty` to `true`.
   * It also calls an exported function (`exports["fms"]:getPlayerFmsData`) and, based on the result, may set `isPlayerOnDuty` to `true`.
3. In the first block, if `Config.CMA` is `true`, it enters another nested block.
   * In this nested block, it checks `Config.CanCivilianAccessRadio`. If true, it sets `isPlayerOnDuty` to `true`.
4. The first block also has a final `else` condition, which sets `isPlayerOnDuty` to `true`.
5. Within the second block (for `'ESX'` or `'ESX Legacy'` framework):
   * It checks `Config.RequireJob`. If false, it sets `isPlayerOnDuty` to `true`.
   * It then retrieves the player's job using the appropriate framework-specific function and checks if the player's job is in the `Config.AllowedJobs`. If true, it sets `isPlayerOnDuty` to `true`.
6. Within the third block (for `'QBCore'` framework):
   * It checks `Config.RequireJob`. If false, it sets `isPlayerOnDuty` to `true`.
   * It then retrieves the player's job using the appropriate framework-specific function and checks if the player's job is in the `Config.AllowedJobs`. If true, it sets `isPlayerOnDuty` to `true`.

In summary, this code is used to determine whether a player is on duty (`isPlayerOnDuty` set to `true`) based on various conditions related to the game framework being used and specific configuration settings. The exact conditions for setting `isPlayerOnDuty` to `true` depend on the framework and configuration settings.

## Panic Button

This code defines a Lua function named `PanicButton(pSource)` which is related to handling a panic button feature. Let's break down what this function does step by step:

1. It defines the `PanicButton` function with a single parameter `pSource`, representing the source or identifier of the player who triggered the panic button.
2. It enters a loop that iterates over all players currently online using the `GetPlayers()` function. This loop is indicated by the `for _, playerId in ipairs(GetPlayers()) do` line, which means it will go through each player's identifier (referred to as `playerId`) one by one.
3. Within the loop, it first checks if the player with the `playerId` is on duty by calling the `IsPlayerOnDuty(playerId)` function. If the player is not on duty, it skips the rest of the code for that player and proceeds to the next player using a `goto` statement labeled as `skip`. This effectively filters out players who are not on duty.
4. After checking if the player is on duty, it proceeds to check their permissions using the `CheckBadgerPermissions(playerId)` function. If the player does not have the required permissions (returns `false`), the function immediately returns without executing the subsequent code for that player.
5. If the player passes the duty and permissions checks, the code proceeds to execute actions:
   * If `Config.DisplayPanicChatMessage` is `true`, it triggers a chat message event for the player using `TriggerClientEvent`. This message informs other players that the player with the `pSource` identifier has activated their panic button.
   * If `Config.PlayPanicSound` is `true`, it triggers an audio event for the player to play a sound named 'Panic' using `TriggerClientEvent`.
6. After performing these actions, the code reaches the `::skip::` label and proceeds to the next player in the loop.

In summary, this function is designed to handle a panic button feature. It checks if players are on duty, have the necessary permissions, and then sends chat messages and plays sounds for those players who meet the criteria specified in the configuration (`Config`). Players who are not on duty or do not have the required permissions are skipped. The `goto` statement is used here to control the flow and skip players who don't meet the conditions.
