#include <amxmodx>
#include <fakemeta>
#include <cstrike>

#define PLUGIN "Paintball Gun"
#define VERSION "1.1"
#define AUTHOR "WhooKid"

new Float:lastshot[33],g_ballsnum,Score;
new onoff,color,shots,veloc,speed,blife,sound;

public plugin_init()
{
	register_plugin(PLUGIN,VERSION,AUTHOR);
	register_cvar("paintballgun",VERSION,FCVAR_SERVER|FCVAR_UNLOGGED);
	server_print("*** %s v%s by %s Enabled ***",PLUGIN,VERSION,AUTHOR);

	register_event("CurWeapon", "ev_curweapon", "be");
	register_forward(FM_UpdateClientData,"fw_updateclientdata",1)
	register_logevent("new_round",2,"0=World triggered","1=Round_Start");
	register_clcmd("say /ent","ent_info",ADMIN_SLAY);

	onoff = register_cvar("amx_pbgun","1");
	color = register_cvar("pbgun_color","1");
	shots = register_cvar("pbgun_shots","220");
	veloc = register_cvar("pbgun_velocity","2000");
	speed = register_cvar("pbgun_speed","0.08");
	blife = register_cvar("pbgun_life","10");
	sound = register_cvar("pbgun_sound","1");
	Score = get_user_msgid("ScoreInfo");
}

public plugin_precache()
{
	precache_sound("misc/pb1.wav");
	precache_sound("misc/pb2.wav");
	precache_sound("misc/pb3.wav");
	precache_sound("misc/pb4.wav");
	precache_sound("misc/pbg.wav");
	precache_model("models/shell.mdl");
	precache_model("sprites/bhit.spr");
	precache_model("sprites/richo1.spr");
	precache_model("models/p_pbgun.mdl");
	precache_model("models/v_pbgun.mdl");
}

public ent_info(id)
	client_print(id,print_chat,"[AMXX] [Ent Info (Current/Max)] Paintballs: (%d/%d)   Entities: (%d/%d)",g_ballsnum,get_pcvar_num(shots),engfunc(EngFunc_NumberOfEntities),global_get(glb_maxEntities));

public ev_curweapon(id)
{
	static model[30];
	pev(id,pev_viewmodel2,model,29);
	if (get_pcvar_num(onoff) && equali(model,"models/v_mp5.mdl"))
	{
		set_pev(id,pev_viewmodel2,"models/v_pbgun.mdl");
		set_pev(id,pev_weaponmodel2,"models/p_pbgun.mdl");
	}
}

public fw_updateclientdata(id,sw,cd_handle)
{
	if (get_pcvar_num(onoff) && user_has_pbgun(id))
	{
		set_cd(cd_handle,CD_flNextAttack,get_gametime()+0.001);
		return FMRES_HANDLED;
	}
	return FMRES_IGNORED;
}

public client_PreThink(id)
{
	if (get_pcvar_num(onoff) && user_has_pbgun(id))
	{
		new buttons = pev(id,pev_button);
		if (buttons & IN_ATTACK)
		{
			new ammo,null = get_user_weapon(id,ammo,null);
			if (ammo)
			{
				set_pev(id,pev_button,buttons & ~IN_ATTACK);
				new Float:gametime = get_gametime();
				if (gametime-lastshot[id]>get_pcvar_float(speed))
				{
					if (fire_paint(id))
					{
						lastshot[id] = gametime;
						set_user_clip(id,ammo-1);
						set_pev(id,pev_punchangle,Float:{-0.5, 0.0, 0.0});
						message_begin(MSG_ONE,SVC_WEAPONANIM,_,id);
						write_byte(3);
						write_byte(0);
						message_end();
						if (get_pcvar_num(sound))
							emit_sound(id,CHAN_AUTO,"misc/pbg.wav",1.0,ATTN_NORM,0,PITCH_NORM);
					}
				}
			}
		}
	}
	return PLUGIN_CONTINUE;
}

public fire_paint(id)
{
	new ent;
	if (g_ballsnum < get_pcvar_num(shots))
		ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"));
	else
		if (engfunc(EngFunc_RemoveEntity,engfunc(EngFunc_FindEntityByString,ent,"classname","pbPaint")))
			g_ballsnum--;

	if (pev_valid(ent))
	{
		static Float:vangles[3],Float:nvelocity[3],Float:voriginf[3],vorigin[3];
		set_pev(ent,pev_classname,"pbBullet");
		set_pev(ent,pev_owner,id);
		set_pev(ent,pev_euser1,id);
		engfunc(EngFunc_SetModel,ent,"models/shell.mdl");
		engfunc(EngFunc_SetSize,ent,Float:{-1.0,-1.0,-1.0},Float:{1.0,1.0,1.0});

		get_user_origin(id,vorigin,1);
		IVecFVec(vorigin,voriginf);
		set_pev(ent,pev_origin,voriginf);

		pev(id,pev_v_angle,vangles);
		set_pev(ent,pev_angles,vangles);
		set_pev(ent,pev_v_angle,vangles);

		set_pev(ent,pev_solid,2);
		set_pev(ent,pev_movetype,5);

		velocity_by_aim(id,get_pcvar_num(veloc),nvelocity);
		set_pev(ent,pev_velocity,nvelocity);

		set_pev(ent,pev_nextthink,get_gametime()+(get_pcvar_num(blife)*1.6));

		set_task(0.1,"bullet_glow",ent);

		g_ballsnum++;

		return ent;
	}
	return 0;
}

