#pragma semicolon 1
#pragma newdecls required

#include <sdktools_engine>
#include <sdktools_functions>
#include <sdktools_trace>
#include <vip_core>

static const char FEATURE[] = "AimTeleport";

int
	m_CollisionGroup,
	iUsesNum[MAXPLAYERS+1];

public Plugin myinfo =
{
	name	= "[VIP] AIM Teleport",
	version	= "1.0.1",
	author	= "Grey83",
	url		= "https://steamcommunity.com/groups/grey83ds"
}

public void OnPluginStart()
{
	m_CollisionGroup = FindSendPropInfo("CBaseEntity", "m_CollisionGroup");

	HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);

	RegConsoleCmd("tele", Cmd_Tele2A);

	LoadTranslations("vip_modules.phrases");
	LoadTranslations("vip_core.phrases");

	if(VIP_IsVIPLoaded()) VIP_OnVIPLoaded();
}

public void OnPluginEnd()
{
	if(CanTestFeatures() && GetFeatureStatus(FeatureType_Native, "VIP_UnregisterFeature") == FeatureStatus_Available
	&& VIP_IsValidFeature(FEATURE))
		VIP_UnregisterFeature(FEATURE);
}

public void VIP_OnVIPLoaded()
{
	if(!VIP_IsValidFeature(FEATURE)) VIP_RegisterFeature(FEATURE, INT, SELECTABLE, OnSelectItem, OnDisplayItem, OnDrawItem);
	else SetFailState("Feature '%s' already in use", FEATURE);
}

public bool OnSelectItem(int client, const char[] sFeatureName)
{
	TeleportClient(client);
	return true;
}

public bool OnDisplayItem(int client, const char[] sFeatureName, char[] sDisplay, int maxlen)
{
	if(VIP_GetClientFeatureStatus(client, sFeatureName) != ENABLED) return false;

	int max_uses = VIP_GetClientFeatureInt(client, FEATURE);
	if(max_uses) FormatEx(sDisplay, maxlen, "%T [%T]", sFeatureName, client, "Left", client, max_uses - iUsesNum[client]);
	else FormatEx(sDisplay, maxlen, "%T", sFeatureName, client);
	return true;
}

public int OnDrawItem(int client, const char[] sFeatureName, int iStyle)
{
	if(VIP_GetClientFeatureStatus(client, sFeatureName) == NO_ACCESS || !VIP_GetClientFeatureInt(client, FEATURE))
		return ITEMDRAW_DISABLED;

	return iStyle;
}

public Action Cmd_Tele2A(int client, int args)
{
	if(client)
	{
		if(VIP_IsClientVIP(client) && VIP_IsClientFeatureUse(client, FEATURE))
			TeleportClient(client);
		else VIP_PrintToChatClient(client, "%T", "COMMAND_NO_ACCESS", client);
	}
	return Plugin_Handled;
}

public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast)
{
	for(int i = 1; i <= MaxClients; i++) iUsesNum[i] = 0;
}

public void OnClientPutInServer(int client)
{
	iUsesNum[client] = 0;
}

stock void TeleportClient(int client)
{
	if(!IsPlayerAlive(client))
	{
		VIP_PrintToChatClient(client, "Вы должны быть живы!");
		return;
	}

	if(GetClientTeam(client) < 2)
	{
		VIP_PrintToChatClient(client, "Вы должны быть в команде!");
		return;
	}

	if(iUsesNum[client] >= VIP_GetClientFeatureInt(client, FEATURE))
	{
		PrintToChat(client, "%tДостигнут лимит использований за раунд!", "VIP_CHAT_PREFIX");
		return;
	}

	static float ang[3], pos[3], vec[3], start[3];
	GetClientEyePosition(client, pos);
	GetClientEyeAngles(client, ang);

	Handle trace = TR_TraceRayFilterEx(pos, ang, MASK_SHOT, RayType_Infinite, TraceEntityFilterPlayer);
	if(TR_DidHit(trace))
	{
		TR_GetEndPosition(start, trace);

		GetVectorDistance(pos, start, false);
		GetAngleVectors(ang, vec, NULL_VECTOR, NULL_VECTOR);
		start[0] -= 35 * vec[0];
		start[1] -= 35 * vec[1];
		start[2] -= 35 * vec[2];

		GetClientAbsOrigin(client, pos);

		TeleportEntity(client, start, NULL_VECTOR, NULL_VECTOR);

		GetClientMins(client, vec);
		GetClientMaxs(client, ang);
		TR_TraceHullFilter(start, start, vec, ang, MASK_PLAYERSOLID, TraceEntityFilterPlayer, client);
		if(TR_DidHit())
		{
			CloseHandle(trace);
			TeleportEntity(client, pos, NULL_VECTOR, NULL_VECTOR);
			return;
		}

		if(m_CollisionGroup > 0)
		{
			SetEntData(client, m_CollisionGroup, 17, _, true);
			CreateTimer(3.0, OffNoBlockPlayer, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
		}
		iUsesNum[client]++;
	}
	CloseHandle(trace);
}

public Action OffNoBlockPlayer(Handle timer, int client)
{
	if((client = GetClientOfUserId(client)) && IsPlayerAlive(client)) SetEntData(client, m_CollisionGroup, 5, _, true);
}

public bool TraceEntityFilterPlayer(int entity, int contentsMask)
{
	return entity > MaxClients || !entity;
}