#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fakemeta>
#include <hamsandwich>
#include <jailbreak>

#define PLUGIN "Jail Ball"
#define VERSION "1.0"
#define AUTHOR "xPaw,Cypis"

new g_trail, Float:g_origin[3], bool:g_CreateBall, g_ball;
public plugin_init() 
{
	register_plugin(PLUGIN, VERSION, AUTHOR);

	RegisterHam(Ham_ObjectCaps, "player", "FwdHamObjectCaps", 1);

	new const szEntity[][] = {
		"worldspawn", "func_wall", "func_door",  "func_door_rotating",
		"func_wall_toggle", "func_breakable", "func_pushable", "func_train",
		"func_illusionary", "func_button", "func_rot_button", "func_rotating"
	}
	
	for(new i=0; i<sizeof szEntity; i++)
		register_touch("ball", szEntity[i], "FwdTouchWorld");
		
	register_touch("ball", "player", "FwdTouchPlayer");
	register_think("ball", "FwdThinkBall");
	
	register_clcmd("say /ball", "MenuBall");
	register_clcmd("say /reset", "vUpdateBall");
	
	register_clcmd("jail_pilka", "MenuBall");
	
	WczytajPliki();
}

public plugin_precache()
{
	g_trail = precache_model("sprites/laserbeam.spr");

	precache_model("models/jb_cypis/ball.mdl");
	
	precache_sound("jb_cypis/bounce.wav");
}

public WczytajPliki()
{
	new szMap[32], szFile[128], bool:znalazl_wczyt = false;
	get_mapname(szMap, 31);
	formatex(szFile, 127, "addons/amxmodx/data/ball/%s.ini", szMap);
	
	if(file_exists(szFile))
	{
		new dane_tablicy[3][32], tablica[256], txtlen;	
		read_file(szFile, 0, tablica, 255, txtlen);
		if(txtlen > 3)
		{
			parse(tablica, dane_tablicy[0], 31, dane_tablicy[1], 31, dane_tablicy[2], 31);
				
			g_origin[0] = str_to_float(dane_tablicy[0]);
			g_origin[1] = str_to_float(dane_tablicy[1]);
			g_origin[2] = str_to_float(dane_tablicy[2]);
			
			znalazl_wczyt = true;
		}
	}

	if(znalazl_wczyt)
	{
		remove_entity_name("func_pushable");
		CreateBall(g_origin);
	}
	else
	{
		new ent;
		while((ent = find_ent_by_class(ent, "func_pushable")) > 0)
		{
			get_brush_entity_origin(ent, g_origin);
			remove_entity(ent);
				
			g_origin[2] += 15.0;
			CreateBall(g_origin);
			ZapiszPilke(g_origin);
			break;
		}
	}
	AddMenuItem("Dodanie Pilki", "jail_pilka", ADMIN_RCON, "Jail");
}

public OnRemoveData()
{	
	if(g_CreateBall)
	{
		if(!pev_valid(g_ball))
			CreateBall(g_origin);
		else 
			UpdateBall();
	}
}

public FwdHamObjectCaps(id)
{
	if(is_user_alive(id) && pev_valid(g_ball)) 
	{
		if(pev(g_ball, pev_iuser1) == id)
			KickBall(id);
	}
}

