|
|
|
|
//=============================================================================
|
|
|
|
|
// observer.cpp
|
|
|
|
|
//
|
|
|
|
|
#include "extdll.h"
|
|
|
|
|
#include "util.h"
|
|
|
|
|
#include "cbase.h"
|
|
|
|
|
#include "player.h"
|
|
|
|
|
#include "weapons.h"
|
|
|
|
|
|
|
|
|
|
extern int gmsgCurWeapon;
|
|
|
|
|
extern int gmsgSetFOV;
|
|
|
|
|
extern int gmsgTeamInfo;
|
|
|
|
|
extern int gmsgSpectator;
|
|
|
|
|
|
|
|
|
|
// Spieler wurde zum Spectator, erstmal alles einrichten
|
|
|
|
|
// Dies wurde von der player.cpp hierher verschoben.
|
|
|
|
|
void CBasePlayer::StartObserver( Vector vecPosition, Vector vecViewAngle )
|
|
|
|
|
{
|
|
|
|
|
// Alle Client-Side-Entities, die dem Spieler
|
|
|
|
|
// zugewiesen wurden, abschalten
|
|
|
|
|
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
|
|
|
|
|
WRITE_BYTE( TE_KILLPLAYERATTACHMENTS );
|
|
|
|
|
WRITE_BYTE( (BYTE)entindex() );
|
|
|
|
|
MESSAGE_END();
|
|
|
|
|
|
|
|
|
|
// Alle Waffen wegstecken
|
|
|
|
|
if (m_pActiveItem)
|
|
|
|
|
m_pActiveItem->Holster( );
|
|
|
|
|
|
|
|
|
|
if ( m_pTank != NULL )
|
|
|
|
|
{
|
|
|
|
|
m_pTank->Use( this, this, USE_OFF, 0 );
|
|
|
|
|
m_pTank = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Message Cache des Anzugs l<EFBFBD>schen,
|
|
|
|
|
// damit wir nicht weiterlabern ;-)
|
|
|
|
|
SetSuitUpdate(NULL, FALSE, 0);
|
|
|
|
|
|
|
|
|
|
// Mitteilung an Ammo-HUD, dass der Spieler tot ist
|
|
|
|
|
MESSAGE_BEGIN( MSG_ONE, gmsgCurWeapon, NULL, pev );
|
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
|
WRITE_BYTE(0XFF);
|
|
|
|
|
WRITE_BYTE(0xFF);
|
|
|
|
|
MESSAGE_END();
|
|
|
|
|
|
|
|
|
|
// Zoom zur<EFBFBD>cksetzen
|
|
|
|
|
m_iFOV = m_iClientFOV = 0;
|
|
|
|
|
pev->fov = m_iFOV;
|
|
|
|
|
MESSAGE_BEGIN( MSG_ONE, gmsgSetFOV, NULL, pev );
|
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
|
MESSAGE_END();
|
|
|
|
|
|
|
|
|
|
// Ein paar Flags setzen
|
|
|
|
|
m_iHideHUD = (HIDEHUD_HEALTH | HIDEHUD_WEAPONS);
|
|
|
|
|
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_NONE;
|
|
|
|
|
ClearBits( m_afPhysicsFlags, PFLAG_DUCKING );
|
|
|
|
|
ClearBits( pev->flags, FL_DUCKING );
|
|
|
|
|
pev->deadflag = DEAD_RESPAWNABLE;
|
|
|
|
|
pev->health = 1;
|
|
|
|
|
|
|
|
|
|
// Status-Bar ausschalten
|
|
|
|
|
m_fInitHUD = TRUE;
|
|
|
|
|
|
|
|
|
|
// Team Status updaten
|
|
|
|
|
pev->team = 0;
|
|
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo );
|
|
|
|
|
WRITE_BYTE( ENTINDEX(edict()) );
|
|
|
|
|
WRITE_STRING( "" );
|
|
|
|
|
MESSAGE_END();
|
|
|
|
|
|
|
|
|
|
// Dem Spieler alles wegnehmen
|
|
|
|
|
RemoveAllItems( FALSE );
|
|
|
|
|
|
|
|
|
|
// Einen Spieler finden, den wir angucken
|
|
|
|
|
m_flNextObserverInput = 0;
|
|
|
|
|
Observer_SetMode(OBS_CHASE_LOCKED);
|
|
|
|
|
|
|
|
|
|
// Allen Clients mitteilen, dass der Spieler jetzt Spectator ist
|
|
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgSpectator );
|
|
|
|
|
WRITE_BYTE( ENTINDEX( edict() ) );
|
|
|
|
|
WRITE_BYTE( 1 );
|
|
|
|
|
MESSAGE_END();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Observermodus verlassen
|
|
|
|
|
void CBasePlayer::StopObserver( void )
|
|
|
|
|
{
|
|
|
|
|
// Spectator-Modus abschalten
|
|
|
|
|
if ( pev->iuser1 || pev->iuser2 )
|
|
|
|
|
{
|
|
|
|
|
// Allen Clients mitteilen, dass der Spieler kein Spectator
|
|
|
|
|
// mehr ist.
|
|
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgSpectator );
|
|
|
|
|
WRITE_BYTE( ENTINDEX( edict() ) );
|
|
|
|
|
WRITE_BYTE( 0 );
|
|
|
|
|
MESSAGE_END();
|
|
|
|
|
|
|
|
|
|
pev->iuser1 = pev->iuser2 = 0;
|
|
|
|
|
m_iHideHUD &= ~(HIDEHUD_HEALTH | HIDEHUD_WEAPONS);
|
|
|
|
|
m_hObserverTarget = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Den n<EFBFBD>chsten Client finden, den der Spieler anschaut
|
|
|
|
|
void CBasePlayer::Observer_FindNextPlayer( bool bReverse )
|
|
|
|
|
{
|
|
|
|
|
// MOD AUTOREN: Hier die Logik <EFBFBD>ndern, wenn ihr den Observer nur
|
|
|
|
|
// bestimmte Spieler beobachten lassen wollt, beispielsweise
|
|
|
|
|
// nur Teammitglieder.
|
|
|
|
|
|
|
|
|
|
int iStart;
|
|
|
|
|
if ( m_hObserverTarget )
|
|
|
|
|
iStart = ENTINDEX( m_hObserverTarget->edict() );
|
|
|
|
|
else
|
|
|
|
|
iStart = ENTINDEX( edict() );
|
|
|
|
|
int iCurrent = iStart;
|
|
|
|
|
m_hObserverTarget = NULL;
|
|
|
|
|
int iDir = bReverse ? -1 : 1;
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
iCurrent += iDir;
|
|
|
|
|
|
|
|
|
|
// Durch alle Clients loopen
|
|
|
|
|
if (iCurrent > gpGlobals->maxClients)
|
|
|
|
|
iCurrent = 1;
|
|
|
|
|
if (iCurrent < 1)
|
|
|
|
|
iCurrent = gpGlobals->maxClients;
|
|
|
|
|
|
|
|
|
|
CBaseEntity *pEnt = UTIL_PlayerByIndex( iCurrent );
|
|
|
|
|
if ( !pEnt )
|
|
|
|
|
continue;
|
|
|
|
|
if ( pEnt == this )
|
|
|
|
|
continue;
|
|
|
|
|
// Keine unsichtbaren Spieler oder andere Observer beobachten
|
|
|
|
|
if ( ((CBasePlayer*)pEnt)->IsObserver() || (pEnt->pev->effects & EF_NODRAW) )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// MOD AUTOREN: Hier die <EFBFBD>berpr<EFBFBD>fungen einf<EFBFBD>gen
|
|
|
|
|
|
|
|
|
|
m_hObserverTarget = pEnt;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
} while ( iCurrent != iStart );
|
|
|
|
|
|
|
|
|
|
// Ziel gefunden?
|
|
|
|
|
if ( m_hObserverTarget )
|
|
|
|
|
{
|
|
|
|
|
// Ziel in pev speichern damit die Bewegungs-DLL dran kommt
|
|
|
|
|
pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
|
|
|
|
|
|
|
|
|
|
ALERT( at_console, "Now Tracking %s\n", STRING( m_hObserverTarget->pev->netname ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ALERT( at_console, "No observer targets.\n" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tastatur-Eingaben f<EFBFBD>r den Observermodus...
|
|
|
|
|
void CBasePlayer::Observer_HandleButtons()
|
|
|
|
|
{
|
|
|
|
|
// Mouse-Clicks verlangsamen
|
|
|
|
|
if ( m_flNextObserverInput > gpGlobals->time )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Springen wechselt zwischen den Modi
|
|
|
|
|
if ( m_afButtonPressed & IN_JUMP )
|
|
|
|
|
{
|
|
|
|
|
if ( pev->iuser1 == OBS_ROAMING )
|
|
|
|
|
Observer_SetMode( OBS_CHASE_LOCKED );
|
|
|
|
|
else if ( pev->iuser1 == OBS_CHASE_LOCKED )
|
|
|
|
|
Observer_SetMode( OBS_CHASE_FREE );
|
|
|
|
|
else
|
|
|
|
|
Observer_SetMode( OBS_ROAMING );
|
|
|
|
|
|
|
|
|
|
m_flNextObserverInput = gpGlobals->time + 0.2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Attack wechselt zum n<EFBFBD>chsten Spieler
|
|
|
|
|
if ( m_afButtonPressed & IN_ATTACK && pev->iuser1 != OBS_ROAMING )
|
|
|
|
|
{
|
|
|
|
|
Observer_FindNextPlayer( false );
|
|
|
|
|
|
|
|
|
|
m_flNextObserverInput = gpGlobals->time + 0.2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Attack2 wechselt zum vorherigen Spieler
|
|
|
|
|
if ( m_afButtonPressed & IN_ATTACK2 && pev->iuser1 != OBS_ROAMING )
|
|
|
|
|
{
|
|
|
|
|
Observer_FindNextPlayer( true );
|
|
|
|
|
|
|
|
|
|
m_flNextObserverInput = gpGlobals->time + 0.2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Versuche, Observer-Modus zu wechseln
|
|
|
|
|
void CBasePlayer::Observer_SetMode( int iMode )
|
|
|
|
|
{
|
|
|
|
|
// Abbrechen, wenn wir bereits im gew<EFBFBD>nschten Modus sind
|
|
|
|
|
if ( iMode == pev->iuser1 )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Wechsle zu Roaming?
|
|
|
|
|
if ( iMode == OBS_ROAMING )
|
|
|
|
|
{
|
|
|
|
|
// MOD AUTOREN: Wenn ihr kein Roaming-Modus in eurem Mod wollt,
|
|
|
|
|
// dann brecht hier einfach ab
|
|
|
|
|
pev->iuser1 = OBS_ROAMING;
|
|
|
|
|
pev->iuser2 = 0;
|
|
|
|
|
|
|
|
|
|
ClientPrint( pev, HUD_PRINTCENTER, "#Spec_Mode3" );
|
|
|
|
|
pev->maxspeed = 320;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wechsle zu ChaseLock?
|
|
|
|
|
if ( iMode == OBS_CHASE_LOCKED )
|
|
|
|
|
{
|
|
|
|
|
// Sicherstellen, dass wir ein Ziel haben
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wechsle zu ChaseFree?
|
|
|
|
|
if ( iMode == OBS_CHASE_FREE )
|
|
|
|
|
{
|
|
|
|
|
// Sicherstellen, dass wir ein Ziel haben
|
|
|
|
|
if ( m_hObserverTarget == NULL )
|
|
|
|
|
Observer_FindNextPlayer( false );
|
|
|
|
|
|
|
|
|
|
if (m_hObserverTarget)
|
|
|
|
|
{
|
|
|
|
|
pev->iuser1 = OBS_CHASE_FREE;
|
|
|
|
|
pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
|
|
|
|
|
ClientPrint( pev, HUD_PRINTCENTER, "#Spec_Mode2" );
|
|
|
|
|
pev->maxspeed = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ClientPrint( pev, HUD_PRINTCENTER, "#Spec_NoTarget" );
|
|
|
|
|
Observer_SetMode(OBS_ROAMING);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|