// ---------------------------------------------------------------
// BubbleMod
// 
// AUTHOR
//        Tyler Lund <halflife@bubblemod.org>
//
// LICENSE                                                            
//                                                                    
//        Permission is granted to anyone to use this  software  for  
//        any purpose on any computer system, and to redistribute it  
//        in any way, subject to the following restrictions:          
//                                                                    
//        1. The author is not responsible for the  consequences  of  
//           use of this software, no matter how awful, even if they  
//           arise from defects in it.                                
//        2. The origin of this software must not be misrepresented,  
//           either by explicit claim or by omission.                 
//        3. Altered  versions  must  be plainly marked as such, and  
//           must  not  be  misrepresented  (by  explicit  claim  or  
//           omission) as being the original software.                
//        3a. It would be nice if I got  a  copy  of  your  improved  
//            version  sent to halflife@bubblemod.org. 
//        4. This notice must not be removed or altered.              
//                                                                    
// ---------------------------------------------------------------

#include	"extdll.h"
#include	"util.h"
#include	"cbase.h"
#include	"player.h"
#include	"weapons.h"
#include	"gamerules.h"

#include "BMOD_messaging.h"
#include "BMOD_CameraPoint.h"
#include "BMOD_player.h"

extern int gmsgCurWeapon;
extern int gmsgSetFOV;
extern int gmsgTeamInfo;
extern int gmsgSpectator;

extern void respawn(entvars_t *pev, BOOL fCopyCorpse);

extern cvar_t bm_spawnkilltime;
extern cvar_t bm_typekills;
extern cvar_t bm_bantime;
extern cvar_t bm_antispam;
extern cvar_t bm_spamlimit;
extern cvar_t bm_typecam;

// Player has become a spectator. Set it up.
// This was moved from player.cpp.
void CBasePlayer::StartObserver( Vector vecPosition, Vector vecViewAngle )
{
	// ??
	// clear any clientside entities attached to this player
	MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
		WRITE_BYTE( TE_KILLPLAYERATTACHMENTS );
		WRITE_BYTE( (BYTE)entindex() );
	MESSAGE_END();
	
	// Holster weapon immediately, to allow it to cleanup
	if (m_pActiveItem)
		m_pActiveItem->Holster( );

	// ?? Let go of tanks?
	if ( m_pTank != NULL )
	{
	 	m_pTank->Use( this, this, USE_OFF, 0 );
	 	m_pTank = NULL;
	}

	// clear out the suit message cache so we don't keep chattering
	SetSuitUpdate(NULL, FALSE, 0);

	// Tell Ammo Hud that the player is dead
	MESSAGE_BEGIN( MSG_ONE, gmsgCurWeapon, NULL, pev );
	 	WRITE_BYTE(0);
	 	WRITE_BYTE(0XFF);
	 	WRITE_BYTE(0xFF);
	MESSAGE_END();

	// reset FOV
	m_iFOV = 0;
	m_iClientFOV = -1;
	pev->fov = m_iFOV;
	SET_VIEW(edict(), edict());

	MESSAGE_BEGIN( MSG_ONE, gmsgSetFOV, NULL, pev );
		WRITE_BYTE(0);
	MESSAGE_END();

	// Setup flags
	m_iHideHUD = (HIDEHUD_FLASHLIGHT | HIDEHUD_WEAPONS | HIDEHUD_HEALTH);
	m_afPhysicsFlags |= PFLAG_OBSERVER;
	pev->effects |= EF_NODRAW;
	pev->view_ofs = g_vecZero;
	pev->angles = pev->v_angle = vecViewAngle;
	pev->fixangle = TRUE;
	pev->solid = SOLID_NOT;
	pev->takedamage = DAMAGE_NO;
	pev->movetype = MOVETYPE_NOCLIP;
	ClearBits( m_afPhysicsFlags, PFLAG_DUCKING );
	ClearBits( pev->flags, FL_DUCKING );
	pev->deadflag = DEAD_RESPAWNABLE;
	pev->health = 1;
	
	// Clear out the status bar
	m_fInitHUD = TRUE;

	// Update Team Status
	// pev->team = 0;

	// Remove all the player's stuff
	// RemoveAllItems( FALSE );

	// Move them to the new position
	UTIL_SetOrigin( pev, vecPosition );

	// Find a player to watch
	Observer_SetMode(OBS_ROAMING);

	// Tell all clients this player is now a spectator
	//MESSAGE_BEGIN( MSG_ALL, gmsgSpectator );  
	//	WRITE_BYTE( ENTINDEX( edict() ) );
	//	WRITE_BYTE( 1 );
	//MESSAGE_END();

	 //MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo );
	 //	WRITE_BYTE( ENTINDEX(edict()) );
	 //  WRITE_STRING( "" );
	 //MESSAGE_END();

	 m_fMsgTimer = gpGlobals->time + .5;
	 m_bSentMsg = FALSE;
}

