
// plugin events
public OnPluginStart()
{
	PrintToConsole(0, "[SM] Decapination loaded.");
	
	CreateConVar("sm_decap_version", PLUGIN_VERSION, "DecapiNation Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);

	cvSpurtInterval = CreateConVar("sm_decapspurtinterval", "0.8", "time in seconds between neck blood spurts");
	cvBloodLoss = CreateConVar("sm_decap_bloodloss", "1", "health lost for each blood spurt");
	cvAimTolerance = CreateConVar("sm_decap_aimtolerance", "10", "tolerance factor for replacing heads");
	cvCheckInterval = CreateConVar("sm_decap_checkinterval", "1.0", "time in seconds between check head/body positions for re-animation");

	cvDecapHeadshot = CreateConVar("sm_decap_headshot", "1", "decapination on headshot");
	cvDecapKnife = CreateConVar("sm_decap_knife", "1", "decapination on knifing");
	cvDecapHE = CreateConVar("sm_decap_he", "1", "decapination on grenade");
	
	cvTKEnabled = CreateConVar("sm_decap_tkenabled", "1", "can decapinate own team");

	cvSpeed = CreateConVar("sm_decap_grabber_speed", "10.0", "speed at which grabbed object will move with player");
	cvDistance = CreateConVar("sm_decap_grabber_distance", "64.0", "distance at which grabbed object will hover in front of player");
	cvThrowTime = CreateConVar("sm_decap_grabber_throwtime", "2.0", "time to charge up to full throw speed");
	cvThrowSpeed = CreateConVar("sm_decap_grabber_throwspeed", "1000.0", "speed at which an object is thrown");
	cvMaxDistance = CreateConVar("sm_decap_grabber_maxdistance", "512.0", "maximum distance from which you can grab an object");
	cvSteal = CreateConVar("sm_decap_grabber_steal", "1", "can objects be 'stolen' from other players (0=no 1=yes)");
	cvDropOnJump = CreateConVar("sm_decap_grabber_droponjump", "1", "drop objects when jumping (prevents player from flying around level on large objects) (0=no 1=yes)");

	HookEvent("player_hurt", EventPlayerHurt, EventHookMode_Pre);
	HookEvent("round_start", EventRoundStart);
	//HookEvent("round_end", EventRoundEnd);
	HookEvent("player_death", EventDeath);
	HookEvent("player_spawn", EventSpawn);
	HookEvent("player_team", EventSpawn);
	
	RegConsoleCmd("+dcgrab", Command_Grab);
	RegConsoleCmd("-dcgrab", Command_UnGrab2);
	RegConsoleCmd("+dcthrow", Command_Throw);
	RegConsoleCmd("-dcthrow", Command_UnThrow);
}

public OnEventShutdown()
{
	UnhookEvent("player_hurt", EventPlayerHurt, EventHookMode_Pre);
	UnhookEvent("round_start", EventRoundStart);
	UnhookEvent("player_death", EventDeath, EventHookMode_Pre);
	UnhookEvent("player_spawn",EventSpawn);
	UnhookEvent("player_team",EventTeam);
	
	UnhookEntityOutput("trigger_multiple","OnStartTouch",OnStartTouch);
}

public OnMapStart()
{
	//open precache file and add everything to download table
	new String:modelfile[256];
	BuildPath(Path_SM, modelfile, 255, "configs/dc_assetconfig.ini");
	new Handle:fileh = OpenFile(modelfile, "r");
	new String:buffer[256];
	while (ReadFileLine(fileh, buffer, sizeof(buffer)))
	{
		new len = strlen(buffer);
		if (buffer[len-1] == '\n')
   			buffer[--len] = '\0';
   			
		if (FileExists(buffer))
		{
			AddFileToDownloadsTable(buffer);
		}
		
		if (IsEndOfFile(fileh))
			break;
	}
	CloseHandle(fileh);
	
	// get chippy from file if it exists
	new String:mapconfigfile[256];
	BuildPath(Path_SM, mapconfigfile, 255, "configs/dc_mapconfig.ini");
	
	new String:mapname[256];
	GetCurrentMap(mapname, sizeof(mapname));
	
	// load kv file
	new Handle:kv = CreateKeyValues("maplocations");
	if (FileToKeyValues(kv, mapconfigfile))
	{
		if (!KvJumpToKey(kv, mapname))
		{
			g_ChippyEnabled = false;
		}
		else
		{
			g_ChippyEnabled = true;
			KvGetVector(kv,"origin",g_ChippyOrigin);
			KvGetVector(kv,"angles",g_ChippyAngles);
		}
	}
	else
		g_ChippyEnabled = false;

	CloseHandle(kv);

	// models
	PrecacheModel("models/player/ct_gign1_dc.mdl",true);
	PrecacheModel("models/player/ct_gsg91_dc.mdl",true);
	PrecacheModel("models/player/ct_sas1_dc.mdl",true);
	PrecacheModel("models/player/ct_urban1_dc.mdl",true);

	PrecacheModel("models/player/t_arctic1_dc.mdl",true);
	PrecacheModel("models/player/t_guerilla1_dc.mdl",true);
	PrecacheModel("models/player/t_leet1_dc.mdl",true);
	PrecacheModel("models/player/t_phoenix1_dc.mdl",true);

	PrecacheModel("models/player/ct_gign_head.mdl",true);
	PrecacheModel("models/player/ct_gsg9_head.mdl",true);
	PrecacheModel("models/player/ct_sas_head.mdl",true);
	PrecacheModel("models/player/ct_urban_head.mdl",true);
	PrecacheModel("models/player/t_arctic_head.mdl",true);
	PrecacheModel("models/player/t_guerilla_head.mdl",true);
	PrecacheModel("models/player/t_leet_head.mdl",true);
	PrecacheModel("models/player/t_phoenix_head.mdl",true);
	
	PrecacheModel("models/decapination/dc_chippy.mdl",true);
	PrecacheModel("models/props/de_train/utility_truck_windows.mdl",true);
	
	// sounds
	PrecacheSound(g_SpurtSound, true);
	PrecacheSound(g_HoldSound, true);
	
	PrecacheSound(g_ChippyIdleSound, true);
	PrecacheSound(g_ChippyGrind1Sound, true);
	PrecacheSound(g_ChippyGrind2Sound, true);
	PrecacheSound(g_ChippyGrind3Sound, true);
	PrecacheSound(g_ChippyFleshySound, true);
	PrecacheSound(g_ChippySquishy1Sound, true);
	PrecacheSound(g_ChippySquishy2Sound, true);
	PrecacheSound(g_ChippySquishy3Sound, true);
	PrecacheSound(g_ChippySquishy4Sound, true);
	PrecacheSound(g_ChippyReject1Sound, true);
	PrecacheSound(g_ChippyReject2Sound, true);
	PrecacheSound(g_ChippyReject3Sound, true);
	PrecacheSound(g_ChippyReject4Sound, true);
	PrecacheSound(g_ChippyReject5Sound, true);
	PrecacheSound(g_AchievementSound, true);

	// particles
	ForcePrecache("blood_advisor_pierce_spray");
	ForcePrecache("blood_advisor_pierce_spray_b");
	ForcePrecache("blood_advisor_pierce_spray_c");	
	ForcePrecache("blood_advisor_puncture");
	ForcePrecache("blood_advisor_puncture_withdraw");
	ForcePrecache("blood_antlionguard_injured_heavy_tiny");
	ForcePrecache("blood_impact_red_01");
	ForcePrecache("blood_impact_red_01_droplets");
	ForcePrecache("blood_impact_red_01_goop");
	ForcePrecache("blood_impact_red_01_mist");
	ForcePrecache("blood_impact_red_01_smalldroplets");
	ForcePrecache("blood_zombie_split_spray");
	ForcePrecache("blood_zombie_split_spray_tiny");
	ForcePrecache("blood_zombie_split_spray_tiny2");
	ForcePrecache("smoke_gib_01");
	
	// reset object list
	for (new i=0; i<=MaxClients; i++)
	{
		ResetPlayer(i);
	}
	
	// start update timers
	new Float:checkinterval = GetConVarFloat(cvCheckInterval);
	
	CreateTimer(0.1, UpdateObjects, INVALID_HANDLE, TIMER_REPEAT);
	CreateTimer((checkinterval), CheckPosTimer, _, TIMER_REPEAT);
}

public ForcePrecache(String:ParticleName[])
{
	decl Particle;
	
	Particle = CreateEntityByName("info_particle_system");
	
	if(IsValidEdict(Particle))
	{
		DispatchKeyValue(Particle, "effect_name", ParticleName);
		
		DispatchSpawn(Particle);
		ActivateEntity(Particle);
		AcceptEntityInput(Particle, "start");
		
		CreateTimer(0.3, DeleteParticle, Particle, TIMER_FLAG_NO_MAPCHANGE);
	}
}

public OnMapEnd()
{
}

public OnClientPutInServer(client)
{
	ResetPlayer(client);
}

public OnClientDisconnect(client)
{
	if((g_HeadEnt[client]) && (IsValidEntity(g_HeadEnt[client])))
	{
		RemoveEdict(g_HeadEnt[client]);
	}
	
	if (g_SpurtTimer[client] != INVALID_HANDLE)
	{
		KillTimer(g_SpurtTimer[client]);
		g_SpurtTimer[client] = INVALID_HANDLE;
	}
	
	ResetPlayer(client);
}

public Action:EventRoundStart(Handle:Event, const String:Name[], bool:Broadcast)
{
	for (new client = 1; client <= MaxClients; client++)
	{
		if (IsClientConnected(client) && IsClientInGame(client))
		{
			ResetView(client);
		}
	}
	
	if (g_ChippyEnabled)
		SpawnChippy();
	
	return Plugin_Continue;
}
