#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <hamsandwich>
#include <nst_zombie>
#include <xs>
#include <nst_wpn>
#include <metahook>
#define ENTITY_PLAYER	pev_iuser2
#define ENTITY_TABLE	pev_iuser3
#define PLUGIN "DJB Zombie Class Banchee"
#define VERSION "1.0"
#define AUTHOR "Csoldjb"



new const CONFIG_NAME[] = "[Banchee Zombie]"
new idclass
new zombie_name[64], zombie_model[64], zombie_health, zombie_sex, zombie_modelindex, zombie_boss, Float:zombie_gravity, Float:zombie_speed, Float:zombie_knockback, zombie_sound_evolution[64],
zombie_sound_death1[64], zombie_sound_death2[64], zombie_sound_hurt1[64], zombie_sound_hurt2[64]

new banchee_skull_model_host[64],banchee_skull_model_origin[64]
new Float:banchee_skull_bat_speed,Float:banchee_skull_bat_flytime,Float:banchee_skull_bat_catch_time,Float:banchee_skull_bat_catch_speed

new bat_timewait

new zombie_sound_bat_hit[64],zombie_sound_bat_miss[64]
new g_stop[33]

new g_bat_time[33]
new g_bat_stat[33]
new g_bat_enemy[33]

new g_illusion_stat[33]
new g_fake_entity[33]

//!!!!
new g_ent_owner
new g_model_index
new spr_skull
// Task offsets
enum (+= 100)
{
	TASK_WAIT_ILLUSIOIN =2000 ,
	TASK_BOT_USE_SKILL,
	TASK_REMOVE_STAT
}
enum EntityPart
{
    Body,
    Weapon
}
public nst_zb_user_infected(id,inf)
{
	if(idclass==nst_zb_get_user_zombie_class(id)&&MH_IsMetaHookPlayer(id))
	{
		new class=djb_cus_ui_get_zombie_class(id)
		MH_NewZBUI(id,"zbs_bat",1,1,1,2,99.0,class)
				MH_NewZBUI(id,"zbs_tancel",1,4,1,2,0.0,class)
		remove_task(id+888)
	}
}
// IDs inside tasks
#define TASK_WAIT_ILLUSIOIN (taskid - TASK_WAIT_ILLUSIOIN)
#define ID_BOT_USE_SKILL (taskid - TASK_BOT_USE_SKILL)
#define ID_TASK_REMOVE_STAT (taskid - TASK_REMOVE_STAT)
public cmd_illusion(id)
{
	g_illusion_stat[id]=1-g_illusion_stat[id]
}
public djb_zbu_selectclass(id)
{
	if(idclass==nst_zb_get_user_zombie_class(id)&&MH_IsMetaHookPlayer(id))
	{
		new class=djb_cus_ui_get_zombie_class(id)
		MH_NewZBUI(id,"zbs_bat",1,1,1,2,99.0,class)
		MH_NewZBUI(id,"zbs_tancel",1,4,1,2,0.0,class)
		remove_task(id+888)
	}
}
	