public pfn_touch(bullet,ent)
{
	new class[30];
	pev(bullet,pev_classname,class,29);
	if (!equali(class,"pbBullet"))
		return;

	new Float:origin[3],class2[30],owner = pev(bullet,pev_euser1);
	pev(ent,pev_classname,class2,29);
	pev(bullet,pev_origin,origin);

	if (is_user_alive(ent))
	{
		new Float:origin2[3],Float:maxs[3],ffkill,headshot = 1;
		
		if (owner == ent || pev(ent,pev_takedamage) == DAMAGE_NO)
			return;
		if (get_user_team(owner) == get_user_team(ent))
			if (get_cvar_num("mp_friendlyfire"))
				ffkill = 1;
			else
				return;

		pev(ent,pev_origin,origin2);
		pev(bullet,pev_maxs,maxs);
		origin[2] += maxs[2];
		if (vector_distance(origin2,origin) <= 26.3)
			headshot = 0;
		origin[2] -= maxs[2];

		user_silentkill(ent);

		if (is_user_connected(owner))
		{
			set_pev(owner,pev_frags,float(ffkill ? get_user_frags(owner)-1 : get_user_frags(owner)+1))

			message_begin(MSG_BROADCAST,Score);
			write_byte(owner);
			write_short(get_user_frags(owner));
			write_short(cs_get_user_deaths(owner));
			write_short(0);
			write_short(get_user_team(owner));
			message_end();

			make_deathmsg(owner,ent,headshot,"mp5navy");

			if (ffkill)
				cs_set_user_tked(owner,1,0);
		}
	}

	if (pev_valid(bullet) && !equali(class,class2))
	{
		static clr[3],wav[15];
		set_pev(bullet,pev_velocity,Float:{0.0,0.0,0.0});
		set_pev(bullet,pev_classname,"pbPaint");
		set_pev(bullet,pev_solid,0);
		set_pev(bullet,pev_movetype,0);
		set_pev(bullet,pev_origin,origin);
		engfunc(EngFunc_SetModel,bullet,random_num(0,1) ? "sprites/bhit.spr" : "sprites/richo1.spr");

		if (task_exists(bullet))
			remove_task(bullet);

		if (get_pcvar_num(sound))
		{
			switch (random_num(1,4))
			{
				case 1: formatex(wav,14,"misc/pb1.wav");
				case 2: formatex(wav,14,"misc/pb2.wav");
				case 3: formatex(wav,14,"misc/pb3.wav");
				case 4: formatex(wav,14,"misc/pb4.wav");
			}
			emit_sound(bullet,CHAN_AUTO,wav,1.0,ATTN_NORM,0,PITCH_NORM);
		}

		switch (get_pcvar_num(color))
		{
			case 2: clr = (get_user_team(owner)==1) ? {255,0,0} : {0,0,255};
			default: {
				switch (random_num(1,8))
				{
					case 1: clr = {255,255,255}	//white
					case 2: clr = {255,0,0}		//red
					case 3: clr = {0,255,0}		//green
					case 4: clr = {0,0,255}		//blue
					case 5: clr = {255,255,0}	//yellow
					case 6: clr = {255,0,255}	//magenta
					case 7: clr = {255,20,147}	//pink
					case 8: clr = {255,165,0}	//orange
				}
			}	
		}	
		set_rendering2(bullet,kRenderFxNoDissipation,clr[0],clr[1],clr[2],kRenderGlow,255);

		set_pev(bullet,pev_flags,FL_ALWAYSTHINK);
		set_pev(bullet,pev_nextthink,get_gametime()+get_pcvar_num(blife));
	}
}

public pfn_think(ent)
{
	if (pev_valid(ent))
	{
		static class[30];
		pev(ent,pev_classname,class,29);
		if (equali(class,"pbPaint") || equali(class,"pbBullet"))
		{
			engfunc(EngFunc_RemoveEntity,ent);
			g_ballsnum--;
		}
	}
}

public bullet_glow(ent)
{
	if (pev_valid(ent))
	{
		static clr[3];
		switch (get_pcvar_num(color))
		{
			case 2: clr = (get_user_team(pev(ent,pev_euser1))==1) ? {255,0,0} : {0,0,255};
			default: clr = {255,255,255};
		}
		set_rendering2(ent,kRenderFxGlowShell,clr[0],clr[1],clr[2],kRenderNormal,255);
	}
}

public new_round()
{
	new ent = -1;
	while (((ent = engfunc(EngFunc_FindEntityByString,ent,"classname","pbPaint")) != 0) || ((ent = engfunc(EngFunc_FindEntityByString,ent,"classname","pbBullet")) != 0))
		engfunc(EngFunc_RemoveEntity,ent);
	g_ballsnum = 0;
}

stock user_has_pbgun(id)
{
	if (is_user_alive(id))
	{
		static model[30];
		pev(id,pev_viewmodel2,model,29);	
		if (equali(model,"models/v_pbgun.mdl"))
			return 1;
	}
	return 0;
}

stock set_user_clip(id,ammo)
{
	new wpn[32],WPNid=-1,null,weaponid = get_user_weapon(id,null,null);
	get_weaponname(weaponid,wpn,31);
	while ((WPNid = engfunc(EngFunc_FindEntityByString,WPNid,"classname",wpn)) != 0)
		if (id == pev(WPNid,pev_owner)){
			cs_set_weapon_ammo(WPNid,ammo);
			return WPNid;
		}
	return 0;
}

// teame06's function
stock set_rendering2(index,fx,r,g,b,render,amount)
{
	set_pev(index, pev_renderfx, fx);
	new Float:RenderColor[3];
	RenderColor[0] = float(r);
	RenderColor[1] = float(g);
	RenderColor[2] = float(b);
	set_pev(index, pev_rendercolor, RenderColor);
	set_pev(index, pev_rendermode, render);
	set_pev(index, pev_renderamt, float(amount));
}
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1033\\ f0\\ fs16 \n\\ par }
*/
