You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
270 lines
8.7 KiB
270 lines
8.7 KiB
//============================================================================= |
|
// 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ö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ü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ächsten Client finden, den der Spieler anschaut |
|
void CBasePlayer::Observer_FindNextPlayer( bool bReverse ) |
|
{ |
|
// MOD AUTOREN: Hier die Logik ä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 Überprüfungen einfü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ü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ä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ü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; |
|
} |
|
} |