/*public plugin_cfg()
{
    //g_ent_owner = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"info_target"))
    
        for(new j=1;j<=get_maxplayers();j++)
        {
            new ent = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"info_target"))
            
            set_pev(ent,pev_aiment,j)
            set_pev(ent,pev_movetype,MOVETYPE_FOLLOW)
            set_pev(ent,pev_solid,SOLID_NOT)
	   engfunc(EngFunc_SetModel,ent,"models/v_ak47.mdl") //EMPTY MODEL
	   set_pev(ent,ENTITY_PLAYER,j)
	   set_pev(ent,ENTITY_TABLE,998)
	   g_fake_entity[j] = ent
	   
	   new ent2 = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"info_target"))
            
            set_pev(ent2,pev_aiment,ent)
            set_pev(ent2,pev_movetype,MOVETYPE_FOLLOW)
            set_pev(ent2,pev_solid,SOLID_NOT)
	   engfunc(EngFunc_SetModel,ent2,"models/player/gsg9/gsg9.mdl")
	   set_pev(ent2,ENTITY_PLAYER,j)
	   set_pev(ent2,ENTITY_TABLE,999)
	   set_pev(ent2,pev_framerate,1.0)
	   
	    
        }
}

public fw_WhatsTheFuckPost(es,e,ent,host,hostflags,player,pSet)
{
	if(g_illusion_stat[host])
	{
		if(ent>0&&ent<33)
		{
			if(nst_zb_get_user_zombie(ent))
			{
				set_es(es, ES_RenderMode, kRenderTransAlpha)
				set_es(es, ES_RenderAmt, 1)
				return FMRES_IGNORED
			}
			else
			{
				set_es(es, ES_RenderMode, kRenderTransAlpha)
				set_es(es, ES_RenderAmt, 255)
				return FMRES_IGNORED
			}
				
		}
		else
		{
			if(pev_valid(ent)&&pev(ent,ENTITY_TABLE)==999)
			{
				new aim = pev(ent,ENTITY_PLAYER) //FAKE PLAYER ENTITY DRAW
				if(nst_zb_get_user_zombie(aim))
				{
					new ef=get_es(es,ES_Effects)
					ef&=~EF_NODRAW
					set_es(es,ES_Effects,ef)
					set_es(es,ES_Sequence,pev(1,pev_sequence))
					set_es(es,ES_GaitSequence,pev(1,pev_gaitsequence))
					new Cr[4]
					pev(1,pev_controller,Cr)
					set_es(es,ES_Controller,Cr)
					set_es(es,ES_WeaponAnim,pev(1,pev_weaponanim))
					new Blend[2]
					pev(1,pev_blending,Blend)
					set_es(es,ES_Blending,Blend)
					set_es(es,ES_FrameRate,1.0)

					return FMRES_IGNORED
				}
				else
				{
					set_es(es,ES_Effects,EF_NODRAW)
					return FMRES_IGNORED
				}
			}
		}
					
	}
	else
	{
		if(pev_valid(ent))
		{
			if(pev(ent,ENTITY_TABLE)==999)
			{
				set_es(es,ES_Effects,get_es(es,ES_Effects)|EF_NODRAW) //NORMAL
				return FMRES_IGNORED
			}
		}
	}
				
		
	return FMRES_IGNORED
}
	
	/*if(player)
	{
		if(host>0&&host<33&&ent>0&&ent<33)
		if(g_illusion_stat[host])
		{
			static weaponModel[50]
			pev(ent,pev_weaponmodel2,weaponModel,charsmax(weaponModel))
			set_es(es,ES_ModelIndex,engfunc(EngFunc_ModelIndex,weaponModel))
			set_es(es, ES_Solid, SOLID_NOT)
			set_es(es, ES_RenderMode, kRenderTransAlpha)
			set_es(es, ES_RenderAmt, 1)
		}
	}
			
	
	if(player)
	{
		if(pev_valid(ent) && (pev(ent,pev_owner) == g_ent_owner))
		{
			new aiment = pev(ent,pev_aiment)
			
			
			if(!g_illusion_stat[aiment])
			{
				set_es(es,ES_Effects,EF_NODRAW)
				return FMRES_IGNORED
			}
			client_print(1,print_chat,"CALLED ENT:%d HOST:%d PLAYER:%d",ent,host,player)
			new ef=get_es(es,ES_Effects)
			ef&=~EF_NODRAW
			set_es(es,ES_Effects,ef)
			set_es(es,ES_ModelIndex,g_model_index)
			if(pev(ent,pev_iuser1) == _:Weapon)
			{
				static weaponModel[50]
				pev(aiment,pev_weaponmodel2,weaponModel,charsmax(weaponModel))
				if(weaponModel[0])
				{
					set_es(es,ES_ModelIndex,engfunc(EngFunc_ModelIndex,weaponModel))
					set_es(es,ES_Sequence,pev(aiment,pev_weaponanim))
				}
				else
				{
					set_es(es,ES_Effects,EF_NODRAW)
				}
			}
			else
			{
				
			}
		}
	}*/
