#define is_zero_vec(%1) (%1[0] == 0 && %1[1] == 0 && %1[2] == 0)

new Float:VEC_NULL[3] = {0.0, 0.0, 0.0};

stock copy_vector(Float:flVec1[], Float:flVec2[])
{
	flVec2[0] = flVec1[0];
	flVec2[1] = flVec1[1];
	flVec2[2] = flVec1[2];
}

stock are_vectors_equal(Float:flVec1[], Float:flVec2[])
{
	return (flVec1[0] == flVec2[0] && flVec1[1] == flVec2[1] && flVec1[2] == flVec2[2]) ? true : false;
}

stock get_player_position(id, Float:flOrigin[3], Float:flAngles[3], &Float:flGravity)
{
	pev(id, pev_origin, flOrigin);
	pev(id, pev_v_angle, flAngles);
	pev(id, pev_gravity, flGravity);
}

stock get_player_origin(id, Float:flOrigin[3], Float:flAngles[3], &Float:flGravity, &Float:flFuser2)
{
	pev(id, pev_origin, flOrigin);
	pev(id, pev_v_angle, flAngles);
	pev(id, pev_gravity, flGravity);
	pev(id, pev_fuser2, flFuser2);
}

// for set_player_origin
new Float:VEC_DUCK_HULL_MIN[3]	= {-16.0, -16.0, -18.0 };
new Float:VEC_DUCK_HULL_MAX[3]	= { 16.0,  16.0,  32.0 };
new Float:VEC_DUCK_VIEW[3]      = { 0.0,   0.0,   12.0 };

stock set_player_origin(id, Float:flOrigin[3], Float:flAngles[3], Float:flGravity, Float:flFuser2)
{
	new iFlags = pev(id, pev_flags);
	iFlags &= ~FL_BASEVELOCITY;					// in case player was on conveyor
	iFlags |= FL_DUCKING;						// prevent stuck
	set_pev(id, pev_flags, iFlags);

	engfunc(EngFunc_SetSize, id, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX);	// prevent stuck
	engfunc(EngFunc_SetOrigin, id, flOrigin);
	set_pev(id, pev_view_ofs, VEC_DUCK_VIEW);


	set_pev(id, pev_velocity, VEC_NULL);		// reset speed
	set_pev(id, pev_basevelocity, VEC_NULL);	// reset speed
	if(flGravity > 0.0)
		set_pev(id, pev_gravity, flGravity);
	set_pev(id, pev_fuser2, flFuser2);

	if(!is_zero_vec(flAngles))
	{
		set_pev(id, pev_v_angle, VEC_NULL);		// reset v_angle so it will match angles
		set_pev(id, pev_angles, flAngles);		// set view
		set_pev(id, pev_punchangle, VEC_NULL);	// reset
		set_pev(id, pev_fixangle, 1);			// update v_angle (and angles?)
	}
}

stock register_cmd(command[], function[], flags = -1, info[] = "")
{
	new szTemp[64];

	formatex(szTemp, charsmax(szTemp), "say /%s", command);
	register_clcmd(szTemp, function, flags, info);

	formatex(szTemp, charsmax(szTemp), "say .%s", command);
	register_clcmd(szTemp, function, flags, info);

	formatex(szTemp, charsmax(szTemp), "say_team /%s", command);
	register_clcmd(szTemp, function, flags, info);

	formatex(szTemp, charsmax(szTemp), "say_team .%s", command);
	register_clcmd(szTemp, function, flags, info);

	formatex(szTemp, charsmax(szTemp), "/%s", command);
	register_clcmd(szTemp, function, flags, info);

	formatex(szTemp, charsmax(szTemp), ".%s", command);
	register_clcmd(szTemp, function, flags, info);
}

