#pragma semicolon 1
#define PLUGIN_AUTHOR "jenz"
#define PLUGIN_VERSION "1.0"

#include <sourcemod>
#include <dhooks>

//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<Address>(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;
}
