├── .vscode └── tasks.json ├── README.md └── scripting ├── fps-threshold.sp └── include └── fps-threshold.inc /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "options": 4 | { 5 | "env": 6 | { 7 | "sm_path": "/home/dev/GFL/SourceMod/scripting", 8 | "server_path": "/home/roy/css/cstrike" 9 | } 10 | }, 11 | "tasks": 12 | [ 13 | { 14 | "label": "sourcepawn", 15 | "type": "shell", 16 | "command": "$sm_path/spcomp64 ${file} -D ${workspaceFolder} -i ${workspaceFolder}/scripting/include && sudo cp -f ${workspaceFolder}/${fileBasenameNoExtension}.smx ${server_path}/addons/sourcemod/plugins", 17 | "problemMatcher": [] 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FPS Threshold 2 | ## Description 3 | A simple SourceMod plugin that calculates the server FPS every second and when it goes under a certain threshold based off of the average FPS in *x* seconds, offers a forward on detection, 4 | 5 | I've made this in hopes to mitigate damage on [Elite Hunterz](https://forum.elite-hunterz.com/)'s Zombie Hunting server from poor performance issues when multiple players are stuck inside of each other. 6 | 7 | ## ConVars 8 | * **sm_fpsth_avgtime** - Calculate the average FPS for *x* seconds (*x* representing the CVar value). 9 | * **sm_fpsth_threshold** - If the average FPS goes below this average, call `FPSTH_OnDetect()` forward. 10 | 11 | ## Forwards 12 | This plugin comes with one forward to allow other plugins to interact. The forward may be found below. 13 | 14 | ```C 15 | /** 16 | * Called when the server is caught going under the average FPS threshold. 17 | * 18 | * @param avgfps The average FPS detected. 19 | * @param curfps The current FPS detected. 20 | * 21 | * @return void 22 | */ 23 | forward void FPSTH_OnDetect(float avgfps, int curfps); 24 | ``` 25 | 26 | ## Useful Plugins 27 | * [Force Noblock](https://github.com/gamemann/FPS-Threshold-Noblock) - Forces Noblock on all players when average FPS goes under threshold. 28 | 29 | ## Credits 30 | * [Christian Deacon](https://github.com/gamemann) -------------------------------------------------------------------------------- /scripting/fps-threshold.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXSTORE 256 5 | 6 | public Plugin myinfo = 7 | { 8 | name = "FPS Threshold", 9 | author = "Roy (Christian Deacon)", 10 | description = "A plugin that offers forwards for other plugins after average FPS goes under a certain threshold.", 11 | version = "1.0.0", 12 | url = "https://github.com/gamemann" 13 | }; 14 | 15 | float g_lastfps = 67.00; 16 | int g_lasttick = 0; 17 | int g_index = 0; 18 | float g_fpsarr[MAXSTORE]; 19 | int g_framecount = 0; 20 | 21 | float last_time = 0.0; 22 | 23 | bool g_uptospeed = false; 24 | 25 | ConVar g_cvMaxStore = null; 26 | ConVar g_cvThreshold = null; 27 | 28 | GlobalForward g_fwdOnDetect; 29 | 30 | public void OnPluginStart() 31 | { 32 | g_cvMaxStore = CreateConVar("sm_fpsth_avgtime", "6", "How long ago should we calculate the FPS average from"); 33 | g_cvThreshold = CreateConVar("sm_fpsth_threshold", "3", "If the average server FPS goes below this, start FPSTH_OnDetect() forward for all associated plugins."); 34 | 35 | g_fwdOnDetect = CreateGlobalForward("FPSTH_OnDetect", ET_Event, Param_Float, Param_Cell); 36 | 37 | RegAdminCmd("sm_fps", Command_FPS, ADMFLAG_SLAY); 38 | 39 | AutoExecConfig(true, "plugin.fpsth"); 40 | } 41 | 42 | public Action Command_FPS(int client, int args) 43 | { 44 | ReplyToCommand(client, "Latest FPS => %.6f", g_lastfps); 45 | 46 | return Plugin_Handled; 47 | } 48 | 49 | public void OnGameFrame() 50 | { 51 | // Always increase frame count. 52 | g_framecount++; 53 | 54 | // Get engine time and compare against last time. 55 | float current_time = GetEngineTime(); 56 | float time = current_time - last_time; 57 | 58 | // Check to see if we exceed a second. 59 | if (time >= 1) 60 | { 61 | last_time = current_time; 62 | 63 | float fps = float(g_framecount); 64 | g_lastfps = fps; 65 | 66 | // Reset frame count to 0. 67 | g_framecount = 0; 68 | 69 | // Reset g_indexlasttick if it exceeds g_cvMaxStore value. 70 | if (g_index > (g_cvMaxStore.IntValue - 1)) 71 | { 72 | g_uptospeed = true; 73 | g_index = 0; 74 | } 75 | 76 | g_fpsarr[g_index] = fps; 77 | 78 | if (g_uptospeed) 79 | { 80 | // Calculate average FPS. 81 | float avg; 82 | int j = g_index; 83 | 84 | for (int i = 0; i < g_cvMaxStore.IntValue; i++) 85 | { 86 | if (j < 0) 87 | { 88 | j = (g_cvMaxStore.IntValue - 1); 89 | } 90 | 91 | avg += g_fpsarr[j]; 92 | 93 | j--; 94 | } 95 | 96 | avg /= g_cvMaxStore.FloatValue; 97 | 98 | if (avg <= 0) 99 | { 100 | return; 101 | } 102 | 103 | if (avg < g_cvThreshold.FloatValue) 104 | { 105 | // Call On Detection forward. 106 | Call_StartForward(g_fwdOnDetect); 107 | Call_PushFloat(avg); 108 | Call_PushCell(fps); 109 | Call_Finish(); 110 | } 111 | } 112 | 113 | // Increase index. 114 | g_index++; 115 | } 116 | } -------------------------------------------------------------------------------- /scripting/include/fps-threshold.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * Called when the server is caught going under the average FPS threshold. 3 | * 4 | * @param avgfps The average FPS detected. 5 | * @param curfps The current FPS detected. 6 | * 7 | * @return void 8 | */ 9 | forward void FPSTH_OnDetect(float avgfps, int fps); --------------------------------------------------------------------------------