stock register_saycmd(command[], function[], flags = -1, info[] = "")
{
	new szTemp[64];

	formatex(szTemp, charsmax(szTemp), "say /%s", command);
	register_clcmd(szTemp, function, flags, info);

	formatex(szTemp, charsmax(szTemp), "say .%s", command);
	register_clcmd(szTemp, function, flags, info);

	formatex(szTemp, charsmax(szTemp), "say_team /%s", command);
	register_clcmd(szTemp, function, flags, info);

	formatex(szTemp, charsmax(szTemp), "say_team .%s", command);
	register_clcmd(szTemp, function, flags, info);
}

stock send_cmd(id, text[])
{
	message_begin(MSG_ONE, 51, _, id);
	write_byte(strlen(text) + 2);
	write_byte(10);
	write_string(text);
	message_end();
}

// Weapons

stock ham_give_weapon_by_name(id, weapon[])
{
	if(!equal(weapon, "weapon_", 7))
		return 0;

	new wEnt = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, weapon));
	if(!pev_valid(wEnt))
		return 0;

	set_pev(wEnt,pev_spawnflags, SF_NORESPAWN);
	dllfunc(DLLFunc_Spawn, wEnt);

	if(!ExecuteHamB(Ham_AddPlayerItem, id, wEnt))
	{
		if(pev_valid(wEnt))
			set_pev(wEnt,pev_flags, pev(wEnt,pev_flags) | FL_KILLME);
		return 0;
	}

	ExecuteHamB(Ham_Item_AttachToPlayer, wEnt, id);
	return 1;
}

stock ham_strip_weapon_by_name(id, weapon[])
{
	if(!equal(weapon, "weapon_", 7))
		return 0;

	new wId = get_weaponid(weapon);
	if(!wId)
		return 0;

	new wEnt;
	while((wEnt = engfunc(EngFunc_FindEntityByString, wEnt, "classname", weapon)) && pev(wEnt, pev_owner) != id) {}
	if(!wEnt)
		return 0;

	if(get_user_weapon(id) == wId)
		ExecuteHamB(Ham_Weapon_RetireWeapon, wEnt);

	if(!ExecuteHamB(Ham_RemovePlayerItem, id, wEnt))
		return 0;
	ExecuteHamB(Ham_Item_Kill, wEnt);

	set_pev(id, pev_weapons, pev(id,pev_weapons) & ~(1<<wId));

	return 1;
}

// Removing entity

stock delete_ent_by_class(classname[])
{
	new ent = find_ent_by_class(ent, classname);

	while (ent)
	{
		remove_entity(ent);
		ent = find_ent_by_class(ent, classname);
	}
}

stock is_player_sliding(id)
{
	if(!is_user_alive(id))
		return 0;

	new flags = entity_get_int(id, EV_INT_flags);
	if(flags & FL_ONGROUND)
		return 0;

	new Float:origin[3], Float:dest[3];
	pev(id, pev_origin, origin);

	dest[0] = origin[0];
	dest[1] = origin[1];
	dest[2] = origin[2] - 1.0;

	new ptr = create_tr2();
	engfunc(EngFunc_TraceHull, origin, dest, 0, flags & FL_DUCKING ? HULL_HEAD : HULL_HUMAN, id, ptr);
	new Float:flFraction;
	get_tr2(ptr, TR_flFraction, flFraction);
	if( flFraction >= 1.0 )
	{
		free_tr2(ptr);
		return 0;
	}

	get_tr2(ptr, TR_vecPlaneNormal, dest);
	free_tr2(ptr);

	return dest[2] <= 0.7;
}

stock SendAudio(id, audio[], pitch)
{
	static msg_send_audio; if(!msg_send_audio) msg_send_audio = get_user_msgid("SendAudio");

	message_begin( id ? MSG_ONE_UNRELIABLE : MSG_BROADCAST, msg_send_audio, _, id);
	write_byte(id);
	write_string(audio);
	write_short(pitch);
	message_end();
}


stock bool:is_user_steam(id)
{
    static dp_pointer;
    if(dp_pointer || (dp_pointer = get_cvar_pointer("dp_r_id_provider")))
    {
        server_cmd("dp_clientinfo %d", id);
        server_exec();
        return (get_pcvar_num(dp_pointer) == 2) ? true : false;
    }
    return false;
}