public FwdThinkBall(ent) 
{
	if(!pev_valid(ent))
		return PLUGIN_HANDLED;
	
	set_pev(ent, pev_nextthink, halflife_time()+0.05);
	
	new Float:EntOrigin[3], Float:EntVelocity[3];
	pev(ent, pev_origin, EntOrigin); 
	pev(ent, pev_velocity, EntVelocity); 
	
	new owner = pev(ent, pev_iuser1);
	new solid = pev(ent, pev_solid);
	
	static Float:LastThink;
	if(LastThink < get_gametime()) 
	{
		if(floatround(vector_length(EntVelocity)) > 10) 
		{
			message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
			write_byte(TE_KILLBEAM);
			write_short(g_ball);
			message_end();
			
			message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
			write_byte(TE_BEAMFOLLOW);
			write_short(g_ball);
			write_short(g_trail);
			write_byte(10);
			write_byte(10);
			write_byte(0);//r
			write_byte(170);//g
			write_byte(127);//b
			write_byte(255);//alpha ?
			message_end();
		}
		LastThink = get_gametime()+3.0;
	}

	if(owner) 
	{
		new Float:OwnerOrigin[3];
		pev(owner, pev_origin, OwnerOrigin); 
		
		if(!is_user_alive(owner))
		{
			OwnerOrigin[2] += 5.0;
			
			set_pev(ent, pev_iuser1, 0);
			set_pev(ent, pev_origin, OwnerOrigin); 
			set_pev(ent, pev_velocity, Float:{1.0, 1.0, 0.0}); 
			return PLUGIN_CONTINUE;
		}
		
		if(solid != SOLID_NOT)
			set_pev(ent, pev_solid, SOLID_NOT);
		
		set_pev(ent, pev_frame, pev(ent, pev_frame));
		set_pev(ent, pev_animtime, 0.0);
		set_pev(ent, pev_framerate, 0.0);
		
		new Float:Angles[3], Float:vReturn[3];
		pev(owner, pev_v_angle, Angles);
		
		vReturn[0] = (floatcos(Angles[1], degrees) * 55.0) + OwnerOrigin[0];
		vReturn[1] = (floatsin(Angles[1], degrees) * 55.0) + OwnerOrigin[1];
		vReturn[2] = OwnerOrigin[2] - ((pev(owner, pev_flags) & FL_DUCKING) ?10.0: 30.0);
	
		set_pev(ent, pev_origin, vReturn); 
		set_pev(ent, pev_velocity, Float:{1.0, 1.0, 0.0}); 
	} 
	else 
	{
		if(solid != SOLID_TRIGGER)
			set_pev(ent, pev_solid, SOLID_TRIGGER);
		
		static Float:VerticalOrigin;
		if(!EntVelocity[2]) 
		{
			set_pev(ent, pev_frame, pev(ent, pev_frame));
			set_pev(ent, pev_animtime, 0.0);
			set_pev(ent, pev_framerate, 0.0);

			static iCounts;
			if(VerticalOrigin > EntOrigin[2]) 
			{
				iCounts++;
				if(iCounts > 10) 
				{
					iCounts = 0;
					UpdateBall();
				}
			}
			else
			{
				iCounts = 0;
				if(PointContents(EntOrigin) != CONTENTS_EMPTY)
					UpdateBall();
			}
			VerticalOrigin = EntOrigin[2];
		}
	}
	return PLUGIN_CONTINUE;
}

KickBall(id)
{
	new Float:origin[3];
	pev(g_ball, pev_origin, origin); 
	
	if(PointContents(origin) != CONTENTS_EMPTY)
		return PLUGIN_HANDLED;
	
	new Float:velocity[3], Float:Angles[3];
	velocity_by_aim(id, 630, velocity);
	pev(id, pev_v_angle, Angles);
	Angles[0] = 0.0;
	set_pev(g_ball, pev_angles, Angles);
	
	set_pev(g_ball, pev_solid, SOLID_TRIGGER);
	set_pev(g_ball, pev_frame, pev(g_ball, pev_frame));
	set_pev(g_ball, pev_animtime, get_gametime());
	set_pev(g_ball, pev_framerate, 1.0);
	
	set_pev(g_ball, pev_iuser1, 0);
	set_pev(g_ball, pev_velocity, velocity); 
	
	jail_set_user_speed(id, 250.0);	
	return PLUGIN_CONTINUE;
}

public FwdTouchPlayer(ent, id)
{
	if(!pev(ent, pev_iuser1))
	{
		set_pev(ent, pev_iuser1, id);
		jail_set_user_speed(id, 200.0);
	}
	return PLUGIN_CONTINUE;
}

public FwdTouchWorld(ent, world)
{
	new Float:velocity[3];
	pev(ent, pev_velocity, velocity); 
	
	if(floatround(vector_length(velocity)) > 10)
	{
		velocity[0] *= 0.85;
		velocity[1] *= 0.85;
		velocity[2] *= 0.85;

		if(velocity[0] && velocity[1])
		{
			new Float:Angels[3];
			vector_to_angle(velocity, Angels);
			Angels[0] = 0.0;
			set_pev(ent, pev_angles, Angels);
		}
		set_pev(ent, pev_velocity, velocity);
		emit_sound(ent, CHAN_ITEM, "jb_cypis/bounce.wav", 1.0, ATTN_NORM, 0, PITCH_NORM);
	}
	return PLUGIN_CONTINUE;
}

