diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/c_fish.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/client/c_fish.cpp')
| -rw-r--r-- | mp/src/game/client/c_fish.cpp | 704 |
1 files changed, 352 insertions, 352 deletions
diff --git a/mp/src/game/client/c_fish.cpp b/mp/src/game/client/c_fish.cpp index 82e5a270..903080cc 100644 --- a/mp/src/game/client/c_fish.cpp +++ b/mp/src/game/client/c_fish.cpp @@ -1,352 +1,352 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-//=============================================================================//
-// c_fish.cpp
-// Simple fish client-side logic
-// Author: Michael S. Booth, April 2005
-
-#include "cbase.h"
-#include <bitbuf.h>
-#include "engine/ivdebugoverlay.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-extern float UTIL_WaterLevel( const Vector &position, float minz, float maxz );
-
-
-ConVar FishDebug( "fish_debug", "0", FCVAR_CHEAT, "Show debug info for fish" );
-
-
-//-----------------------------------------------------------------------------
-/**
- * Client-side fish entity
- */
-class C_Fish : public C_BaseAnimating
-{
-public:
- DECLARE_CLASS( C_Fish, C_BaseAnimating );
- DECLARE_CLIENTCLASS();
-
- virtual void Spawn( void );
- virtual void ClientThink();
-
- virtual void OnDataChanged( DataUpdateType_t type );
-
-private:
- friend void RecvProxy_FishOriginX( const CRecvProxyData *pData, void *pStruct, void *pOut );
- friend void RecvProxy_FishOriginY( const CRecvProxyData *pData, void *pStruct, void *pOut );
-
- Vector m_pos; ///< local position
- Vector m_vel; ///< local velocity
- QAngle m_angles; ///< local angles
-
- int m_localLifeState; ///< our version of m_lifeState
-
- float m_deathDepth; ///< water depth when we died
- float m_deathAngle; ///< angle to float at when dead
- float m_buoyancy; ///< so each fish floats at a different rate when dead
-
- CountdownTimer m_wiggleTimer; ///< for simulating swimming motions
- float m_wigglePhase; ///< where in the wiggle sinusoid we are
- float m_wiggleRate; ///< the speed of our wiggling
-
- Vector m_actualPos; ///< position from server
- QAngle m_actualAngles; ///< angles from server
-
- Vector m_poolOrigin;
- float m_waterLevel; ///< Z coordinate of water surface
-
- bool m_gotUpdate; ///< true after we have received a network update
-
- enum { MAX_ERROR_HISTORY = 20 };
- float m_errorHistory[ MAX_ERROR_HISTORY ]; ///< error history samples
- int m_errorHistoryIndex;
- int m_errorHistoryCount;
- float m_averageError;
-};
-
-
-//-----------------------------------------------------------------------------
-void RecvProxy_FishOriginX( const CRecvProxyData *pData, void *pStruct, void *pOut )
-{
- C_Fish *fish = (C_Fish *)pStruct;
- float *out = (float *)pOut;
-
- *out = pData->m_Value.m_Float + fish->m_poolOrigin.x;
-}
-
-void RecvProxy_FishOriginY( const CRecvProxyData *pData, void *pStruct, void *pOut )
-{
- C_Fish *fish = (C_Fish *)pStruct;
- float *out = (float *)pOut;
-
- *out = pData->m_Value.m_Float + fish->m_poolOrigin.y;
-}
-
-
-IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_Fish, DT_CFish, CFish )
-
- RecvPropVector( RECVINFO(m_poolOrigin) ),
-
- RecvPropFloat( RECVINFO_NAME( m_actualPos.x, m_x ), 0, RecvProxy_FishOriginX ),
- RecvPropFloat( RECVINFO_NAME( m_actualPos.y, m_y ), 0, RecvProxy_FishOriginY ),
- RecvPropFloat( RECVINFO_NAME( m_actualPos.z, m_z ) ),
-
- RecvPropFloat( RECVINFO_NAME( m_actualAngles.y, m_angle ) ),
-
- RecvPropInt( RECVINFO(m_nModelIndex) ),
- RecvPropInt( RECVINFO(m_lifeState) ),
-
- RecvPropFloat( RECVINFO(m_waterLevel) ), ///< get this from the server in case we die when slightly out of the water due to error correction
-
-END_RECV_TABLE()
-
-
-
-//-----------------------------------------------------------------------------
-void C_Fish::Spawn( void )
-{
- BaseClass::Spawn();
-
- m_angles = QAngle( 0, 0, 0 );
- m_actualAngles = m_angles;
-
- m_vel = Vector( 0, 0, 0 );
- m_gotUpdate = false;
- m_localLifeState = LIFE_ALIVE;
- m_buoyancy = RandomFloat( 0.4f, 1.0f );
-
- m_errorHistoryIndex = 0;
- m_errorHistoryCount = 0;
- m_averageError = 0.0f;
-
- SetNextClientThink( CLIENT_THINK_ALWAYS );
-}
-
-
-//-----------------------------------------------------------------------------
-void C_Fish::ClientThink()
-{
- if (FishDebug.GetBool())
- {
- debugoverlay->AddLineOverlay( m_pos, m_actualPos, 255, 0, 0, true, 0.1f );
- switch( m_localLifeState )
- {
- case LIFE_DYING:
- debugoverlay->AddTextOverlay( m_pos, 0.1f, "DYING" );
- break;
-
- case LIFE_DEAD:
- debugoverlay->AddTextOverlay( m_pos, 0.1f, "DEAD" );
- break;
- }
- }
-
- float deltaT = gpGlobals->frametime;
-
-
- // check if we just died
- if (m_localLifeState == LIFE_ALIVE && m_lifeState != LIFE_ALIVE)
- {
- // we have died
- m_localLifeState = LIFE_DYING;
-
- m_deathDepth = m_pos.z;
-
- // determine surface float angle
- m_deathAngle = RandomFloat( 87.0f, 93.0f ) * ((RandomInt( 0, 100 ) < 50) ? 1.0f : -1.0f);
- }
-
-
- switch( m_localLifeState )
- {
- case LIFE_DYING:
- {
- // depth parameter
- float t = (m_pos.z - m_deathDepth) / (m_waterLevel - m_deathDepth);
- t *= t;
-
- // roll onto side
- m_angles.z = m_deathAngle * t;
-
- // float to surface
- const float fudge = 2.0f;
- if (m_pos.z < m_waterLevel - fudge)
- {
- m_vel.z += (1.0f - t) * m_buoyancy * deltaT;
- }
- else
- {
- m_localLifeState = LIFE_DEAD;
- }
-
- break;
- }
-
- case LIFE_DEAD:
- {
- // depth parameter
- float t = (m_pos.z - m_deathDepth) / (m_waterLevel - m_deathDepth);
- t *= t;
-
- // roll onto side
- m_angles.z = m_deathAngle * t;
-
- // keep near water surface
- const float sub = 0.5f;
- m_vel.z += 10.0f * (m_waterLevel - m_pos.z - sub) * deltaT;
-
- // bob on surface
- const float rollAmp = 5.0f;
- const float rollFreq = 2.33f;
- m_angles.z += rollAmp * sin( rollFreq * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
-
- const float rollAmp2 = 7.0f;
- const float rollFreq2 = 4.0f;
- m_angles.x += rollAmp2 * sin( rollFreq2 * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
-
- const float bobAmp = 0.75f;
- const float bobFreq = 4.0f;
- m_vel.z += bobAmp * sin( bobFreq * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
-
- const float bobAmp2 = 0.75f;
- const float bobFreq2 = 3.333f;
- m_vel.z += bobAmp2 * sin( bobFreq2 * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
-
- // decay movement speed to zero
- const float drag = 1.0f;
- m_vel.z -= drag * m_vel.z * deltaT;
-
- break;
- }
-
- case LIFE_ALIVE:
- {
- // use server-side Z coordinate directly
- m_pos.z = m_actualPos.z;
-
- // use server-side angles
- m_angles = m_actualAngles;
-
- // fishy wiggle based on movement
- if (!m_wiggleTimer.IsElapsed())
- {
- float swimPower = 1.0f - (m_wiggleTimer.GetElapsedTime() / m_wiggleTimer.GetCountdownDuration());
- const float amp = 6.0f * swimPower;
- float wiggle = amp * sin( m_wigglePhase );
-
- m_wigglePhase += m_wiggleRate * deltaT;
-
- // wiggle decay
- const float wiggleDecay = 5.0f;
- m_wiggleRate -= wiggleDecay * deltaT;
-
- m_angles.y += wiggle;
- }
-
- break;
- }
- }
-
- // compute error between our local position and actual server position
- Vector error = m_actualPos - m_pos;
- error.z = 0.0f;
- float errorLen = error.Length();
-
- if (m_localLifeState == LIFE_ALIVE)
- {
- // if error is far above average, start swimming
- const float wiggleThreshold = 2.0f;
- if (errorLen - m_averageError > wiggleThreshold)
- {
- // if error is large, we must have started swimming
- const float swimTime = 5.0f;
- m_wiggleTimer.Start( swimTime );
-
- m_wiggleRate = 2.0f * errorLen;
-
- const float maxWiggleRate = 30.0f;
- if (m_wiggleRate > maxWiggleRate)
- {
- m_wiggleRate = maxWiggleRate;
- }
- }
-
- // update average error
- m_errorHistory[ m_errorHistoryIndex++ ] = errorLen;
- if (m_errorHistoryIndex >= MAX_ERROR_HISTORY)
- {
- m_errorHistoryIndex = 0;
- m_errorHistoryCount = MAX_ERROR_HISTORY;
- }
- else if (m_errorHistoryCount < MAX_ERROR_HISTORY)
- {
- ++m_errorHistoryCount;
- }
-
- m_averageError = 0.0f;
- if (m_errorHistoryCount)
- {
- for( int r=0; r<m_errorHistoryCount; ++r )
- {
- m_averageError += m_errorHistory[r];
- }
- m_averageError /= (float)m_errorHistoryCount;
- }
- }
-
- // keep fish motion smooth by correcting towards actual server position
- // NOTE: This only tracks XY motion
- const float maxError = 20.0f;
- float errorT = errorLen / maxError;
- if (errorT > 1.0f)
- {
- errorT = 1.0f;
- }
-
- // we want a nonlinear spring force for tracking
- errorT *= errorT;
-
- // as fish move faster, their error increases - use a stiffer spring when fast, and a weak one when slow
- const float trackRate = 0.0f + errorT * 115.0f;
- m_vel.x += trackRate * error.x * deltaT;
- m_vel.y += trackRate * error.y * deltaT;
-
- const float trackDrag = 2.0f + errorT * 6.0f;
- m_vel.x -= trackDrag * m_vel.x * deltaT;
- m_vel.y -= trackDrag * m_vel.y * deltaT;
-
-
- // euler integration
- m_pos += m_vel * deltaT;
-
- SetNetworkOrigin( m_pos );
- SetAbsOrigin( m_pos );
-
- SetNetworkAngles( m_angles );
- SetAbsAngles( m_angles );
-}
-
-
-//-----------------------------------------------------------------------------
-void C_Fish::OnDataChanged( DataUpdateType_t type )
-{
- //if (!m_gotUpdate)
-
- if (type == DATA_UPDATE_CREATED)
- {
- // initial update
- m_gotUpdate = true;
-
- m_pos = m_actualPos;
- m_vel = Vector( 0, 0, 0 );
-
- return;
- }
-}
-
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// c_fish.cpp +// Simple fish client-side logic +// Author: Michael S. Booth, April 2005 + +#include "cbase.h" +#include <bitbuf.h> +#include "engine/ivdebugoverlay.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern float UTIL_WaterLevel( const Vector &position, float minz, float maxz ); + + +ConVar FishDebug( "fish_debug", "0", FCVAR_CHEAT, "Show debug info for fish" ); + + +//----------------------------------------------------------------------------- +/** + * Client-side fish entity + */ +class C_Fish : public C_BaseAnimating +{ +public: + DECLARE_CLASS( C_Fish, C_BaseAnimating ); + DECLARE_CLIENTCLASS(); + + virtual void Spawn( void ); + virtual void ClientThink(); + + virtual void OnDataChanged( DataUpdateType_t type ); + +private: + friend void RecvProxy_FishOriginX( const CRecvProxyData *pData, void *pStruct, void *pOut ); + friend void RecvProxy_FishOriginY( const CRecvProxyData *pData, void *pStruct, void *pOut ); + + Vector m_pos; ///< local position + Vector m_vel; ///< local velocity + QAngle m_angles; ///< local angles + + int m_localLifeState; ///< our version of m_lifeState + + float m_deathDepth; ///< water depth when we died + float m_deathAngle; ///< angle to float at when dead + float m_buoyancy; ///< so each fish floats at a different rate when dead + + CountdownTimer m_wiggleTimer; ///< for simulating swimming motions + float m_wigglePhase; ///< where in the wiggle sinusoid we are + float m_wiggleRate; ///< the speed of our wiggling + + Vector m_actualPos; ///< position from server + QAngle m_actualAngles; ///< angles from server + + Vector m_poolOrigin; + float m_waterLevel; ///< Z coordinate of water surface + + bool m_gotUpdate; ///< true after we have received a network update + + enum { MAX_ERROR_HISTORY = 20 }; + float m_errorHistory[ MAX_ERROR_HISTORY ]; ///< error history samples + int m_errorHistoryIndex; + int m_errorHistoryCount; + float m_averageError; +}; + + +//----------------------------------------------------------------------------- +void RecvProxy_FishOriginX( const CRecvProxyData *pData, void *pStruct, void *pOut ) +{ + C_Fish *fish = (C_Fish *)pStruct; + float *out = (float *)pOut; + + *out = pData->m_Value.m_Float + fish->m_poolOrigin.x; +} + +void RecvProxy_FishOriginY( const CRecvProxyData *pData, void *pStruct, void *pOut ) +{ + C_Fish *fish = (C_Fish *)pStruct; + float *out = (float *)pOut; + + *out = pData->m_Value.m_Float + fish->m_poolOrigin.y; +} + + +IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_Fish, DT_CFish, CFish ) + + RecvPropVector( RECVINFO(m_poolOrigin) ), + + RecvPropFloat( RECVINFO_NAME( m_actualPos.x, m_x ), 0, RecvProxy_FishOriginX ), + RecvPropFloat( RECVINFO_NAME( m_actualPos.y, m_y ), 0, RecvProxy_FishOriginY ), + RecvPropFloat( RECVINFO_NAME( m_actualPos.z, m_z ) ), + + RecvPropFloat( RECVINFO_NAME( m_actualAngles.y, m_angle ) ), + + RecvPropInt( RECVINFO(m_nModelIndex) ), + RecvPropInt( RECVINFO(m_lifeState) ), + + RecvPropFloat( RECVINFO(m_waterLevel) ), ///< get this from the server in case we die when slightly out of the water due to error correction + +END_RECV_TABLE() + + + +//----------------------------------------------------------------------------- +void C_Fish::Spawn( void ) +{ + BaseClass::Spawn(); + + m_angles = QAngle( 0, 0, 0 ); + m_actualAngles = m_angles; + + m_vel = Vector( 0, 0, 0 ); + m_gotUpdate = false; + m_localLifeState = LIFE_ALIVE; + m_buoyancy = RandomFloat( 0.4f, 1.0f ); + + m_errorHistoryIndex = 0; + m_errorHistoryCount = 0; + m_averageError = 0.0f; + + SetNextClientThink( CLIENT_THINK_ALWAYS ); +} + + +//----------------------------------------------------------------------------- +void C_Fish::ClientThink() +{ + if (FishDebug.GetBool()) + { + debugoverlay->AddLineOverlay( m_pos, m_actualPos, 255, 0, 0, true, 0.1f ); + switch( m_localLifeState ) + { + case LIFE_DYING: + debugoverlay->AddTextOverlay( m_pos, 0.1f, "DYING" ); + break; + + case LIFE_DEAD: + debugoverlay->AddTextOverlay( m_pos, 0.1f, "DEAD" ); + break; + } + } + + float deltaT = gpGlobals->frametime; + + + // check if we just died + if (m_localLifeState == LIFE_ALIVE && m_lifeState != LIFE_ALIVE) + { + // we have died + m_localLifeState = LIFE_DYING; + + m_deathDepth = m_pos.z; + + // determine surface float angle + m_deathAngle = RandomFloat( 87.0f, 93.0f ) * ((RandomInt( 0, 100 ) < 50) ? 1.0f : -1.0f); + } + + + switch( m_localLifeState ) + { + case LIFE_DYING: + { + // depth parameter + float t = (m_pos.z - m_deathDepth) / (m_waterLevel - m_deathDepth); + t *= t; + + // roll onto side + m_angles.z = m_deathAngle * t; + + // float to surface + const float fudge = 2.0f; + if (m_pos.z < m_waterLevel - fudge) + { + m_vel.z += (1.0f - t) * m_buoyancy * deltaT; + } + else + { + m_localLifeState = LIFE_DEAD; + } + + break; + } + + case LIFE_DEAD: + { + // depth parameter + float t = (m_pos.z - m_deathDepth) / (m_waterLevel - m_deathDepth); + t *= t; + + // roll onto side + m_angles.z = m_deathAngle * t; + + // keep near water surface + const float sub = 0.5f; + m_vel.z += 10.0f * (m_waterLevel - m_pos.z - sub) * deltaT; + + // bob on surface + const float rollAmp = 5.0f; + const float rollFreq = 2.33f; + m_angles.z += rollAmp * sin( rollFreq * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT; + + const float rollAmp2 = 7.0f; + const float rollFreq2 = 4.0f; + m_angles.x += rollAmp2 * sin( rollFreq2 * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT; + + const float bobAmp = 0.75f; + const float bobFreq = 4.0f; + m_vel.z += bobAmp * sin( bobFreq * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT; + + const float bobAmp2 = 0.75f; + const float bobFreq2 = 3.333f; + m_vel.z += bobAmp2 * sin( bobFreq2 * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT; + + // decay movement speed to zero + const float drag = 1.0f; + m_vel.z -= drag * m_vel.z * deltaT; + + break; + } + + case LIFE_ALIVE: + { + // use server-side Z coordinate directly + m_pos.z = m_actualPos.z; + + // use server-side angles + m_angles = m_actualAngles; + + // fishy wiggle based on movement + if (!m_wiggleTimer.IsElapsed()) + { + float swimPower = 1.0f - (m_wiggleTimer.GetElapsedTime() / m_wiggleTimer.GetCountdownDuration()); + const float amp = 6.0f * swimPower; + float wiggle = amp * sin( m_wigglePhase ); + + m_wigglePhase += m_wiggleRate * deltaT; + + // wiggle decay + const float wiggleDecay = 5.0f; + m_wiggleRate -= wiggleDecay * deltaT; + + m_angles.y += wiggle; + } + + break; + } + } + + // compute error between our local position and actual server position + Vector error = m_actualPos - m_pos; + error.z = 0.0f; + float errorLen = error.Length(); + + if (m_localLifeState == LIFE_ALIVE) + { + // if error is far above average, start swimming + const float wiggleThreshold = 2.0f; + if (errorLen - m_averageError > wiggleThreshold) + { + // if error is large, we must have started swimming + const float swimTime = 5.0f; + m_wiggleTimer.Start( swimTime ); + + m_wiggleRate = 2.0f * errorLen; + + const float maxWiggleRate = 30.0f; + if (m_wiggleRate > maxWiggleRate) + { + m_wiggleRate = maxWiggleRate; + } + } + + // update average error + m_errorHistory[ m_errorHistoryIndex++ ] = errorLen; + if (m_errorHistoryIndex >= MAX_ERROR_HISTORY) + { + m_errorHistoryIndex = 0; + m_errorHistoryCount = MAX_ERROR_HISTORY; + } + else if (m_errorHistoryCount < MAX_ERROR_HISTORY) + { + ++m_errorHistoryCount; + } + + m_averageError = 0.0f; + if (m_errorHistoryCount) + { + for( int r=0; r<m_errorHistoryCount; ++r ) + { + m_averageError += m_errorHistory[r]; + } + m_averageError /= (float)m_errorHistoryCount; + } + } + + // keep fish motion smooth by correcting towards actual server position + // NOTE: This only tracks XY motion + const float maxError = 20.0f; + float errorT = errorLen / maxError; + if (errorT > 1.0f) + { + errorT = 1.0f; + } + + // we want a nonlinear spring force for tracking + errorT *= errorT; + + // as fish move faster, their error increases - use a stiffer spring when fast, and a weak one when slow + const float trackRate = 0.0f + errorT * 115.0f; + m_vel.x += trackRate * error.x * deltaT; + m_vel.y += trackRate * error.y * deltaT; + + const float trackDrag = 2.0f + errorT * 6.0f; + m_vel.x -= trackDrag * m_vel.x * deltaT; + m_vel.y -= trackDrag * m_vel.y * deltaT; + + + // euler integration + m_pos += m_vel * deltaT; + + SetNetworkOrigin( m_pos ); + SetAbsOrigin( m_pos ); + + SetNetworkAngles( m_angles ); + SetAbsAngles( m_angles ); +} + + +//----------------------------------------------------------------------------- +void C_Fish::OnDataChanged( DataUpdateType_t type ) +{ + //if (!m_gotUpdate) + + if (type == DATA_UPDATE_CREATED) + { + // initial update + m_gotUpdate = true; + + m_pos = m_actualPos; + m_vel = Vector( 0, 0, 0 ); + + return; + } +} + |