// Leave observer mode
void CBasePlayer::StopObserver( void )
{
	// Turn off spectator
	if ( pev->iuser1 || pev->iuser2 )
	{
		// Tell all clients this player is not a spectator anymore
		//MESSAGE_BEGIN( MSG_ALL, gmsgSpectator );  
		// 	WRITE_BYTE( ENTINDEX( edict() ) );
		// 	WRITE_BYTE( 0 );
		//MESSAGE_END();

		pev->iuser1 = pev->iuser2 = 0; 
		m_hObserverTarget = NULL;
		m_iHideHUD = 0;
		
		//MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo );
	 	//	WRITE_BYTE( ENTINDEX(edict()) );
	 	//	WRITE_STRING( m_szTeamName );
		//MESSAGE_END();
	}
}

// Find the next client in the game for this player to spectate
void CBasePlayer::Observer_FindNextPlayer( bool bReverse )
{

	int		iStart;
	if ( m_hObserverTarget )
		iStart = ENTINDEX( m_hObserverTarget->edict() );
	else
		iStart = ENTINDEX( edict() );
	int	    iCurrent = iStart;
	m_hObserverTarget = NULL;
	int iDir = 1; 

	do
	{
		iCurrent += iDir;

		// Loop through the clients
		if (iCurrent > gpGlobals->maxClients)
			iCurrent = 1;
		if (iCurrent < 1)
			iCurrent = gpGlobals->maxClients;

		CBaseEntity *pEnt = UTIL_PlayerByIndex( iCurrent );
		if ( !pEnt )
			continue;
		if ( pEnt == this )
			continue;
		// Don't spec observers or invisible players or defunct players
		if ( ((CBasePlayer*)pEnt)->IsObserver() 
			|| (pEnt->pev->effects & EF_NODRAW) 
			|| (STRING(pEnt->pev->netname)[0] == 0) 
			|| (!((CBasePlayer*)pEnt)->m_bIsConnected) 
			)
			continue;

		// MOD AUTHORS: Add checks on target here.

		m_hObserverTarget = pEnt;
		break;

	} while ( iCurrent != iStart );

	// Did we find a target?
	if ( m_hObserverTarget )
	{
		// Store the target in pev so the physics DLL can get to it
		pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
		// Move to the target
		UTIL_SetOrigin( pev, m_hObserverTarget->pev->origin );
		
		// ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("Chase Camera: %s\n", STRING( m_hObserverTarget->pev->netname ) ) );
		ALERT( at_console, "Now Tracking %s\n", STRING( m_hObserverTarget->pev->netname ) );
	}
	else
	{
		ALERT( at_console, "No observer targets.\n" );
	}
}