public MenuBall(id) 
{
	if(!(get_user_flags(id) & ADMIN_RCON))
		return PLUGIN_HANDLED;
		
	new menu = menu_create("Menu:", "HandleMenuBall");
	menu_additem(menu, "Stworz Pilke");
	menu_additem(menu, "Resetuj Pilke");
	menu_additem(menu, "Usun Pilke");
	menu_setprop(menu, MPROP_EXITNAME, "Wyjdz");
	menu_display(id, menu);
	return PLUGIN_HANDLED;
}

public HandleMenuBall(id, menu, item)
{
	if(item == MENU_EXIT)
	{
		return PLUGIN_CONTINUE;
	}
	switch(item) 
	{
		case 0:    
		{
			if(pev_valid(g_ball))
				remove_entity_name("ball");
			
			new origin[3];
			get_user_origin(id, origin, 3);
			IVecFVec(origin, g_origin);
			
			g_origin[2] += 15.0;
			CreateBall(g_origin);
			ZapiszPilke(g_origin);
		}
		case 1: 
		{
			if(pev_valid(g_ball))
				UpdateBall();
		}
		case 2: 
		{
			if(!pev_valid(g_ball))
				return PLUGIN_CONTINUE;
			
			g_CreateBall = false;
			remove_entity_name("ball");
			
			new szMapa[32], szFile[128];
			get_mapname(szMapa, 31);
			formatex(szFile, 127, "addons/amxmodx/data/ball/%s.ini", szMapa);
			write_file(szFile, "", 0);
		}
	}
	menu_display(id, menu);
	return PLUGIN_CONTINUE;
}

public vUpdateBall(id)
{
	if(get_user_flags(id) & ADMIN_BAN)
		UpdateBall();
	return PLUGIN_HANDLED;
}

UpdateBall()
{
	if(!pev_valid(g_ball))
		return
		
	set_pev(g_ball, pev_velocity, Float:{0.0, 0.0, 0.1}); 
	set_pev(g_ball, pev_mins, Float:{-15.0, -15.0, 0.0});
	set_pev(g_ball, pev_maxs, Float:{15.0, 15.0, 15.0});
		
	set_pev(g_ball, pev_solid, SOLID_TRIGGER);
	set_pev(g_ball, pev_frame, 0.0);
	set_pev(g_ball, pev_animtime, 0.0);
	set_pev(g_ball, pev_framerate, 0.0);
	set_pev(g_ball, pev_iuser1, 0);
	
	set_pev(g_ball, pev_origin, g_origin);
}

CreateBall(Float:origin[3])
{
	g_ball = create_entity("info_target");
			
	set_pev(g_ball, pev_classname, "ball");
	engfunc(EngFunc_SetModel, g_ball, "models/jb_cypis/ball.mdl");
			
	set_pev(g_ball, pev_solid, SOLID_TRIGGER);
	set_pev(g_ball, pev_movetype, MOVETYPE_BOUNCE);
			
	set_pev(g_ball, pev_mins, Float:{-15.0, -15.0, 0.0});
	set_pev(g_ball, pev_maxs, Float:{15.0, 15.0, 15.0});
		
	set_pev(g_ball, pev_sequence, 2);
	set_pev(g_ball, pev_framerate, 0.0);
	set_pev(g_ball, pev_frame, 0.0);

	set_pev(g_ball, pev_origin, origin);
	set_pev(g_ball, pev_nextthink, get_gametime()+0.05);
	g_CreateBall = true;
}

ZapiszPilke(Float:origin[3])
{
	new szTemp[128], szMapa[32], szFile[128];
	get_mapname(szMapa, 31);
	
	formatex(szFile, 127, "addons/amxmodx/data/ball/%s.ini", szMapa);
	formatex(szTemp, 127, "%f %f %f", origin[0], origin[1], origin[2]);
	write_file(szFile, szTemp, 0);
}
