#pragma semicolon 1 #define PLUGIN_AUTHOR "jenz" #define PLUGIN_VERSION "1.0" #include #include //https://github.com/Mikusch/SM-TickrateChanger/tree/main public Plugin myinfo = { name = "tickrate_command_caller", author = PLUGIN_AUTHOR, description = "set tickrate based on what nextmap is", version = PLUGIN_VERSION, url = "www.unloze.com" }; Handle hChangeLevel; char map_intended_switch[256]; //---------------------------------------------------------------------------------------------------- // Purpose: //---------------------------------------------------------------------------------------------------- public void OnPluginStart() { Handle conf = LoadGameConfigFile("force_change_level.games"); if (conf == INVALID_HANDLE) SetFailState("Failed to load gamedata force_change_level.games"); //thanks Irineu hChangeLevel = DHookCreateDetour(Address_Null, CallConv_CDECL, ReturnType_Bool, ThisPointer_Ignore); if (!hChangeLevel) SetFailState("Failed to setup detour "); if (!DHookSetFromConf(hChangeLevel, conf, SDKConf_Signature, "Host_Changelevel")) SetFailState("Failed to load signature from gamedata"); DHookAddParam(hChangeLevel, HookParamType_Bool); DHookAddParam(hChangeLevel, HookParamType_CharPtr); DHookAddParam(hChangeLevel, HookParamType_CharPtr); if (!DHookEnableDetour(hChangeLevel, false, ChangeLevel)) SetFailState("Failed to detour "); delete conf; } //thanks Irineu public MRESReturn ChangeLevel(DHookReturn hReturn, DHookParam hParams) { char cmd[256]; Address addr_map_name = DHookGetParamAddress(hParams, 2); for (int i = 0; i < sizeof(cmd) - 1; i++) { int iByte = LoadFromAddress(addr_map_name + view_as
(i), NumberType_Int8); if (iByte < 32 || iByte > 126) //ascii range of legal characters we are interested in { break; } cmd[i] = iByte; } //LogMessage("cmd: %s", cmd); check_map(cmd); return MRES_Ignored; } public void check_map(const char []map) { new Handle:fileHandle = OpenFile("maps_66_tick.txt", "r" ); char lineBuffer[256]; bool changeTick = false; while(!IsEndOfFile(fileHandle) && ReadFileLine(fileHandle, lineBuffer, sizeof(lineBuffer))) { TrimString(lineBuffer); if (StrEqual(map, lineBuffer, false)) { changeTick = true; break; } } CloseHandle(fileHandle); float interveral_per_tick_pre = GetConVarFloat(FindConVar("sm_interval_per_tick")); bool double_map_change = false; if (changeTick) { ServerCommand("sm_tickrate 66"); //are we at 100 tick and change to 66 right now? do a quick change map restart. double_map_change = interveral_per_tick_pre < 0.014; } else { ServerCommand("sm_tickrate 100"); //are we at 66 tick and change to 100 right now? do a quick change map restart. double_map_change = interveral_per_tick_pre > 0.011; } if (double_map_change) { Format(map_intended_switch, sizeof(map_intended_switch), map); CreateTimer(10.0, restart_map); } } public Action restart_map(Handle timer, any data) { ForceChangeLevel(map_intended_switch, "switching tickrate, applied double map change which was needed to fix entities."); return Plugin_Continue; }