// Handle buttons in observer mode
void CBasePlayer::Observer_HandleButtons()
{
	// Slow down mouse clicks
	if ( m_fMsgTimer <= gpGlobals->time )
	{
		// Show the observer mode instructions
		if (!m_bSentMsg)
		{
			m_bSentMsg = TRUE;
			PrintMessage( this, BMOD_CHAN_INFO, Vector (20,250,20), Vector (.5, 15, 2), "SPEC");
			PrintMessage( this, BMOD_CHAN_RUNE, Vector (20,250,20), Vector (.5, 86400, 2), 
				"-Spectator Mode-\n FIRE=Spawn   JUMP=Switch Modes   ALT FIRE=Switch Targets");
		}

		// Check to see if the observer wants to spray their logo
		if (pev->impulse == 201) {
			ImpulseCommands();
		}

		// Jump changes modes: Chase to Roaming
		if ( pev->button & IN_JUMP )
		{
			if ( pev->iuser1 == OBS_ROAMING )
				Observer_SetMode( OBS_CHASE_FREE );
			else
				Observer_SetMode( OBS_ROAMING );
			m_fMsgTimer = gpGlobals->time + 0.2;
		}

		// Attack2 cycles player targets
		if ( pev->button & IN_ATTACK2 && pev->iuser1 != OBS_ROAMING )
		{
			Observer_FindNextPlayer( false );
			m_fMsgTimer = gpGlobals->time + 0.2;
		}

		// Attack Spawns
		// if ( m_afButtonPressed & IN_ATTACK && pev->iuser1 != OBS_ROAMING )
		if ( pev->button & IN_ATTACK )
		{
//			g_engfuncs.pfnServerPrint( "Player spawned from Obs!\n" );
			StopObserver();
			m_fMsgTimer = gpGlobals->time + 0.2;
		}		
	}

	// clear attack/use commands from player
	m_afButtonPressed = 0;
	pev->button = 0;
	m_afButtonReleased = 0;

	pev->impulse = 0;
	if ((m_hObserverTarget != NULL) && (m_hObserverTarget->IsPlayer()) && (pev->iuser1 == OBS_CHASE_FREE))
	{
		pev->origin = m_hObserverTarget->pev->origin;
		pev->velocity = m_hObserverTarget->pev->velocity;
	}
}

// Attempt to change the observer mode
void CBasePlayer::Observer_SetMode( int iMode )
{
	// Just abort if we're changing to the mode we're already in
	if ( iMode == pev->iuser1 )
		return;

	// Changing to Roaming?
	if ( iMode == OBS_ROAMING )
	{
		// MOD AUTHORS: If you don't want to allow roaming observers at all in your mod, just abort here.
		pev->iuser1 = OBS_ROAMING;
		pev->iuser2 = 0;
		m_hObserverTarget = NULL;

		ClientPrint( pev, HUD_PRINTCENTER, "#Spec_Mode3" );
		// pev->maxspeed = 320;
		pev->maxspeed = 1000;
		return;
	}

	// Changing to Chase Lock?
	if ( iMode == OBS_CHASE_LOCKED )
	{
		// If changing from Roaming, or starting observing, make sure there is a target
		if ( m_hObserverTarget == NULL )
			Observer_FindNextPlayer( false );

		if (m_hObserverTarget)
		{
			pev->iuser1 = OBS_CHASE_LOCKED;
			pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
			ClientPrint( pev, HUD_PRINTCENTER, "#Spec_Mode1" );
			pev->maxspeed = 0;
		}
		else
		{
			ClientPrint( pev, HUD_PRINTCENTER, "#Spec_NoTarget"  );
			Observer_SetMode(OBS_ROAMING);
		}

		return;
	}

	// Changing to Chase Freelook?
	if ( iMode == OBS_CHASE_FREE )
	{
		// If changing from Roaming, or starting observing, make sure there is a target
		// if ( m_hObserverTarget == NULL )
		if ( pev->iuser1 == OBS_ROAMING )
			Observer_FindNextPlayer( false );

		if (m_hObserverTarget)
		{
			pev->iuser1 = OBS_CHASE_FREE;
			pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
			// ClientPrint( pev, HUD_PRINTCENTER, "Chase-Camera Mode" );
			pev->maxspeed = 0;
		}
		else
		{
			ClientPrint( pev, HUD_PRINTCENTER, "#Spec_NoTarget"  );
			Observer_SetMode(OBS_ROAMING);
		}
		
		return;
	}
}

