517 lines
12 KiB
C++
517 lines
12 KiB
C++
/***
|
|
*
|
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
|
*
|
|
* This product contains software technology licensed from Id
|
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
* Use, distribution, and modification of this source code and/or resulting
|
|
* object code is restricted to non-commercial enhancements to products from
|
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
|
* without written permission from Valve LLC.
|
|
*
|
|
****/
|
|
|
|
#include "stdafx.h"
|
|
#include "cbase.h"
|
|
#include "player.h"
|
|
#include "weapons.h"
|
|
#include "game.h"
|
|
#include "pm_shared.h"
|
|
|
|
#ifndef min
|
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
|
#endif
|
|
#ifndef max
|
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
extern int gmsgCrosshair;
|
|
extern int gmsgCurWeapon;
|
|
extern int gmsgStatusIcon;
|
|
extern int gmsgSetFOV;
|
|
extern int gmsgSpecHealth2;
|
|
extern int gmsgNVGToggle;
|
|
|
|
int GetForceCamera(void)
|
|
{
|
|
int retVal;
|
|
|
|
if (!fadetoblack.value)
|
|
{
|
|
retVal = (int)CVAR_GET_FLOAT("mp_forcechasecam");
|
|
|
|
if (retVal == FORCECAMERA_SPECTATE_ANYONE)
|
|
retVal = (int)CVAR_GET_FLOAT("mp_forcecamera");
|
|
}
|
|
else
|
|
retVal = FORCECAMERA_ONLY_FRIST_PERSON;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
CBaseEntity *CBasePlayer::Observer_IsValidTarget(int iTarget, bool bOnlyTeam)
|
|
{
|
|
if (iTarget > gpGlobals->maxClients || iTarget < 1)
|
|
return NULL;
|
|
|
|
CBasePlayer *pEnt = (CBasePlayer *)UTIL_PlayerByIndex(iTarget);
|
|
|
|
if (!pEnt || pEnt == this || pEnt->has_disconnected || pEnt->IsObserver() || (pEnt->pev->effects & EF_NODRAW) || pEnt->m_iTeam == TEAM_UNASSIGNED || (bOnlyTeam && pEnt->m_iTeam != m_iTeam))
|
|
return NULL;
|
|
|
|
return pEnt;
|
|
}
|
|
|
|
void UpdateClientEffects(CBasePlayer *pObserver, int oldMode);
|
|
|
|
void CBasePlayer::Observer_FindNextPlayer(bool bReverse, char *name)
|
|
{
|
|
int iStart;
|
|
int iCurrent;
|
|
int iDir;
|
|
bool bForceSameTeam;
|
|
CBasePlayer *pPlayer;
|
|
|
|
if (m_flNextFollowTime && gpGlobals->time < m_flNextFollowTime)
|
|
return;
|
|
|
|
m_flNextFollowTime = gpGlobals->time + 0.25;
|
|
|
|
iStart = m_hObserverTarget ? ENTINDEX(m_hObserverTarget->edict()) : ENTINDEX(edict());
|
|
iCurrent = iStart;
|
|
|
|
m_hObserverTarget = NULL;
|
|
|
|
iDir = bReverse ? -1 : 1;
|
|
bForceSameTeam = (GetForceCamera() != FORCECAMERA_SPECTATE_ANYONE && m_iTeam != TEAM_SPECTATOR);
|
|
|
|
do
|
|
{
|
|
iCurrent += iDir;
|
|
|
|
if (iCurrent > gpGlobals->maxClients)
|
|
iCurrent = 1;
|
|
else if (iCurrent < 1)
|
|
iCurrent = gpGlobals->maxClients;
|
|
|
|
m_hObserverTarget = Observer_IsValidTarget(iCurrent, bForceSameTeam);
|
|
|
|
if (m_hObserverTarget)
|
|
{
|
|
if (!name)
|
|
break;
|
|
|
|
pPlayer = (CBasePlayer *)UTIL_PlayerByIndex(ENTINDEX(m_hObserverTarget->edict()));
|
|
|
|
if (!strcmp(name, STRING(pPlayer->pev->netname)))
|
|
break;
|
|
}
|
|
}
|
|
while (iCurrent != iStart);
|
|
|
|
if (m_hObserverTarget)
|
|
{
|
|
UTIL_SetOrigin(pev, m_hObserverTarget->pev->origin);
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgSpecHealth2, NULL, pev);
|
|
WRITE_BYTE(min(0, m_hObserverTarget->pev->health));
|
|
WRITE_BYTE(ENTINDEX(m_hObserverTarget->edict()));
|
|
MESSAGE_END();
|
|
|
|
if (pev->iuser1 != OBS_ROAMING)
|
|
pev->iuser2 = ENTINDEX(m_hObserverTarget->edict());
|
|
|
|
UpdateClientEffects(this, pev->iuser1);
|
|
}
|
|
}
|
|
|
|
void UpdateClientEffects(CBasePlayer *pObserver, int oldMode)
|
|
{
|
|
bool clearProgress = false;
|
|
bool clearBlindness = false;
|
|
bool blindnessOk = fadetoblack.value == 0 ? true : false;
|
|
bool clearNightvision = false;
|
|
|
|
if (oldMode == OBS_IN_EYE && pObserver->pev->iuser1 != OBS_IN_EYE)
|
|
{
|
|
clearProgress = true;
|
|
clearBlindness = true;
|
|
clearNightvision = true;
|
|
}
|
|
|
|
if (pObserver->pev->iuser1 == OBS_IN_EYE)
|
|
{
|
|
clearProgress = true;
|
|
clearBlindness = true;
|
|
clearNightvision = true;
|
|
|
|
if (pObserver->m_hObserverTarget->IsPlayer())
|
|
{
|
|
CBasePlayer *pPlayer = (CBasePlayer *)UTIL_PlayerByIndex(ENTINDEX(pObserver->m_hObserverTarget->edict()));
|
|
|
|
if (pPlayer)
|
|
{
|
|
if (pPlayer->m_progressStart != 0)
|
|
{
|
|
if (pPlayer->m_progressEnd > pPlayer->m_progressStart)
|
|
{
|
|
if (pPlayer->m_progressEnd > gpGlobals->time)
|
|
{
|
|
float percentRemaining = gpGlobals->time - pPlayer->m_progressStart;
|
|
pObserver->SetProgressBarTime2(pPlayer->m_progressEnd - pPlayer->m_progressStart, percentRemaining);
|
|
clearProgress = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (blindnessOk)
|
|
{
|
|
if (pPlayer)
|
|
{
|
|
if (pPlayer->m_blindStartTime != 0)
|
|
{
|
|
if (pPlayer->m_blindFadeTime != 0)
|
|
{
|
|
float fadeTime, holdTime, alpha, ratio;
|
|
float endTime = pPlayer->m_blindFadeTime + pPlayer->m_blindHoldTime + pPlayer->m_blindStartTime;
|
|
|
|
if (endTime > gpGlobals->time)
|
|
{
|
|
clearBlindness = false;
|
|
fadeTime = pPlayer->m_blindFadeTime;
|
|
alpha = pPlayer->m_blindAlpha;
|
|
holdTime = pPlayer->m_blindHoldTime + pPlayer->m_blindStartTime - gpGlobals->time;
|
|
|
|
if (holdTime <= 0)
|
|
{
|
|
holdTime = 0;
|
|
ratio = (endTime - gpGlobals->time) / pPlayer->m_blindFadeTime;
|
|
alpha = pPlayer->m_blindAlpha * ratio;
|
|
fadeTime = ratio * fadeTime;
|
|
}
|
|
|
|
UTIL_ScreenFade(pObserver, Vector(255, 255, 255), fadeTime, holdTime, alpha, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
clearNightvision = false;
|
|
|
|
if (pPlayer->m_bNightVisionOn != pObserver->m_bNightVisionOn)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgNVGToggle, NULL, pObserver->pev);
|
|
WRITE_BYTE(pPlayer->m_bNightVisionOn != false);
|
|
MESSAGE_END();
|
|
|
|
pObserver->m_bNightVisionOn = pPlayer->m_bNightVisionOn;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (clearProgress)
|
|
pObserver->SetProgressBarTime(0);
|
|
|
|
if (blindnessOk && clearBlindness)
|
|
UTIL_ScreenFade(pObserver, Vector(0, 0, 0), 0.001, 0, 0, 0);
|
|
|
|
if (clearNightvision)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgNVGToggle, NULL, pObserver->pev);
|
|
WRITE_BYTE(0);
|
|
MESSAGE_END();
|
|
|
|
pObserver->m_bNightVisionOn = false;
|
|
}
|
|
}
|
|
|
|
void CBasePlayer::Observer_HandleButtons(void)
|
|
{
|
|
if (m_flNextObserverInput > gpGlobals->time)
|
|
return;
|
|
|
|
if (m_afButtonPressed & IN_JUMP)
|
|
{
|
|
if (pev->iuser1 == OBS_CHASE_LOCKED)
|
|
Observer_SetMode(OBS_IN_EYE);
|
|
else if (pev->iuser1 == OBS_CHASE_FREE)
|
|
Observer_SetMode(OBS_IN_EYE);
|
|
else if (pev->iuser1 == OBS_IN_EYE)
|
|
Observer_SetMode(OBS_ROAMING);
|
|
else if (pev->iuser1 == OBS_ROAMING)
|
|
Observer_SetMode(OBS_MAP_FREE);
|
|
else if (pev->iuser1 == OBS_MAP_FREE)
|
|
Observer_SetMode(OBS_MAP_CHASE);
|
|
else
|
|
Observer_SetMode(m_bObserverAutoDirector ? OBS_CHASE_LOCKED : OBS_CHASE_FREE);
|
|
|
|
m_flNextObserverInput = gpGlobals->time + 0.2;
|
|
}
|
|
|
|
if (m_afButtonPressed & IN_ATTACK)
|
|
{
|
|
Observer_FindNextPlayer(false);
|
|
m_flNextObserverInput = gpGlobals->time + 0.2;
|
|
}
|
|
|
|
if (m_afButtonPressed & IN_ATTACK2)
|
|
{
|
|
Observer_FindNextPlayer(true);
|
|
m_flNextObserverInput = gpGlobals->time + 0.2;
|
|
}
|
|
}
|
|
|
|
void CBasePlayer::Observer_CheckTarget(void)
|
|
{
|
|
int iPlayerIndex;
|
|
CBasePlayer *pEnt;
|
|
int lastMode;
|
|
|
|
if (pev->iuser1 == OBS_ROAMING && m_bWasFollowing == false)
|
|
return;
|
|
|
|
if (m_bWasFollowing == true)
|
|
{
|
|
Observer_FindNextPlayer(false);
|
|
|
|
if (m_hObserverTarget)
|
|
Observer_SetMode(m_iObserverLastMode);
|
|
|
|
return;
|
|
}
|
|
|
|
if (m_hObserverTarget == NULL)
|
|
Observer_FindNextPlayer(false);
|
|
|
|
if (m_hObserverTarget)
|
|
{
|
|
iPlayerIndex = ENTINDEX(ENT(m_hObserverTarget->pev));
|
|
pEnt = (CBasePlayer *)UTIL_PlayerByIndex(iPlayerIndex);
|
|
|
|
if (!pEnt || pEnt->pev->deadflag == DEAD_RESPAWNABLE || (pEnt->pev->effects & EF_NODRAW))
|
|
{
|
|
Observer_FindNextPlayer(false);
|
|
}
|
|
else
|
|
{
|
|
if (pEnt->pev->deadflag == DEAD_DEAD && gpGlobals->time > pEnt->m_fDeadTime + 2)
|
|
{
|
|
Observer_FindNextPlayer(false);
|
|
|
|
if (m_hObserverTarget == NULL)
|
|
{
|
|
lastMode = pev->iuser1;
|
|
Observer_SetMode(OBS_ROAMING);
|
|
m_iObserverLastMode = lastMode;
|
|
m_bWasFollowing = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lastMode = pev->iuser1;
|
|
Observer_SetMode(OBS_ROAMING);
|
|
m_iObserverLastMode = lastMode;
|
|
}
|
|
}
|
|
|
|
void CBasePlayer::Observer_CheckProperties(void)
|
|
{
|
|
if (pev->iuser1 == OBS_IN_EYE && m_hObserverTarget != NULL)
|
|
{
|
|
CBasePlayer *target = (CBasePlayer *)UTIL_PlayerByIndex(ENTINDEX(ENT(m_hObserverTarget->pev)));
|
|
|
|
if (!target)
|
|
return;
|
|
|
|
int weapon = target->m_pActiveItem ? target->m_pActiveItem->m_iId : 0;
|
|
|
|
if (m_iFOV != target->m_iFOV || m_iObserverWeapon != weapon)
|
|
{
|
|
m_iClientFOV = m_iFOV = target->m_iFOV;
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgSetFOV, NULL, pev);
|
|
WRITE_BYTE(m_iFOV);
|
|
MESSAGE_END();
|
|
|
|
m_iObserverWeapon = weapon;
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgCurWeapon, NULL, pev);
|
|
WRITE_BYTE(1);
|
|
WRITE_BYTE(m_iObserverWeapon);
|
|
WRITE_BYTE(0);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
int targetBombState = STATUSICON_HIDE;
|
|
|
|
if (target->m_bHasC4)
|
|
{
|
|
if (target->m_signals.GetState() & SIGNAL_BOMB)
|
|
targetBombState = STATUSICON_FLASH;
|
|
else
|
|
targetBombState = STATUSICON_SHOW;
|
|
}
|
|
|
|
if (m_iObserverC4State != targetBombState)
|
|
{
|
|
m_iObserverC4State = targetBombState;
|
|
|
|
if (targetBombState)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pev);
|
|
WRITE_BYTE(m_iObserverC4State);
|
|
WRITE_STRING("c4");
|
|
WRITE_BYTE(0);
|
|
WRITE_BYTE(160);
|
|
WRITE_BYTE(0);
|
|
MESSAGE_END();
|
|
}
|
|
else
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pev);
|
|
WRITE_BYTE(STATUSICON_HIDE);
|
|
WRITE_STRING("c4");
|
|
MESSAGE_END();
|
|
}
|
|
}
|
|
|
|
if (m_bObserverHasDefuser != target->m_bHasDefuser)
|
|
{
|
|
m_bObserverHasDefuser = target->m_bHasDefuser;
|
|
|
|
if (target->m_bHasDefuser)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pev);
|
|
WRITE_BYTE(STATUSICON_SHOW);
|
|
WRITE_STRING("defuser");
|
|
WRITE_BYTE(0);
|
|
WRITE_BYTE(160);
|
|
WRITE_BYTE(0);
|
|
MESSAGE_END();
|
|
}
|
|
else
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pev);
|
|
WRITE_BYTE(STATUSICON_HIDE);
|
|
WRITE_STRING("defuser");
|
|
MESSAGE_END();
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
m_iFOV = 90;
|
|
|
|
if (m_iObserverWeapon)
|
|
{
|
|
m_iObserverWeapon = 0;
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgCurWeapon, NULL, pev);
|
|
WRITE_BYTE(1);
|
|
WRITE_BYTE(m_iObserverWeapon);
|
|
WRITE_BYTE(0);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
if (m_iObserverC4State)
|
|
{
|
|
m_iObserverC4State = 0;
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pev);
|
|
WRITE_BYTE(0);
|
|
WRITE_STRING("c4");
|
|
MESSAGE_END();
|
|
}
|
|
|
|
if (m_bObserverHasDefuser)
|
|
{
|
|
m_bObserverHasDefuser = false;
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pev);
|
|
WRITE_BYTE(0);
|
|
WRITE_STRING("defuser");
|
|
MESSAGE_END();
|
|
}
|
|
}
|
|
|
|
void CBasePlayer::Observer_SetMode(int iMode)
|
|
{
|
|
int forcecamera;
|
|
int oldMode;
|
|
char modemsg[16];
|
|
|
|
if (iMode == pev->iuser1)
|
|
return;
|
|
|
|
forcecamera = GetForceCamera();
|
|
|
|
if (iMode < OBS_CHASE_LOCKED || iMode > OBS_MAP_CHASE)
|
|
iMode = OBS_IN_EYE;
|
|
|
|
oldMode = pev->iuser1;
|
|
|
|
if (m_iTeam != TEAM_SPECTATOR)
|
|
{
|
|
if (forcecamera == FORCECAMERA_SPECTATE_ONLY_TEAM)
|
|
{
|
|
if (iMode == OBS_ROAMING)
|
|
iMode = OBS_MAP_FREE;
|
|
}
|
|
else if (forcecamera == FORCECAMERA_ONLY_FRIST_PERSON)
|
|
iMode = OBS_IN_EYE;
|
|
}
|
|
|
|
if (m_hObserverTarget)
|
|
{
|
|
CBasePlayer *pEnt = (CBasePlayer *)((CBaseEntity *)m_hObserverTarget);
|
|
|
|
if (pEnt == this || !pEnt || pEnt->has_disconnected || pEnt->IsObserver() || (pEnt->pev->effects & EF_NODRAW) || (forcecamera != FORCECAMERA_SPECTATE_ANYONE && pEnt->m_iTeam != m_iTeam))
|
|
m_hObserverTarget = NULL;
|
|
}
|
|
|
|
pev->iuser1 = iMode;
|
|
|
|
if (iMode != OBS_ROAMING)
|
|
{
|
|
if (m_hObserverTarget == NULL)
|
|
{
|
|
Observer_FindNextPlayer(false);
|
|
|
|
if (m_hObserverTarget == NULL)
|
|
{
|
|
ClientPrint(pev, HUD_PRINTCENTER, "#Spec_NoTarget");
|
|
pev->iuser1 = OBS_ROAMING;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pev->iuser1 != OBS_ROAMING)
|
|
pev->iuser2 = ENTINDEX(ENT(m_hObserverTarget->pev));
|
|
else
|
|
pev->iuser2 = 0;
|
|
|
|
pev->iuser3 = 0;
|
|
|
|
if (m_hObserverTarget)
|
|
UTIL_SetOrigin(pev, m_hObserverTarget->pev->origin);
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgCrosshair, NULL, pev);
|
|
WRITE_BYTE((iMode == OBS_ROAMING) ? 1 : 0);
|
|
MESSAGE_END();
|
|
|
|
UpdateClientEffects(this, oldMode);
|
|
|
|
sprintf(modemsg, "#Spec_Mode%i", pev->iuser1);
|
|
ClientPrint(pev, HUD_PRINTCENTER, modemsg);
|
|
|
|
m_iObserverLastMode = iMode;
|
|
m_bWasFollowing = false;
|
|
}
|