/*================================================================================
	
	-------------------------------------------
	-*- [ZP] Extra Item: Parachute 1.1 -*-
	-------------------------------------------
	
	~~~~~~~~~~~~~~~
	- Description -
	~~~~~~~~~~~~~~~
	
	This item allows humans to float slowly to the ground while holding down the USE button.
	
	One can hold several parachutes at the same time.
	
	Credits to:
	KRoTaL/JTP10181
	
================================================================================*/

#include <amxmodx>
#include <fakemeta>
#include <zombieplague>

/*================================================================================
 [Plugin Customization]
=================================================================================*/

// uncomment the following line if you want that a parachute lasts for a whole round
// #define WHOLE_ROUND
const g_item_cost = 5
const Float:g_fFallspeed = -100.0 // higher (absolute) value means higher fallspeed. (just negative because of downwards direction)

/*===============================================================================*/

#if defined WHOLE_ROUND
new const g_item_name[] = { "Parachute (for one round)" }
#else
new const g_item_name[] = { "Parachute (+1)" }
#endif

new g_itemid_parachute;
new parachutes_num[33] = 0;
new para_ent[33] = 0;
new Float:save_gravity[33] = 1.0;

public plugin_init()
{
	register_plugin("[ZP] Extra Item: Parachute", "1.1", "pharse")
	
	register_forward(FM_PlayerPreThink, "FW_PlayerPreThink");
	
	register_event("HLTV", "EVENT_round_start", "a", "1=0", "2=0");
	
	g_itemid_parachute = zp_register_extra_item(g_item_name, g_item_cost, ZP_TEAM_HUMAN);
}

public plugin_precache()
{
	precache_model("models/parachute.mdl")
}

public client_connect(id)
{
	parachute_reset(id)
}

public client_disconnect(id)
{
	parachute_reset(id)
}

public parachute_reset(id)
{
	if(para_ent[id] > 0) {
		if (pev_valid(para_ent[id]))
			EF_RemoveEntity(para_ent[id])
	}

	parachutes_num[id] = 0;
	para_ent[id] = 0;
	save_gravity[id] = 1.0;
}

public EVENT_round_start()
{
	for (new id; id <= 32; id++) parachute_reset(id);
}

public FW_PlayerPreThink(id)
{
	//parachute.mdl animation information
	//0 - deploy - 84 frames
	//1 - idle - 39 frames
	//2 - detach - 29 frames
	
	if (!is_user_alive(id) || !parachutes_num[id]) return
	
	if (zp_get_user_zombie(id)){
		parachute_reset(id);
		return;
	}
	
	new Float:frame

	new button = pev(id,pev_button)
	new oldbutton = pev(id,pev_oldbuttons)
	new flags = pev(id,pev_flags)

	if (para_ent[id] > 0 && (flags & FL_ONGROUND)) {
		
		set_pev(id,pev_gravity,save_gravity)
		EF_RemoveEntity(para_ent[id])
		para_ent[id] = 0
		remove_one_parachute(id)
		return
	}

	if ( (button & IN_USE) && !(flags & FL_ONGROUND) ) {

		new Float:velocity[3]
		pev(id,pev_velocity,velocity)

		if (velocity[2] < 0.0) {

			if(para_ent[id] <= 0) {
				para_ent[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString,"info_target"))
				if(para_ent[id] > 0) {
					set_pev(para_ent[id],pev_classname,"parachute")
					set_pev(para_ent[id],pev_aiment,id)
					set_pev(para_ent[id],pev_owner,id)
					set_pev(para_ent[id],pev_movetype,MOVETYPE_FOLLOW)
					engfunc(EngFunc_SetModel,para_ent[id],"models/parachute.mdl")
					set_pev(para_ent[id],pev_sequence,0)
					set_pev(para_ent[id],pev_gaitsequence,1)
					set_pev(para_ent[id],pev_frame,0.0)
					set_pev(para_ent[id],pev_fuser1,0.0)
					pev(id,pev_gravity,save_gravity[id]);
				}
			}

			if (para_ent[id] > 0) {

				set_pev(id,pev_sequence,3)
				set_pev(id,pev_gaitsequence,1)
				set_pev(id,pev_frame,1.0)
				set_pev(id,pev_framerate,1.0)
				set_pev(id,pev_gravity,0.1)

				velocity[2] = (velocity[2] + 40.0 < g_fFallspeed) ? velocity[2] + 40.0 : g_fFallspeed
				set_pev(id,pev_velocity,velocity)

				if (pev(para_ent[id],pev_sequence) == 0) {

					frame = pev(para_ent[id],pev_fuser1) + 1.0
					set_pev(para_ent[id],pev_fuser1,frame)
					set_pev(para_ent[id],pev_frame,frame)

					if (frame > 100.0) {
						set_pev(para_ent[id],pev_animtime,0.0)
						set_pev(para_ent[id],pev_framerate,0.4)
						set_pev(para_ent[id],pev_sequence,1)
						set_pev(para_ent[id],pev_gaitsequence,1)
						set_pev(para_ent[id],pev_frame,0.0)
						set_pev(para_ent[id],pev_fuser1,0.0)
					}
				}
			}
		}
		else if (para_ent[id] > 0) {
			EF_RemoveEntity(para_ent[id])
			set_pev(id,pev_gravity,save_gravity[id])
			para_ent[id] = 0
			remove_one_parachute(id)
		}
	}
	else if ((oldbutton & IN_USE) && para_ent[id] > 0 ) {
		EF_RemoveEntity(para_ent[id])
		set_pev(id,pev_gravity,save_gravity[id])
		para_ent[id] = 0
		remove_one_parachute(id)
	}
}

// Player buys our upgrade, add one parachute
public zp_extra_item_selected(player, itemid)
{
	if (itemid == g_itemid_parachute){
		
		parachutes_num[player] += 1;
		#if defined WHOLE_ROUND
		client_print(player, print_chat, "[ZP] You have just bought a Parachutes. Hold down the USE key to float slowly down to the ground.");
		#else
		client_print(player, print_chat, "[ZP] You now have %d Parachutes. Hold down the USE key to float slowly down to the ground.", parachutes_num[player]);
		#endif
	}
}

public remove_one_parachute(id)
{
	#if defined WHOLE_ROUND
	return;
	#endif
	parachutes_num[id] -= 1;
	
	if (parachutes_num[id] > 0 )
		client_print(id, print_chat, "[ZP] You still have %d Parachutes.", parachutes_num[id]);
}

// from fakemeta_stocks.inc
public EF_RemoveEntity(ENTITY)
{
	engfunc(EngFunc_RemoveEntity, ENTITY);
}