void CBasePlayer::BMOD_PreThink(void)
{
	// Bubblemod freeze ray
	if (m_flFreezeTime > 0)
    {
      if (m_flFreezeTime <= gpGlobals->time)
      {
         EnableControl(TRUE);
		 // pev->movetype = MOVETYPE_WALK;
         pev->rendermode = kRenderNormal;
         pev->renderfx = kRenderFxNone;
         pev->renderamt = 0;
		 
         m_flFreezeTime = 0;
      }
      else
	  {
		pev->v_angle = m_vFreezeAngle;
        pev->fixangle = TRUE;
	  }
    }

	// Bubblemod spawn
	if (
		m_fSpawnTimeStamp &&
		m_fSpawnTimeStamp + bm_spawnkilltime.value >= gpGlobals->time &&
		m_iMessageFire
		)
	{
		PrintMessage( this, BMOD_CHAN_INFO, Vector (255,0,0), Vector (.1, bm_spawnkilltime.value, .1), 
			UTIL_VarArgs("Spawn Protection: %d seconds", (int)(m_fSpawnTimeStamp + bm_spawnkilltime.value - gpGlobals->time))
			);
	}

	if (m_fSpawnTimeStamp > 0 &&
		((m_fSpawnTimeStamp + bm_spawnkilltime.value) <= gpGlobals->time) ) {

		if (m_RuneFlags == RUNE_NONE &&
			m_flFreezeTime == 0) {
			 pev->rendermode = kRenderNormal;
			 pev->renderfx = kRenderFxNone;
			 pev->renderamt = 0;
		}
		 BMOD_ResetSpawnKill();
    }

	// Bubblemod runes
	if (m_RuneFlags && (m_RuneTime < gpGlobals->time) )
	{
		m_RuneFlags = RUNE_NONE;
		pev->rendermode = kRenderNormal;
	    pev->renderfx = kRenderFxNone;
		pev->renderamt = 0;	
	}

	// BubbleMod Type detection
	if (pev->button & ~IN_SCORE ) {
		BMOD_ResetTypeKill();
	}

	// Color the typer
	if (BMOD_IsTyping() &&
		m_iMessageFire ) {
		if (!(m_iMessageCounter % 2)) {
			//MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
			//	WRITE_BYTE( TE_SMOKE );
			//	WRITE_COORD( pev->origin.x );
			//	WRITE_COORD( pev->origin.y );
			//	WRITE_COORD( pev->origin.z - 36 );
			//	WRITE_SHORT( g_sModelIndexSmoke );
			//	WRITE_BYTE( 10 ); // scale * 10
			//	WRITE_BYTE( 10  ); // framerate
			//MESSAGE_END();
			MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
				WRITE_BYTE( TE_SPRITE );
				WRITE_COORD( pev->origin.x + RANDOM_LONG( -10, 10) );
				WRITE_COORD( pev->origin.y + RANDOM_LONG( -10, 10) );
				WRITE_COORD( pev->origin.z + RANDOM_LONG( -30, 30) );
				WRITE_SHORT( g_sModelIndexFlare );
				WRITE_BYTE( 3 ); // scale * 10
				WRITE_BYTE( 255  ); // alpha
			MESSAGE_END();
		}
		float fCos = cos( gpGlobals->time * 4.00) * 8;
		float fSin = sin( gpGlobals->time * 4.00) * 8;
        MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
                WRITE_BYTE( TE_BUBBLES );
                WRITE_COORD( pev->origin.x + fCos);  
                WRITE_COORD( pev->origin.y + fSin);
                WRITE_COORD( pev->origin.z - 36 );
                WRITE_COORD( pev->origin.x + fCos);  // mins
                WRITE_COORD( pev->origin.y + fSin);
                WRITE_COORD( pev->origin.z - 36 );
                WRITE_COORD( 75 );  // height
                WRITE_SHORT( g_sModelIndexBubbles );
                WRITE_BYTE( 3 ); // count
                WRITE_COORD( -1 ); // speed
        MESSAGE_END();

		// Away put your weapons!
		//if (m_pActiveItem) 	{
		//	ResetAutoaim( );
		//	m_pActiveItem->Holster( );
		//	m_pActiveItem = NULL;
		//}
		m_pLastItem = m_pActiveItem;

		if (!m_bTypeMode) {
			m_bTypeMode = TRUE;
			// EnableControl(FALSE);
			if (bm_typecam.value) {
				// spawn a camera above us and use that for our view.
				CCamPoint *pCam = (CCamPoint*)CBaseEntity::Create( "campoint", 
					pev->origin + Vector(0,0,40), 
					Vector(pev->angles.x + 22, pev->angles.y + 180, 0), 
					edict() );
				if (pCam) {
					pCam->m_pOwner = this;
					pCam->Think();
					// UTIL_ClientPrintAll( HUD_PRINTTALK, "<SERVER> Camera point created.\n");	
					SET_VIEW(edict(), pCam->edict());
					SET_MODEL(ENT(pCam->pev), STRING(pev->model) );
					pev->fov = m_iFOV = 140;
				}	
			}
		}
	}
}

