#include <amxmodx>
#include <fakemeta>

#define SAVETIME_MIN 0.5
#define SAVETIME_MAX 3.0
#define LOADTIME 2.5
#define MAXWEAPONS 30
#define SKINSPERWEAPONS 5
#define POINTSLEN 6

#pragma semicolon 1

new const PLUGIN[] = "Skin System";
new const VERSION[] = "2.1";
new const AUTHOR[] = "DeRoiD";

new KillPoints[31][33], Skin[31][SKINSPERWEAPONS],
vSkinMdl[31][SKINSPERWEAPONS][64], pSkinMdl[31][SKINSPERWEAPONS][64],
SkinName[31][SKINSPERWEAPONS][32], Already[31];
new PointsFile[64];
new SkinsFile[64];

new const WeaponNames[][] =
{
	"", "P228", "Shield", "Scout", "He Grenade", "XM1014", "C4", "MAC10", "AUG",
	"Smoke Grenade", "Elite", "Five-Seven", "UMP45", "SG550", "Galil", "FAMAS",
	"USP", "Glock18", "AWP", "MP5", "M249", "M3", "M4A1", "TMP", "G3SG1",
	"Flashbang", "Deagle", "SG552", "AK47", "Knife", "P90"
};

public plugin_init()
{
	register_dictionary("skinsystem.txt");
	
	register_plugin(PLUGIN, VERSION, AUTHOR);
	register_cvar(PLUGIN, AUTHOR, FCVAR_SERVER);
	
	register_clcmd("say", "Say");
	register_clcmd("say_team", "Say");
	
	register_event("CurWeapon","WeaponModel","be","1=1");
	
	set_task(random_float(100.0, 200.0), "Adv", 0, _, _, "b");
	
	LoadSkins();
	
	register_forward(FM_ClientUserInfoChanged, "NameChange");
}
public NameChange(Player) 
{
	if(!is_user_connected(Player))
		return FMRES_IGNORED;

	new OldName[32], NewName[32], Name[32];
	get_user_name(Player, Name, 31);
	pev(Player, pev_netname, OldName, charsmax(OldName));
	if(OldName[0])
	{
		get_user_info(Player, "name", NewName, charsmax(NewName));
		if(!equal(OldName, NewName))
		{
			remove_task(Player);
			for(new Num = 1; Num < MAXWEAPONS+1; Num++)
			{
				KillPoints[Num][Player] = 0;
			}
			set_task(0.1, "LoadPoints", Player);
		}
	}
	return FMRES_IGNORED;
}
public Adv()
{
	client_print(0, print_chat, "%L", LANG_SERVER, "ADV", PLUGIN, VERSION, AUTHOR);
}
public WeaponModel(Player) {
	new Weapon = get_user_weapon(Player);
 
	if(!is_user_alive(Player) || !is_user_connected(Player))
	{
		return PLUGIN_HANDLED;
	}
	
	for(new Num = 1; Num < MAXWEAPONS; Num++)
	{
		if(Num == Weapon)
		{
			for(new x; x < SKINSPERWEAPONS; x++)
			{
				if(KillPoints[Weapon][Player] >= Skin[Weapon][x])
				{
					if(strlen(vSkinMdl[Weapon][x]) > 5)
					set_pev(Player, pev_viewmodel2, vSkinMdl[Weapon][x]);
					if(strlen(pSkinMdl[Weapon][x]) > 5)
					set_pev(Player, pev_weaponmodel2, pSkinMdl[Weapon][x]);
				}
			}
		}
	}
	return PLUGIN_CONTINUE;
}
public plugin_precache() {
	static ConfigsDir[64]; 
	get_localinfo("amxx_configsdir", ConfigsDir, 63);
	formatex(PointsFile, 63, "%s/skinsystem/save.ini", ConfigsDir);
	formatex(SkinsFile, 63, "%s/skinsystem/skins.cfg", ConfigsDir);
	
	new Len, Line[256], Data[3][48], FileLine;
	FileLine = file_size(SkinsFile, 1);
	for(new Num = 0; Num < FileLine; Num++)
	{
		read_file(SkinsFile, Num, Line, 255, Len);
		parse(Line, Data[0], 31, Data[1], 47, Data[2], 47);
		
		if(Line[0] == ';' || strlen(Line) < 5)
			continue;

		remove_quotes(Data[1]);
		remove_quotes(Data[2]);
		
		if(strlen(Data[1]) > 5)
		precache_model(Data[1]);
		if(strlen(Data[2]) > 5)
		precache_model(Data[2]);
	}
}
public client_death(Killer, Victim, Weapon)
{
	if(Killer == Victim
	|| Killer > 32 || Killer < 1
	|| Weapon == 25 || Weapon == 9
	|| Weapon < 1 || Weapon > 30)
	{
		return PLUGIN_HANDLED;
	}
	
	set_task(random_float(SAVETIME_MIN, SAVETIME_MAX), "SavePoints", Killer);
	KillPoints[Weapon][Killer]++;
	return PLUGIN_CONTINUE;
}
public LoadSkins()
{
	new File;
	File = fopen(SkinsFile, "rt");
	
	if(File)
	{
		new Line[256], Type[32], Data[5][64];
		while(!feof(File))
		{
			fgets(File, Line, 255);
			
			if(Line[0] == ';' || strlen(Line) < 5)
				continue;
				
			parse(Line, Type, 31);
			
			for(new Num = 1; Num < MAXWEAPONS+1; Num++)
			{
				if(Already[Num] >= SKINSPERWEAPONS)
				continue;
				
				if(equali(Type, WeaponNames[Num]))
				{
					parse(Line, Data[0], 63, Data[1], 63, Data[2], 63, Data[3], 63, Data[4], 63);
					copy(vSkinMdl[Num][Already[Num]], 63, Data[1]);
					copy(pSkinMdl[Num][Already[Num]], 63, Data[2]);
					copy(SkinName[Num][Already[Num]], 31, Data[4]);
					Skin[Num][Already[Num]] = str_to_num(Data[3]);
					Already[Num]++;
				}
			}
		}
		fclose(File);
	}
}
public ShowSkins(Player, i)
{
	new MotdTitle[64];
	formatex(MotdTitle, 63, "%L", LANG_SERVER, "MOTD1");
	
	new Motd[1024], Line[256];
	formatex(Line, 255, "<body bgcolor=^"black^">^n<font color=^"red^">^n");
	add(Motd, 1023, Line, 255);
	formatex(Line, 255, "<p align=^"center^">%s %s by: %s</p></font>^n<font color=^"greenyellow^">^n", PLUGIN, VERSION, AUTHOR);
	add(Motd, 1023, Line, 255);
	formatex(Line, 255, "<p align=^"center^">%L:</p></font>^n", LANG_SERVER, "SKINS", WeaponNames[i]);
	add(Motd, 1023, Line, 255);
	formatex(Line, 255, "<h5>^n<font color=^"white^">^n");
	add(Motd, 1023, Line, 255);
	
	for(new Num; Num < MAXWEAPONS; Num++)
	{
		if(Num != i)
		continue;
		formatex(Line, 255, "<p>");
		add(Motd, 1023, Line, 255);
		for(new x; x < SKINSPERWEAPONS; x++)
		{
			if(strlen(SkinName[Num][x]) < 3)
			continue;
			
			formatex(Line, 255, "<br>%s: (%L)", SkinName[Num][x], LANG_SERVER, "KILLS", Skin[Num][x]);
			add(Motd, 1023, Line, 255);
		}
		formatex(Line, 255, "</p>");
		add(Motd, 1023, Line, 255);
	}
	formatex(Line, 255, "^n</h5>^n</font>^n</body>");
	add(Motd, 1023, Line, 255);
	show_motd(Player, Motd, MotdTitle);
}
public ShowPoints(Player, Target)
{
	new Name[32], MotdTitle[64];
	get_user_name(Target, Name, 31);
	
	formatex(MotdTitle, 63, "%L", LANG_SERVER, "PKILLS", Name);
	
	new Motd[1024], Line[256];
	formatex(Line, 255, "<body bgcolor=^"black^">^n<font color=^"red^">^n");
	add(Motd, 1023, Line, 255);
	formatex(Line, 255, "<p align=^"center^">%s %s by: %s</p></font>^n<font color=^"white^">^n", PLUGIN, VERSION, AUTHOR);
	add(Motd, 1023, Line, 255);
	formatex(Line, 255, "<p align=^"center^">%L:</p></font>^n", LANG_SERVER, "PKILLS", Name);
	add(Motd, 1023, Line, 255);
	formatex(Line, 255, "<font color=^"cyan^">^n");
	add(Motd, 1023, Line, 255);
	formatex(Line, 255, "<h5>^n");
	add(Motd, 1023, Line, 255);
 
	if(Target > 0)
	{
		formatex(Line, 255, "<p align=^"center^">");
		add(Motd, 1023, Line, 255);
		new Len;
		for(new Num = 1; Num < MAXWEAPONS+1; Num++)
		{
			if(Num == 2 || Num == 6 || Num == 9 || Num == 25)
			{
				continue;
			}
			
			Len++;
			
			if(Len < POINTSLEN)
			{
				formatex(Line, 255, " %s: %d |", WeaponNames[Num], KillPoints[Num][Target]);
				add(Motd, 1023, Line, 255);
			}
			else
			{
				Len = 0;
				formatex(Line, 255, " %s: %d</p>^n<p align=^"center^">", WeaponNames[Num], KillPoints[Num][Target]);
				add(Motd, 1023, Line, 255);
			}
		}
		formatex(Line, 255, "</p>");
		add(Motd, 1023, Line, 255);
	}
	formatex(Line, 255, "^n</h5>^n</font>^n</body>");
	add(Motd, 1023, Line, 255);
	show_motd(Player, Motd, MotdTitle);
}
public Say(Player)
{
	new Message[32];
	read_args(Message, 31);
	remove_quotes(Message);
	
	if(equali(Message, "/mykills"))
	{
		ShowPoints(Player, Player);
	}
	else if(containi(Message, "/skins") != -1)
	{
		for(new Num; Num < MAXWEAPONS+1; Num++)
		{
			if(containi(Message, WeaponNames[Num]) != -1)
			{
				ShowSkins(Player, Num);
				return PLUGIN_HANDLED;
			}
		}
	}
	else
	{
		new TargetName[32], Name[32], Command[32];
		parse(Message, Command, 31, TargetName, 31);
		if(equali(Command, "/kill"))
		{
			for(new Target; Target < 32; Target++)
			{
				if(Target == Player || !is_user_connected(Target))
				{
					continue;
				}
				
				get_user_name(Target, Name, 31);
				
				if((containi(Name, TargetName) != -1))
				{
					if(equali(Name, TargetName))
					ShowPoints(Player, Target);
					else if(strlen(TargetName) > 3)
					ShowPoints(Player, Target);
					return PLUGIN_HANDLED;
				}
			}
		}
	}
	return PLUGIN_CONTINUE;
}
public client_putinserver(Player)
{
	remove_task(Player);
	set_task(LOADTIME, "LoadPoints", Player);
}
public client_connect(Player)
{
	for(new Num = 1; Num < MAXWEAPONS+1; Num++)
	{
		KillPoints[Num][Player] = 0;
	}
}
public LoadPoints(Player)
{
	if(!is_user_connected(Player))
	{
		return PLUGIN_HANDLED;
	}
	
	new File;
	File = fopen(PointsFile, "rt");
	
	if(File)
	{
		new Line[192];
		new Name[32], LineName[32], Data[31][8];
		
		get_user_name(Player, Name, charsmax(Name));
		while(!feof(File))
		{
			fgets(File, Line, 191);
			
			if(Line[0] == ';' || strlen(Line) < 2)
				continue;
				
			parse(Line, LineName, 31);
			
			if(equal(LineName, Name))
			{
				parse(Line, Data[0], 7, Data[1], 7, Data[2], 7, Data[3], 7, Data[4], 7, Data[5], 7,
				Data[6], 7, Data[7], 7, Data[8], 7, Data[9], 7, Data[10], 7, Data[11], 7, Data[12], 7,
				Data[13], 7, Data[14], 7, Data[15], 7, Data[16], 7, Data[17], 7, Data[18], 7, Data[19], 7,
				Data[20], 7, Data[21], 7, Data[22], 7, Data[23], 7, Data[24], 7, Data[25], 7, Data[26], 7,
				Data[27], 7, Data[28], 7, Data[29], 7, Data[30], 7);
				
				for(new Num = 1; Num < MAXWEAPONS+1; Num++)
				{
					KillPoints[Num][Player] = str_to_num(Data[Num]);
				}
				return PLUGIN_HANDLED;
			}
		}
		fclose(File);
	}
	return PLUGIN_CONTINUE;
}
public SavePoints(Player)
{
	if(!is_user_connected(Player))
	{
		return PLUGIN_HANDLED;
	}
	
	new File;
	File = fopen(PointsFile, "rt");
	
	if(File)
	{
		new Line[192], LineNum;
		
		new Name[32], LineName[32], bool:Found;
		get_user_name(Player, Name, charsmax(Name));
		
		while(!feof(File))
		{
			fgets(File, Line, 191);
			
			if(Line[0] == ';' || strlen(Line) < 2)
				continue;
				
			parse(Line, LineName, 31);
			
			if(equal(LineName, Name) && !Found)
			{
				new SaveLine[192], PlayerPoints[192], String[8];
				
				for(new Num = 1; Num < MAXWEAPONS+1; Num++)
				{
					format(String, 7, "^"%i^" ", KillPoints[Num][Player]);
					add(PlayerPoints, 191, String);
				}
				
				formatex(SaveLine, 191, "^"%s^" %s", Name, PlayerPoints);
				write_file(PointsFile, SaveLine, LineNum);
				Found = true;
				return PLUGIN_HANDLED;
			}
			
			LineNum++;
		}
		
		if(!Found)
		{
			new SaveLine[192], PlayerPoints[192], String[8];
				
			for(new Num; Num < MAXWEAPONS; Num++)
			{
				format(String, 7, "^"%i^" ", KillPoints[Num][Player]);
				add(PlayerPoints, 191, String);
			}
			
			formatex(SaveLine, 191, "^"%s^" %s", Name, PlayerPoints);
			write_file(PointsFile, SaveLine);
			return PLUGIN_HANDLED;
		}
		fclose(File);
	}
	return PLUGIN_CONTINUE;
}
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1038\\ f0\\ fs16 \n\\ par }
*/
