#pragma semicolon 1

#define PLUGIN_AUTHOR "TRANSLUCENT"
#define PLUGIN_VERSION "0.62wtf"
#define MAXLENGTH_MESSAGE 256

#define STARTZONE 0
#define ENDZONE 1

#define FRAMEINTERVAL 330
#define REPLAYS_PATH "data/ctimer" // Path to where replays are stored
#define BACKUP_REPLAYS
#define MAXVELOCITY 280.0
#define MAX_DIST 1536.0
#define MAX_DIST_SQ MAX_DIST * MAX_DIST

#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <cstrike>
#include <PlayerManager>

/* Global variables */
enum
{
    RUNDATA_POSITION_X, 
	RUNDATA_POSITION_Y, 
	RUNDATA_POSITION_Z, 
	RUNDATA_PITCH, 
	RUNDATA_YAW, 
	RUNDATA_BUTTONS, 
	RUNDATA_IMPULSE, 
	RUNDATA_WEAPONID, 
	RUNDATA_MAX
}

///TIMER HANDLES
Handle g_hDrawFullZone = INVALID_HANDLE;
Handle g_hDrawZone = INVALID_HANDLE;
Handle g_hHudLoop = INVALID_HANDLE;
Handle g_hSideHudLoop = INVALID_HANDLE;

///DATABASE
Database g_hDatabase = null;

///PLAYERS
float g_fMapTime[MAXPLAYERS + 1];
float g_fStartTime[MAXPLAYERS + 1];
int g_iActivity[MAXPLAYERS + 1] = -1; //-1 - Inactive, 0 - Running, 1 - StartZone, 2 - EndZone

///BOTS AND RECORDING
//ArrayList g_arrayGhost;
ArrayList g_arrayRun[MAXPLAYERS + 1]; //Record array
//char g_sGhostNames[MAX_NAME_LENGTH];
//int g_iGhost = -1;
//int g_iGhostFrame = -1;
//int g_fGhostVel = -1;
float g_fTickrate;

///ZONEMAP INFO
int g_iSnapToClient = -1;
bool g_bEditorComesFromMenu;
float g_fStartOrigins[2][3];
float g_fEndOrigins[2][3];
int g_iEditor = -1;
int g_iTriggerEnt[2] = -1;

///MAP INFO
bool g_bActive = false;
int g_iTier = 1;
int g_iMapID = -1;
float g_fWrTime = -1.0;
char g_sMapName[64];
char g_sWrHolder[MAX_NAME_LENGTH];

///OTHERS
bool g_bLateLoad = false;
int g_iBeam;
ConVar g_hCvarLasers = null;
bool g_bLasers = false;

// Offsets (netprops)
int m_vecOrigin; // CBaseEntity::m_vecOrigin
int m_hActiveWeapon; // CBaseCombatCharacter::m_hActiveWeapon

public Plugin myinfo = 
{
	name = "Under Average Timer",
	author = PLUGIN_AUTHOR,
	description = "",
	version = PLUGIN_VERSION,
	url = ""
};

public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
	CreateNative("CTimer_Stop", Native_StopTime);

	RegPluginLibrary("ctimer");
	
	g_bLateLoad = late;
	return APLRes_Success;
}

public void OnPluginStart()
{
	LoadTranslations("ctimer.phrases");
	
	HookEvent("round_start", Event_RoundStart);
	HookEvent("player_death", Event_PlayerDeath);

	RegAdminCmd("sm_timeradmin", Command_TimerAdmin, ADMFLAG_CHEATS, "Your one stop for timer management");
	RegAdminCmd("sm_zones", Command_Zones, ADMFLAG_CHEATS, "Create zones");
	
	RegConsoleCmd("sm_stop", Command_Stop, "Stops your timer");
	RegConsoleCmd("sm_time", Command_Time, "Get a players time");
	RegConsoleCmd("sm_top", Command_Top, "Get a maps top times");
	RegConsoleCmd("sm_wr", Command_WR, "Get a maps best time");
	
	RegAdminCmd("sm_origins", Command_Origins, ADMFLAG_CHEATS);
	
	g_hCvarLasers = CreateConVar("ctimer_zone_lazers", "1", "Lazors", FCVAR_NONE, true, 0.0, true, 1.0);
	
	if(g_hCvarLasers != null)
	{
		g_hCvarLasers.AddChangeHook(OnLazorsChange);
	}
	
	g_hDrawFullZone = CreateTimer(0.2, DrawFullZoneTimer, INVALID_HANDLE, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
	g_hDrawZone = CreateTimer(1.0, DrawZoneTimer, INVALID_HANDLE, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
	g_hHudLoop = CreateTimer(0.2, HudLoop, INVALID_HANDLE, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
	g_hSideHudLoop = CreateTimer(1.0, SideHudLoop, INVALID_HANDLE, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
	
	for (new i = 1; i <= MaxClients; i++)
	{
		g_arrayRun[i] = new ArrayList(RUNDATA_MAX);
	}
	
	m_vecOrigin = FindSendPropInfo("CBaseEntity", "m_vecOrigin");
	
	if (m_vecOrigin == -1)
	{
		SetFailState("Couldn't find CBaseEntity::m_vecOrigin");
	}
	if (m_vecOrigin == 0)
	{
		SetFailState("No offset available for CBaseEntity::m_vecOrigin");
	}
	
	m_hActiveWeapon = FindSendPropInfo("CBaseCombatCharacter", "m_hActiveWeapon");
	
	if (m_hActiveWeapon == -1)
	{
		SetFailState("Couldn't find CBaseCombatCharacter::m_hActiveWeapon");
	}
	if (m_hActiveWeapon == 0)
	{
		SetFailState("No offset available for CBaseCombatCharacter::m_hActiveWeapon");
	}
	
	//g_arrayGhost = new ArrayList(9, 0);
	
	g_fTickrate = (1.0 / GetTickInterval());
	
	EstablishConnection();
}

#include "ctimer/actions.sp"
#include "ctimer/bots.sp"
#include "ctimer/commands.sp"
#include "ctimer/menus.sp"
#include "ctimer/timers.sp"
#include "ctimer/utility.sp"
#include "ctimer/sql.sp"
#include "ctimer/zones.sp"

public Action Command_Origins(int client, int args)
{
	PrintToChatAll("Start: %f|%f|%f %f|%f|%f", g_fStartOrigins[0][0], g_fStartOrigins[0][1], g_fStartOrigins[0][2], g_fEndOrigins[0][0], g_fEndOrigins[0][1], g_fEndOrigins[0][2]);
	PrintToChatAll("End: %f|%f|%f %f|%f|%f", g_fStartOrigins[1][0], g_fStartOrigins[1][1], g_fStartOrigins[1][2], g_fEndOrigins[1][0], g_fEndOrigins[1][1], g_fEndOrigins[1][2]);
	PrintToChatAll("MapID: %i", g_iMapID);
	PrintToChatAll("Active: %s", g_bActive ? "active":"inactive");
	PrintToChatAll("Tier: %i", g_iTier);
	PrintToChatAll("Wr: %.2f, %s", g_fWrTime, g_sWrHolder);
	PrintToChatAll("Speccount: %i", GetSpecCount(client));
	return Plugin_Handled;
}