void CBasePlayer::BMOD_Think( void )
{
	// BMOD End - Message delayer.
	// Message delayer. USE THIS for general messages to players. 
	// counts tenths of seconds. 
	if (m_fMessageTimer < gpGlobals->time) 
	{
		m_fMessageTimer = gpGlobals->time + .1;
		m_iMessageCounter++;
		m_iMessageFire = TRUE;
	}

	// Locator
	if (m_LocateMode && m_iMessageFire) {
		int yang = (int)pev->angles.y;
		if (yang < 0)
			yang += 360;

		ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("Location: %dx %dy %dz, facing %d", 
			(int)pev->origin.x,
			(int)pev->origin.y,
			(int)pev->origin.z,
			yang
			) );
	}

	// Llamas!
	if (m_IsLlama && m_iMessageFire && !(m_iMessageCounter%5)) {
		CLIENT_COMMAND(edict(), "drop\n");
	}

	// Autoban
	if (m_bBanMe && m_iMessageFire) 
	{
		char cmd[81] = "";
		sprintf( cmd, "banid %d %s kick\n", (int)bm_bantime.value, GETPLAYERAUTHID( edict() ));
		SERVER_COMMAND(cmd);
	}

	// BMOD Begin - Spam Kick
	if (m_iMessageFire && !(m_iMessageCounter%10) && m_iSpamSay)
	{
		m_iSpamSay--;
	}

	if (bm_antispam.value && m_iSpamSay > bm_spamlimit.value)
	{
		char cmd[81] = "";
		sprintf( cmd, "kick # %u\n", GETPLAYERUSERID( edict() ));
		SERVER_COMMAND(cmd);
		UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "<SERVER> %s was kicked for spamming.\n",
			STRING( pev->netname )));
		UTIL_LogPrintf( "\"SERVER<-1><-1><>\" say \"%s was was kicked for spamming.\"\n",  
			STRING( pev->netname ));
		UTIL_LogPrintf( "// \"%s<%i><%s><%s>\" was kicked for spamming.\n",  
			STRING( pev->netname ),
			GETPLAYERUSERID( edict() ),
			GETPLAYERAUTHID( edict() ),
			g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( edict() ), "model" )
			);
		m_iSpamSay = 0;
	}
	// BMOD End - Spam Kick


}

void CBasePlayer::BMOD_PostThink( void )
{

}