public plugin_init()
{
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	// Language files
	register_dictionary(LANG_FILE)
	
	// Events
	register_logevent("logevent_round_start",2, "1=Round_Start")
	register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
	register_event("DeathMsg", "Death", "a")
	
	//Skull Command
	register_clcmd("drop", "cmd_bat")
	register_clcmd("drop2","cmd_illusion")
	register_forward(FM_PlayerPreThink,"fw_PlayerPreThink")
	//register_forward(FM_AddToFullPack,"fw_WhatsTheFuckPost",1)
	
	//Ham Register
	RegisterHam(Ham_Touch,"info_target","fw_Touch_Post",1)
	RegisterHam(Ham_Think,"info_target","fw_Think")
	
}
public fw_Think(ent)
{
	if(!pev_valid(ent)) return HAM_IGNORED
	new classname[32]
	pev(ent,pev_classname,classname,31)
	if(equal(classname,"banchee_bat"))
	{
		static Float:origin[3];
		pev(ent,pev_origin,origin);
    
		message_begin(MSG_BROADCAST,SVC_TEMPENTITY); 
		write_byte(TE_EXPLOSION); // TE_EXPLOSION
		write_coord(floatround(origin[0])); // origin x
		write_coord(floatround(origin[1])); // origin y
		write_coord(floatround(origin[2])); // origin z
		write_short(spr_skull); // sprites
		write_byte(40); // scale in 0.1's
		write_byte(30); // framerate
		write_byte(0); // flags 
		message_end(); // message end
		g_stop[pev(ent,pev_owner)]=0
		engfunc(EngFunc_RemoveEntity,ent)
	}
	
	return HAM_IGNORED
}
public fw_PlayerPreThink(id)
{
	if(!is_user_alive(id)) return FMRES_IGNORED
	if(g_bat_stat[id])
	{
		new owner = g_bat_enemy[id],Float:ownerorigin[3]
		pev(owner,pev_origin,ownerorigin)
		static Float:vec[3]
		aim_at_origin(id,ownerorigin,vec)
		engfunc(EngFunc_MakeVectors, vec)
		global_get(glb_v_forward, vec)
		vec[0] *= banchee_skull_bat_catch_speed
		vec[1] *= banchee_skull_bat_catch_speed
		vec[2] =0.0
		set_pev(id,pev_velocity,vec)
	}
	if(g_stop[id]) set_pev(id,pev_maxspeed,0.1)
	return FMRES_IGNORED
}
public clear_stat(taskid)
{
	new id=ID_TASK_REMOVE_STAT
	g_bat_stat[id]=0
	g_bat_time[id]=0
	if(MH_IsMetaHookPlayer(id))
	{
		if(idclass!=nst_zb_get_user_zombie_class(id)) return
		new class=djb_cus_ui_get_zombie_class(id)
		MH_NewZBUI(id,"zbs_bat",1,3,1,2,1.0,class)
		set_task(1.0,"Fade_Icon",id+888,"",0,"a",2)
		set_task(3.0,"Fade_Icon_End",id+888)
		
	}
}
public Fade_Icon(idx)
{
	new id=idx-888
	if(idclass!=nst_zb_get_user_zombie_class(id)) return
	new class=djb_cus_ui_get_zombie_class(id)
	MH_NewZBUI(id,"zbs_bat",1,3,1,2,1.0,class)
}
public Fade_Icon_End(idx)
{
	new id=idx-888
	if(idclass!=nst_zb_get_user_zombie_class(id)) return
	new class=djb_cus_ui_get_zombie_class(id)
	MH_NewZBUI(id,"zbs_bat",1,1,1,2,99.0,class)
}
public fw_Touch_Post(ent,ptd)
{
	if(!pev_valid(ent)) return HAM_IGNORED
	new classname[32]
	pev(ent,pev_classname,classname,31)
	if(equal(classname,"banchee_bat"))
	{
		if(!pev_valid(ptd))
		{
			static Float:origin[3];
			pev(ent,pev_origin,origin);
    
			message_begin(MSG_BROADCAST,SVC_TEMPENTITY); 
			write_byte(TE_EXPLOSION); // TE_EXPLOSION
			write_coord(floatround(origin[0])); // origin x
			write_coord(floatround(origin[1])); // origin y
			write_coord(floatround(origin[2])); // origin z
			write_short(spr_skull); // sprites
			write_byte(40); // scale in 0.1's
			write_byte(30); // framerate
			write_byte(0); // flags 
			message_end(); // message end
			g_stop[pev(ent,pev_owner)]=0
			engfunc(EngFunc_RemoveEntity,ent)
			return HAM_IGNORED
		}
			
		new owner = pev(ent,pev_owner)
		if(0<ptd&&ptd<33&&is_user_alive(ptd)&&ptd!=owner)
		{
			g_bat_enemy[ptd]=owner
			set_pev(ent,pev_nextthink,get_gametime()+banchee_skull_bat_catch_time)
			set_task(banchee_skull_bat_catch_time,"clear_stat2",ptd+TASK_REMOVE_STAT)
			set_pev(ent,pev_movetype,MOVETYPE_FOLLOW)
			set_pev(ent,pev_aiment,ptd)
			g_bat_stat[ptd]=1
		}
	}
	return HAM_IGNORED
}
public clear_stat2(idx)
{
	new id = idx-TASK_REMOVE_STAT
	g_bat_enemy[id]=0
	g_bat_stat[id]=0
}
public plugin_precache()
{
	load_customization_from_files()
	precache_model(banchee_skull_model_host)
	precache_model(banchee_skull_model_origin)
	spr_skull = precache_model("sprites/ef_bat.spr")
	
	// register zombie class
	new modrun = nst_zb_get_mod()
	// only use in ZB3
	if (modrun==NSTZB_ZB3) idclass = nst_zb3_register_zombie_class(zombie_name, zombie_model, zombie_gravity, zombie_speed, zombie_knockback, zombie_sound_death1, zombie_sound_death2, zombie_sound_hurt1, zombie_sound_hurt2, zombie_sound_bat_hit, zombie_sound_evolution, zombie_sex, zombie_modelindex)	
	if (modrun==NSTZB_ZBU) idclass = nst_zbu_register_zombie_class(zombie_name, zombie_model, zombie_health, zombie_gravity, zombie_speed, zombie_knockback, zombie_sound_death1, zombie_sound_death2, zombie_sound_hurt1, zombie_sound_hurt2, zombie_sound_evolution, zombie_sex, zombie_modelindex)
}
public event_round_start()
{
	for (new id=1; id<33; id++)
	{
		if (!is_user_connected(id)) continue;
		remove_task(id+888)
		
		reset_value_player(id)
		//UNDONE Reset SPR
	}
}
public logevent_round_start()
{
	for (new id=1; id<33; id++)
	{
		if (!is_user_connected(id)) continue;
		if (is_user_bot(id))
		{
			if (task_exists(id+TASK_BOT_USE_SKILL)) remove_task(id+TASK_BOT_USE_SKILL)
			set_task(float(random_num(5,15)), "bot_use_skill", id+TASK_BOT_USE_SKILL)
		}
	}
}
public Death()
{
	new victim = read_data(2) 
	reset_value_player(victim)
}
public client_connect(id)
{
	reset_value_player(id)
}
public client_disconnect(id)
{
	reset_value_player(id)
}
reset_value_player(id)
{
	if(!nst_zb_get_take_damage())  if (task_exists(id+TASK_BOT_USE_SKILL)) remove_task(id+TASK_BOT_USE_SKILL)
	remove_task(id+888)
	//UNDONE Reset Value
	g_bat_time[id]=0
}