void CBasePlayer::BMOD_Identify( void )
{
	static float timer = gpGlobals->time;
	static CBasePlayer *LastIdentPlayer = NULL;

	TraceResult tr;

	CBasePlayer *pPlayer = GetClassPtr((CBasePlayer *)pev);

	Vector anglesAim = pPlayer->pev->v_angle;
	UTIL_MakeVectors( anglesAim );
	anglesAim.x              = -anglesAim.x;
	Vector vecSrc = pPlayer->GetGunPosition( ) - gpGlobals->v_up * 1;
	Vector vecDir = gpGlobals->v_forward;

	gpGlobals->trace_flags = FTRACE_SIMPLEBOX;
	UTIL_TraceLine(vecSrc, vecSrc + vecDir * 8192, dont_ignore_monsters, ENT(pPlayer->pev), &tr);

	CBaseEntity *pOther = CBaseEntity::Instance( tr.pHit );

	// Do we have our nose in a wall?
	if (((tr.vecEndPos - vecSrc).Length() > 40) || pOther->IsPlayer()) {
		BMOD_ResetTypeKill();
	}

	if ( pOther->IsPlayer() && 
			(
				(CBasePlayer *)pOther != LastIdentPlayer ||
				timer <= gpGlobals->time
			)
		)
	{
		char szExtra[81] = "\n";
		if (((CBasePlayer *)pOther)->BMOD_IsASpawn()) {
			strcat(szExtra, "\nFresh Spawn! DO NOT SHOOT!");
		}
		if (((CBasePlayer *)pOther)->BMOD_IsTyping()) {
			strcat(szExtra, "\nTyping! DO NOT SHOOT!");
		}

		CBasePlayer *pPlayer = (CBasePlayer *)pOther;
		if (IsObserver())
				ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("-%s-\n(%s) %i / %i%s", 
					STRING( pPlayer->pev->netname ), 
					g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" ),
					(int)pPlayer->pev->health, 
					(int)pPlayer->pev->armorvalue,
					szExtra
					) );
		else if ( g_pGameRules->PlayerRelationship( pOther, this ) == GR_TEAMMATE )
				ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("-%s-\n%i / %i", 
					STRING( pPlayer->pev->netname ), 
					(int)pPlayer->pev->health, 
					(int)pPlayer->pev->armorvalue) 
					);
		else
				ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("-%s-\n(%s)%s", 
					STRING( pPlayer->pev->netname ),
					g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" ),
					szExtra
					) );

		timer = gpGlobals->time + .5;
		LastIdentPlayer = (CBasePlayer *)pOther;
	}
	else if (!pOther->IsPlayer()) {
		LastIdentPlayer = NULL;
	}
}

int CBasePlayer::BMOD_WasSpawnKilled( void )
{
	if ( !IsAlive() && 
		m_fSpawnTimeStamp &&
		((m_fSpawnTimeStamp + bm_spawnkilltime.value) > gpGlobals->time) &&
		bm_spawnkilltime.value)
		return TRUE;
	return FALSE;
}

int CBasePlayer::BMOD_IsASpawn( void )
{
	if ( IsAlive() && 
		m_fSpawnTimeStamp &&
		((m_fSpawnTimeStamp + bm_spawnkilltime.value) > gpGlobals->time) &&
		bm_spawnkilltime.value)
		return TRUE;
	return FALSE;
}

void CBasePlayer::BMOD_ResetSpawnKill( void )
{


	if (m_RuneFlags == RUNE_NONE &&
		m_flFreezeTime == 0) {
		pev->rendermode = kRenderNormal;
		pev->renderfx = kRenderFxNone;
		pev->renderamt = 0;	
	}
	m_fSpawnTimeStamp = 0;
	PrintMessage( this, BMOD_CHAN_INFO, Vector (20,250,20), Vector (.1, 1, .1), "");
}


int CBasePlayer::BMOD_WasTypeKilled( void )
{
	if ( !IsAlive() && 
		m_flTypeKillStamp > 0 &&
		m_flTypeKillStamp < gpGlobals->time &&
		!bm_typekills.value )
		return TRUE;
	return FALSE;
}

int CBasePlayer::BMOD_IsTyping( void )
{
	if ( IsAlive() &&
		m_flTypeKillStamp &&
		m_flTypeKillStamp < gpGlobals->time &&
		!bm_typekills.value ) {

			// Do we have a crowbar?
			if (m_pActiveItem != NULL &&
				strcmp("weapon_crowbar", STRING(m_pActiveItem->pev->classname))
				) 
			{
				BMOD_ResetTypeKill();
				return FALSE;
			}

			return TRUE;
	}
	return FALSE;
}

void CBasePlayer::BMOD_ResetTypeKill( void )
{
	if ( IsAlive() ) {
		// make a sound if we are coming out of type mode.
		if (m_bTypeMode) 
		{
			EMIT_SOUND(ENT(pev), CHAN_VOICE, "fvox/alert.wav", 1.0, ATTN_NORM);
			SET_VIEW(edict(), edict());
			pev->fov = m_iFOV = 0;
		}
		m_bTypeMode = FALSE;
		// EnableControl(TRUE);
		m_flTypeKillStamp = gpGlobals->time + 4;
	}
	return;
}