// bot use skill
public bot_use_skill(taskid)
{
	new id = ID_BOT_USE_SKILL
	if (!is_user_bot(id)) return;

	cmd_bat(id)
	if (task_exists(taskid)) remove_task(taskid)
	set_task(float(random_num(5,15)), "bot_use_skill", id+TASK_BOT_USE_SKILL)
}

// #################### MAIN FUNCTION ####################
public cmd_bat(id)
{
	if (!is_user_alive(id) || !nst_zb_get_take_damage()) return PLUGIN_CONTINUE

	if (idclass==nst_zb_get_user_zombie_class(id) && nst_zb_get_user_zombie(id) && !g_bat_time[id])
	{
		// check health
		/*new start_health = nst_zb_get_user_start_health(id)
		if (get_user_health(id)>=start_health) return PLUGIN_CONTINUE*/
		
		// set time wait
		g_bat_time[id]=1
		set_task(bat_timewait,"clear_stat",TASK_REMOVE_STAT+id)
		//EFFECT!!
		new ent = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"info_target"))
		if(!pev_valid(ent)) return PLUGIN_HANDLED
		
		new Float:vecAngle[3],Float:vecOrigin[3],Float:vecVelocity[3],Float:vecForward[3]
		fm_get_user_startpos(id,5.0,2.0,-1.0,vecOrigin)
		pev(id,pev_angles,vecAngle)
		
		engfunc(EngFunc_MakeVectors,vecAngle)
		global_get(glb_v_forward,vecForward)

		//xs_vec_mul_scalar(vecForward,banchee_skull_bat_speed,vecVelocity)
		velocity_by_aim(id,floatround(banchee_skull_bat_speed),vecVelocity)
		//Entity Statue
		set_pev(ent,pev_origin,vecOrigin)
		set_pev(ent,pev_angles,vecAngle)
		set_pev(ent,pev_classname,"banchee_bat")
		set_pev(ent,pev_movetype,MOVETYPE_FLY)
		set_pev(ent,pev_solid,SOLID_BBOX)
		engfunc(EngFunc_SetSize,ent,{-20.0,-15.0,-8.0},{20.0,15.0,8.0})
		new level = nst_zb_get_user_level(id)
		engfunc(EngFunc_SetModel,ent,level>1?banchee_skull_model_origin:banchee_skull_model_host)
		set_pev(ent,pev_animtime,get_gametime())
		set_pev(ent,pev_framerate,1.0) // speed :D
		set_pev(ent,pev_owner,id)
		set_pev(ent,pev_velocity,vecVelocity)
		set_pev(ent,pev_nextthink,get_gametime()+banchee_skull_bat_flytime)
		g_stop[id]=ent
		nst_wpn_send_weapon_anim(id,2)
		if(MH_IsMetaHookPlayer(id))
		{
			new class=djb_cus_ui_get_zombie_class(id)
			remove_task(id+888)
			MH_NewZBUI(id,"zbs_bat",1,1,1,2,0.0,class)
			MH_NewZBUI(id,"zbs_bat",1,4,1,2,bat_timewait,class)
		}
		
		
		
		return PLUGIN_HANDLED
	}
	
	return PLUGIN_CONTINUE
}
PlaySound(id, const sound[])
{
	client_cmd(id, "spk ^"%s^"", sound)
}
fm_set_user_health(id, health)
{
	(health > 0) ? set_pev(id, pev_health, float(health)) : dllfunc(DLLFunc_ClientKill, id);
}
// LOAD CONFIG
load_customization_from_files()
{
	// Build customization file path
	new path[64]
	get_configsdir(path, charsmax(path))
	format(path, charsmax(path), "%s/%s", path, CLASS_FILE)
	
	// File not present
	if (!file_exists(path))
	{
		new error[100]
		formatex(error, charsmax(error), "Cannot load customization file %s!", path)
		set_fail_state(error)
		return;
	}
	
	// Set up some vars to hold parsing info
	new linedata[1024], key[64], value[960], section
	
	// Open customization file for reading
	new file = fopen(path, "rt")
	
	while (file && !feof(file))
	{
		// Read one line at a time
		fgets(file, linedata, charsmax(linedata))
		
		// Replace newlines with a null character to prevent headaches
		replace(linedata, charsmax(linedata), "^n", "")
		
		// Blank line or comment
		if (!linedata[0] || linedata[0] == ';') continue;
		
		// New section starting
		if (equali(linedata, CONFIG_NAME))
		{
			section = 1
			continue;
		}
		else if (linedata[0] == '[')
		{
			if (section)
			{
				section = 0
				return;
			}
			continue;
		}
		
		if (section)
		{
			// Get key and value(s)
			strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
			
			// Trim spaces
			trim(key)
			trim(value)
			
			// set value
			if (equal(key, "NAME"))
				format(zombie_name, charsmax(zombie_name), "%s", value)
			else if (equal(key, "MODEL"))
				format(zombie_model, charsmax(zombie_model), "%s", value)
			else if (equal(key, "SET_MODEL_INDEX"))
				zombie_modelindex = str_to_num(value)
			else if (equal(key, "HEALTH"))
				zombie_health = str_to_num(value)
			else if (equal(key, "SEX"))
				zombie_sex = str_to_num(value)
			else if (equal(key, "GRAVITY"))
				zombie_gravity = str_to_float(value)
			else if (equal(key, "SPEED"))
				zombie_speed = str_to_float(value)
			else if (equal(key, "KNOCK_BACK"))
				zombie_knockback = str_to_float(value)
			else if (equal(key, "SOUND_HURT1"))
				format(zombie_sound_hurt1, charsmax(zombie_sound_hurt1), "%s", value)
			else if (equal(key, "SOUND_HURT2"))
				format(zombie_sound_hurt2, charsmax(zombie_sound_hurt2), "%s", value)
			else if (equal(key, "SOUND_DEATH1"))
				format(zombie_sound_death1, charsmax(zombie_sound_death1), "%s", value)
			else if (equal(key, "SOUND_DEATH2"))
				format(zombie_sound_death2, charsmax(zombie_sound_death2), "%s", value)
			else if (equal(key, "SOUND_EVOLUTION"))
				format(zombie_sound_evolution, charsmax(zombie_sound_evolution), "%s", value)
				
			else if (equal(key, "SKULL_BAT_SPEED"))
				banchee_skull_bat_speed = str_to_float(value)
			else if (equal(key, "SKULL_BAT_FLYTIME"))
				banchee_skull_bat_flytime = str_to_float(value)
			else if (equal(key, "SKULL_BAT_CATCH_TIME"))
				banchee_skull_bat_catch_time = str_to_float(value)
			else if (equal(key, "SKULL_BAT_CATCH_SPEED"))
				banchee_skull_bat_catch_speed = str_to_float(value)
				
			else if (equal(key, "SOUND_BAT_HIT"))
				format(zombie_sound_bat_hit, charsmax(zombie_sound_bat_hit), "%s", value)
			else if (equal(key, "SOUND_BAT_MISS"))
				format(zombie_sound_bat_miss, charsmax(zombie_sound_bat_miss), "%s", value)
			else if (equal(key, "SKULL_MODEL_HOST"))
				format(banchee_skull_model_host, charsmax(banchee_skull_model_host), "%s", value)
			else if (equal(key, "SKULL_MODEL_ORIGIN"))
				format(banchee_skull_model_origin, charsmax(banchee_skull_model_origin), "%s", value)

			else if (equal(key, "BAT_TIME_WAIT"))
				bat_timewait = str_to_float(value)

		}
		else continue;
		

	}
	if (file) fclose(file)
}
////////////////////////////////////STOCKS/////////////////////////////
stock fm_get_user_startpos(id,Float:forw,Float:right,Float:up,Float:vStart[])
{
	new Float:vOrigin[3], Float:vAngle[3], Float:vForward[3], Float:vRight[3], Float:vUp[3]
	
	pev(id, pev_origin, vOrigin)
	pev(id, pev_v_angle, vAngle)
	
	engfunc(EngFunc_MakeVectors, vAngle)
	
	global_get(glb_v_forward, vForward)
	global_get(glb_v_right, vRight)
	global_get(glb_v_up, vUp)
	
	vStart[0] = vOrigin[0] + vForward[0] * forw + vRight[0] * right + vUp[0] * up
	vStart[1] = vOrigin[1] + vForward[1] * forw + vRight[1] * right + vUp[1] * up
	vStart[2] = vOrigin[2] + vForward[2] * forw + vRight[2] * right + vUp[2] * up
}
stock aim_at_origin(id, Float:target[3], Float:angles[3])
{
	static Float:vec[3]
	pev(id,pev_origin,vec)
	vec[0] = target[0] - vec[0]
	vec[1] = target[1] - vec[1]
	vec[2] = target[2] - vec[2]
	engfunc(EngFunc_VecToAngles,vec,angles)
	angles[0] *= -1.0
	angles[2] = 0.0
}
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1033\\ f0\\ fs16 \n\\ par }
*/
