This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions
+117
View File
@@ -0,0 +1,117 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "proxyentity.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "c_baseobject.h"
#include <KeyValues.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CObjectBuildAlphaProxy : public CEntityMaterialProxy
{
public:
CObjectBuildAlphaProxy();
virtual ~CObjectBuildAlphaProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues* pKeyValues );
virtual void OnBind( C_BaseEntity *pC_BaseEntity );
private:
IMaterialVar* m_pAlphaVar;
float buildstart;
float buildend;
};
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CObjectBuildAlphaProxy::CObjectBuildAlphaProxy()
{
m_pAlphaVar = 0;
}
CObjectBuildAlphaProxy::~CObjectBuildAlphaProxy()
{
}
//-----------------------------------------------------------------------------
// Init baby...
//-----------------------------------------------------------------------------
bool CObjectBuildAlphaProxy::Init( IMaterial *pMaterial, KeyValues* pKeyValues )
{
bool foundVar;
m_pAlphaVar = pMaterial->FindVar( "$alpha", &foundVar, false );
if( !foundVar )
{
m_pAlphaVar = 0;
}
buildstart = pKeyValues->GetFloat( "buildstart", 1.0f );
buildend = pKeyValues->GetFloat( "buildfinish", 1.0f );
return true;
}
//-----------------------------------------------------------------------------
// Set the appropriate texture...
//-----------------------------------------------------------------------------
void CObjectBuildAlphaProxy::OnBind( C_BaseEntity *pEntity )
{
if( !m_pAlphaVar )
return;
// It needs to be a TF2 C_BaseObject to have this proxy applied
C_BaseObject *pObject = dynamic_cast< C_BaseObject * >( pEntity );
if ( !pObject )
return;
float build_amount = pObject->GetCycle(); //pObject->GetPercentageConstructed();
float frac;
if ( build_amount <= buildstart )
{
frac = 0.0f;
}
else if ( build_amount >= buildend )
{
frac = 1.0f;
}
else
{
// Avoid div by zero
if ( buildend == buildstart )
{
frac = 1.0f;
}
else
{
frac = ( build_amount - buildstart ) / ( buildend - buildstart );
frac = clamp( frac, 0.0f, 1.0f );
}
}
if ( !pObject->IsBuilding() )
{
frac = 1.0f;
}
m_pAlphaVar->SetFloatValue( frac );
}
EXPOSE_INTERFACE( CObjectBuildAlphaProxy, IMaterialProxy, "TFObjectBuildAlpha" IMATERIAL_PROXY_INTERFACE_VERSION );
+355
View File
@@ -0,0 +1,355 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "ObjectControlPanel.h"
#include <vgui_controls/Controls.h>
#include <vgui_controls/Label.h>
#include "vgui_bitmapbutton.h"
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
#include "C_BaseTFPlayer.h"
#include "clientmode_tfbase.h"
#include <vgui/IScheme.h>
#include <vgui_controls/Slider.h>
#include "vgui_rotation_slider.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define DISMANTLE_WAIT_TIME 5.0
//-----------------------------------------------------------------------------
// Standard VGUI panel for objects
//-----------------------------------------------------------------------------
DECLARE_VGUI_SCREEN_FACTORY( CObjectControlPanel, "object_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CObjectControlPanel::CObjectControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, panelName, g_hVGuiObjectScheme )
{
// Make some high-level panels to group stuff we want to activate/deactivate
m_pActivePanel = new CCommandChainingPanel( this, "ActivePanel" );
m_pDeterioratingPanel = new CCommandChainingPanel( this, "DeterioratingPanel" );
m_pDismantlingPanel = new CCommandChainingPanel( this, "DismantlingPanel" );
SetCursor( vgui::dc_none ); // don't draw a VGUI cursor for this panel, and for its children
// Make sure these are behind everything
m_pActivePanel->SetZPos( -1 );
m_pDeterioratingPanel->SetZPos( -1 );
m_pDismantlingPanel->SetZPos( -1 );
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CObjectControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Grab ahold of certain well-known controls
m_pHealthLabel = new vgui::Label( this, "HealthReadout", "" );
m_pOwnerLabel = new vgui::Label( this, "OwnerReadout", "" );
m_pDismantleButton = new CBitmapButton( this, "DismantleButton", "Dismantle" );
m_pAssumeControlButton = new CBitmapButton( GetDeterioratingPanel(), "AssumeControl", "" );
m_pDismantleTimeLabel = new vgui::Label( GetDismantlingPanel(), "DismantleTime", "" );
m_flDismantleTime = -1;
// Make sure we get ticked...
vgui::ivgui()->AddTickSignal( GetVPanel() );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
SetCursor( vgui::dc_none ); // don't draw a VGUI cursor for this panel, and for its children
// Make the bounds of the sub-panels match
int x, y, w, h;
GetBounds( x, y, w, h );
m_pActivePanel->SetBounds( x, y, w, h );
m_pDeterioratingPanel->SetBounds( x, y, w, h );
m_pDismantlingPanel->SetBounds( x, y, w, h );
// Make em all invisible
m_pActivePanel->SetVisible( false );
m_pDeterioratingPanel->SetVisible( false );
m_pDismantlingPanel->SetVisible( false );
m_pCurrentPanel = m_pActivePanel;
return true;
}
//-----------------------------------------------------------------------------
// Returns the object it's attached to
//-----------------------------------------------------------------------------
C_BaseObject *CObjectControlPanel::GetOwningObject() const
{
C_BaseEntity *pScreenEnt = GetEntity();
if (!pScreenEnt)
return NULL;
C_BaseEntity *pObj = pScreenEnt->GetOwnerEntity();
if (!pObj)
return NULL;
Assert( dynamic_cast<C_BaseObject*>(pObj) );
return static_cast<C_BaseObject*>(pObj);
}
//-----------------------------------------------------------------------------
// Ticks the panel when its in its various states
//-----------------------------------------------------------------------------
void CObjectControlPanel::OnTickDeteriorating( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer )
{
char buf[256];
if ( pLocalPlayer && ClassCanBuild( pLocalPlayer->PlayerClass(), pObj->GetType() ) )
{
int nCost = CalculateObjectCost( pObj->GetType(), pLocalPlayer->GetNumObjects( pObj->GetType() ), pLocalPlayer->GetTeamNumber() );
Q_snprintf( buf, sizeof( buf ), "Buy for %d", nCost );
m_pAssumeControlButton->SetText( buf );
m_pAssumeControlButton->SetVisible( true );
bool bHasEnoughResources = pLocalPlayer->GetBankResources() >= nCost;
m_pAssumeControlButton->SetEnabled( bHasEnoughResources );
}
else
{
m_pAssumeControlButton->SetVisible( false );
}
ShowDismantleButton( false );
}
void CObjectControlPanel::OnTickActive( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer )
{
ShowDismantleButton( !(pObj->GetFlags() & OF_CANNOT_BE_DISMANTLED) && pObj->GetOwner() == pLocalPlayer );
}
void CObjectControlPanel::OnTickDismantling( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer )
{
ShowDismantleButton( false );
if ( !m_bDismantled && (gpGlobals->curtime >= m_flDismantleTime))
{
Dismantle();
m_bDismantled = true;
}
int nSec = (int)(m_flDismantleTime - gpGlobals->curtime + 0.5f);
if (nSec < 0)
nSec = 0;
char buf[256];
int nLen = Q_snprintf( buf, sizeof( buf ), "%d second", nSec );
if (nSec != 1)
{
buf[nLen] = 's';
++nLen;
buf[nLen] = 0;
}
m_pDismantleTimeLabel->SetText( buf );
}
vgui::Panel* CObjectControlPanel::TickCurrentPanel()
{
C_BaseTFPlayer *pLocalPlayer = C_BaseTFPlayer::GetLocalPlayer();
C_BaseObject *pObj = GetOwningObject();
if (IsDismantling())
{
m_pCurrentPanel = GetDismantlingPanel();
OnTickDismantling(pObj, pLocalPlayer);
}
else if (pObj->IsDeteriorating())
{
m_pCurrentPanel = GetDeterioratingPanel();
OnTickDeteriorating(pObj, pLocalPlayer);
}
else
{
m_pCurrentPanel = GetActivePanel();
OnTickActive(pObj, pLocalPlayer);
}
return m_pCurrentPanel;
}
void CObjectControlPanel::ShowDismantleButton( bool bShow )
{
m_pDismantleButton->SetVisible( bShow );
}
void CObjectControlPanel::ShowOwnerLabel( bool bShow )
{
m_pOwnerLabel->SetVisible( bShow );
}
void CObjectControlPanel::ShowHealthLabel( bool bShow )
{
m_pHealthLabel->SetVisible( bShow );
}
void CObjectControlPanel::SendToServerObject( const char *pMsg )
{
C_BaseObject *pObj = GetOwningObject();
if (pObj)
{
pObj->SendClientCommand( pMsg );
}
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CObjectControlPanel::OnTick()
{
BaseClass::OnTick();
C_BaseObject *pObj = GetOwningObject();
if (!pObj)
return;
char buf[256];
Q_snprintf( buf, sizeof( buf ), "Health: %d%%", (int)(pObj->HealthFraction() * 100.0f) );
m_pHealthLabel->SetText( buf );
C_BaseTFPlayer *pPlayer = pObj->GetOwner();
if (pPlayer)
{
Q_snprintf( buf, sizeof( buf ), "Owner: %s", pPlayer->GetPlayerName() );
}
else
{
Q_snprintf( buf, sizeof( buf ), "No Owner" );
}
m_pOwnerLabel->SetText( buf );
// Update the current subpanel
m_pCurrentPanel->SetVisible( false );
m_pCurrentPanel = TickCurrentPanel();
m_pCurrentPanel->SetVisible( true );
}
//-----------------------------------------------------------------------------
// Dismantles the object
//-----------------------------------------------------------------------------
void CObjectControlPanel::Dismantle()
{
SendToServerObject( "dismantle" );
}
//-----------------------------------------------------------------------------
// Starts/stops dismantling
//-----------------------------------------------------------------------------
void CObjectControlPanel::StartDismantling()
{
m_flDismantleTime = gpGlobals->curtime + DISMANTLE_WAIT_TIME;
m_bDismantled = false;
}
void CObjectControlPanel::StopDismantling()
{
m_flDismantleTime = -1.0f;
}
bool CObjectControlPanel::IsDismantling() const
{
return m_flDismantleTime >= 0.0f;
}
//-----------------------------------------------------------------------------
// Assumes control of the object
//-----------------------------------------------------------------------------
void CObjectControlPanel::AssumeControl()
{
SendToServerObject( "takecontrol" );
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CObjectControlPanel::OnCommand( const char *command )
{
if (!Q_strnicmp(command, "Dismantle", 10))
{
StartDismantling();
return;
}
if (!Q_strnicmp(command, "CancelDismantle", 20))
{
StopDismantling();
return;
}
if (!Q_strnicmp(command, "AssumeControl", 15))
{
AssumeControl();
return;
}
BaseClass::OnCommand(command);
}
DECLARE_VGUI_SCREEN_FACTORY( CRotatingObjectControlPanel, "rotating_object_control_panel" );
//-----------------------------------------------------------------------------
// This is a panel for an object that has rotational controls
//-----------------------------------------------------------------------------
CRotatingObjectControlPanel::CRotatingObjectControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, panelName )
{
}
bool CRotatingObjectControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Grab ahold of certain well-known controls
m_pRotationSlider = new CRotationSlider( GetActivePanel(), "RotationSlider" );
m_pRotationLabel = new vgui::Label( GetActivePanel(), "RotationLabel", "Rotation Control" );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
m_pRotationSlider->SetControlledObject( GetOwningObject() );
return true;
}
void CRotatingObjectControlPanel::OnTickActive( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer )
{
BaseClass::OnTickActive( pObj, pLocalPlayer );
bool bEnable = (pObj->GetOwner() == pLocalPlayer);
m_pRotationSlider->SetVisible( bEnable );
m_pRotationLabel->SetVisible( bEnable );
}
+135
View File
@@ -0,0 +1,135 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Clients CBaseObject
//
// $NoKeywords: $
//=============================================================================//
#ifndef OBJECTCONTROLPANEL_H
#define OBJECTCONTROLPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "c_vguiscreen.h"
namespace vgui
{
class Panel;
class Label;
class Button;
}
class C_BaseObject;
class CRotationSlider;
class C_BaseTFPlayer;
//-----------------------------------------------------------------------------
// Base class for all vgui screens on objects:
//-----------------------------------------------------------------------------
class CObjectControlPanel : public CVGuiScreenPanel
{
DECLARE_CLASS( CObjectControlPanel, CVGuiScreenPanel );
public:
CObjectControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnCommand( const char *command );
virtual void OnTick();
protected:
// Method to add controls to particular panels
vgui::Panel *GetActivePanel() { return m_pActivePanel; }
vgui::Panel *GetDeterioratingPanel() { return m_pDeterioratingPanel; }
vgui::Panel *GetDismantlingPanel() { return m_pDismantlingPanel; }
// Override these to deal with various controls in various modes
virtual void OnTickDeteriorating( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer );
virtual void OnTickActive( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer );
virtual void OnTickDismantling( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer );
C_BaseObject *GetOwningObject() const;
// This should update the current panel and return that panel.
virtual vgui::Panel* TickCurrentPanel();
// The dismantle button has its own logic about whether or not to hide itself.
// Use this to make it go away.
void ShowDismantleButton( bool bShow );
void ShowOwnerLabel( bool bShow );
void ShowHealthLabel( bool bShow );
// Send a message to the owner.
void SendToServerObject( const char *pMsg );
private:
// Operations performed through the controls
void AssumeControl();
void Dismantle();
void StartDismantling();
void StopDismantling();
bool IsDismantling() const;
vgui::EditablePanel *m_pActivePanel;
vgui::EditablePanel *m_pDeterioratingPanel;
vgui::EditablePanel *m_pDismantlingPanel;
vgui::Label *m_pHealthLabel;
vgui::Label *m_pOwnerLabel;
vgui::Button *m_pDismantleButton;
vgui::Button *m_pAssumeControlButton;
vgui::Label *m_pDismantleTimeLabel;
vgui::Panel *m_pCurrentPanel;
bool m_bDismantled;
float m_flDismantleTime;
};
// This is used for child panels. It forwards the messages to the parent panel.
class CCommandChainingPanel : public vgui::EditablePanel
{
typedef vgui::EditablePanel BaseClass;
public:
CCommandChainingPanel( vgui::Panel *parent, const char *panelName ) :
BaseClass( parent, panelName )
{
SetPaintBackgroundEnabled( false );
}
void OnCommand( const char *command )
{
BaseClass::OnCommand( command );
if (GetParent())
{
GetParent()->OnCommand(command);
}
}
};
//-----------------------------------------------------------------------------
// This is a panel for an object that has rotational controls
//-----------------------------------------------------------------------------
class CRotatingObjectControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CRotatingObjectControlPanel, CObjectControlPanel );
public:
CRotatingObjectControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
protected:
virtual void OnTickActive( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer );
private:
CRotationSlider *m_pRotationSlider;
vgui::Label *m_pRotationLabel;
};
#endif // OBJECTCONTROLPANEL_H
+198
View File
@@ -0,0 +1,198 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialsystem.h"
#include <KeyValues.h>
#include "materialsystem/imaterialvar.h"
#include "C_BaseTFPlayer.h"
#include "functionproxy.h"
#include "C_PlayerResource.h"
//-----------------------------------------------------------------------------
// Returns the player health (from 0 to 1)
//-----------------------------------------------------------------------------
class CPlayerHealthProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pEnt );
private:
CFloatInput m_Factor;
};
bool CPlayerHealthProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 ))
return false;
return true;
}
void CPlayerHealthProxy::OnBind( void *pArg )
{
// NOTE: Player health max is not available on the server...
C_BaseEntity *pEntity = BindArgToEntity( pArg );
C_BaseTFPlayer* pPlayer = dynamic_cast<C_BaseTFPlayer*>(pEntity);
if (!pPlayer)
return;
Assert( m_pResult );
SetFloatResult( pPlayer->HealthFraction() * m_Factor.GetFloat() );
/*
// Should we draw their health?
// If he's not on our team we can't see it unless we're a command with "targetinginfo".
if ( GetLocalTeam() != GetTeam() && !(local->HasNamedTechnology("targetinginfo") && IsLocalPlayerClass(TFCLASS_COMMANDO) ))
return drawn;
// Don't draw health bars above myself
if ( local == this )
return drawn;
// Don't draw health bars over dead/dying player
if ( GetHealth() <= 0 )
return drawn;
return drawn;
*/
}
EXPOSE_INTERFACE( CPlayerHealthProxy, IMaterialProxy, "PlayerHealth" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// A function that returns the time since last being damaged
//-----------------------------------------------------------------------------
class CPlayerDamageTimeProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pEnt );
private:
CFloatInput m_Factor;
};
bool CPlayerDamageTimeProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1.0f ))
return false;
return true;
}
void CPlayerDamageTimeProxy::OnBind( void *pArg )
{
C_BaseEntity *pEntity = BindArgToEntity( pArg );
// NOTE: Player health max is not available on the server...
C_BaseTFPlayer* pPlayer = dynamic_cast<C_BaseTFPlayer*>(pEntity);
if (!pPlayer)
{
SetFloatResult( 10000 * m_Factor.GetFloat() );
return;
}
Assert( m_pResult );
float dt = gpGlobals->curtime - pPlayer->GetLastDamageTime();
SetFloatResult( dt * m_Factor.GetFloat() );
}
EXPOSE_INTERFACE( CPlayerDamageTimeProxy, IMaterialProxy, "PlayerDamageTime" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// A function that returns the time since last being healed
//-----------------------------------------------------------------------------
class CPlayerHealTimeProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pEnt );
private:
CFloatInput m_Factor;
};
bool CPlayerHealTimeProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1.0f ))
return false;
return true;
}
void CPlayerHealTimeProxy::OnBind( void *pArg )
{
// NOTE: Player health max is not available on the server...
C_BaseEntity *pEntity = BindArgToEntity( pArg );
C_BaseTFPlayer* pPlayer = dynamic_cast<C_BaseTFPlayer*>(pEntity);
if (!pPlayer)
return;
Assert( m_pResult );
float dt = gpGlobals->curtime - pPlayer->GetLastGainHealthTime();
SetFloatResult( dt * m_Factor.GetFloat() );
}
EXPOSE_INTERFACE( CPlayerHealTimeProxy, IMaterialProxy, "PlayerHealTime" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Returns the player score
//-----------------------------------------------------------------------------
class CPlayerScoreProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pEntity );
private:
CFloatInput m_Factor;
};
bool CPlayerScoreProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 ))
return false;
return true;
}
void CPlayerScoreProxy::OnBind( void *pArg )
{
// Find the view angle between the player and this entity....
C_BaseEntity *pEntity = BindArgToEntity( pArg );
C_BaseTFPlayer* pPlayer = dynamic_cast<C_BaseTFPlayer*>(pEntity);
if (!pPlayer)
return;
if ( !g_PR )
return;
int score = g_PR->GetPlayerScore(pPlayer->index);
Assert( m_pResult );
SetFloatResult( score * m_Factor.GetFloat() );
}
EXPOSE_INTERFACE( CPlayerScoreProxy, IMaterialProxy, "PlayerScore" IMATERIAL_PROXY_INTERFACE_VERSION );
+101
View File
@@ -0,0 +1,101 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_vguiscreen.h"
#include "clientmode_tfbase.h"
#include <vgui/IVGui.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/Label.h>
#include "c_info_act.h"
//-----------------------------------------------------------------------------
// Base class for all vgui screens on objects:
//-----------------------------------------------------------------------------
class CRespawnWaveVGuiScreen : public CVGuiScreenPanel
{
DECLARE_CLASS( CRespawnWaveVGuiScreen, CVGuiScreenPanel );
public:
CRespawnWaveVGuiScreen( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick();
private:
vgui::Label *m_pTime1RemainingLabel;
vgui::Label *m_pTime2RemainingLabel;
};
//-----------------------------------------------------------------------------
// Standard VGUI panel for objects
//-----------------------------------------------------------------------------
DECLARE_VGUI_SCREEN_FACTORY( CRespawnWaveVGuiScreen, "respawn_wave_screen" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CRespawnWaveVGuiScreen::CRespawnWaveVGuiScreen( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, panelName, g_hVGuiObjectScheme )
{
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CRespawnWaveVGuiScreen::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Load all of the controls in
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
// Make sure we get ticked...
vgui::ivgui()->AddTickSignal( GetVPanel() );
// Grab ahold of certain well-known controls
// NOTE: it is valid for these controls to not exist!
m_pTime1RemainingLabel = dynamic_cast<vgui::Label*>(FindChildByName( "RespawnTime1Remaining" ));
m_pTime2RemainingLabel = dynamic_cast<vgui::Label*>(FindChildByName( "RespawnTime2Remaining" ));
return true;
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CRespawnWaveVGuiScreen::OnTick()
{
BaseClass::OnTick();
if (!GetEntity())
return;
int nTime1Remaining = 0;
int nTime2Remaining = 0;
if (g_hCurrentAct.Get())
{
nTime1Remaining = g_hCurrentAct->RespawnTimeRemaining( GetEntity()->GetTeamNumber(), 1 );
nTime2Remaining = g_hCurrentAct->RespawnTimeRemaining( GetEntity()->GetTeamNumber(), 2 );
}
char buf[32];
if (m_pTime1RemainingLabel)
{
Q_snprintf( buf, sizeof( buf ), "%d", nTime1Remaining );
m_pTime1RemainingLabel->SetText( buf );
}
if (m_pTime2RemainingLabel)
{
Q_snprintf( buf, sizeof( buf ), "%d", nTime2Remaining );
m_pTime2RemainingLabel->SetText( buf );
}
}
+148
View File
@@ -0,0 +1,148 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_vguiscreen.h"
#include "clientmode_tfbase.h"
#include <vgui/IVGui.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/Label.h>
#include "vgui_bitmapbutton.h"
#include "c_info_act.h"
#include "tf_shareddefs.h"
#include "c_basetfplayer.h"
int g_ValidVehicles[] =
{
OBJ_WAGON,
OBJ_BATTERING_RAM,
OBJ_VEHICLE_TANK,
OBJ_VEHICLE_TELEPORT_STATION,
OBJ_WALKER_STRIDER,
OBJ_WALKER_MINI_STRIDER
// If you add a new vehicle here, you have to add a button for it to the screen_vehicle_bay.res file.
// The button's name must be VehicleButton%d, where %d is it's index into this array.
// Then add the build%d command to OnCommand at the bottom of this file.
};
#define NUM_VEHICLES ARRAYSIZE(g_ValidVehicles)
//-----------------------------------------------------------------------------
// Vgui screen handling vehicle selection in vehicle bays
//-----------------------------------------------------------------------------
class CVehicleBayVGuiScreen : public CVGuiScreenPanel
{
DECLARE_CLASS( CVehicleBayVGuiScreen, CVGuiScreenPanel );
public:
CVehicleBayVGuiScreen( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick();
virtual void OnCommand( const char *command );
private:
vgui::Button *m_pVehicleButtons[ NUM_VEHICLES ];
};
//-----------------------------------------------------------------------------
// Standard VGUI panel for objects
//-----------------------------------------------------------------------------
DECLARE_VGUI_SCREEN_FACTORY( CVehicleBayVGuiScreen, "vehicle_bay_screen" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CVehicleBayVGuiScreen::CVehicleBayVGuiScreen( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, panelName, g_hVGuiObjectScheme )
{
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CVehicleBayVGuiScreen::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Create our vehicle buttons
for ( int i = 0; i < NUM_VEHICLES; i++ )
{
char ch[128];
Q_snprintf( ch, sizeof(ch), "VehicleButton%d", i );
m_pVehicleButtons[i] = new CBitmapButton( this, ch, "Name" );
}
// Load all of the controls in
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
// Make sure we get ticked...
vgui::ivgui()->AddTickSignal( GetVPanel() );
return true;
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CVehicleBayVGuiScreen::OnTick()
{
BaseClass::OnTick();
if (!GetEntity())
return;
C_BaseTFPlayer *pLocalPlayer = C_BaseTFPlayer::GetLocalPlayer();
if ( !pLocalPlayer )
return;
int nBankResources = pLocalPlayer ? pLocalPlayer->GetBankResources() : 0;
// Set the vehicles costs
for ( int i = 0; i < NUM_VEHICLES; i++ )
{
if ( !m_pVehicleButtons[i] )
continue;
char buf[128];
int iCost = CalculateObjectCost( g_ValidVehicles[i], pLocalPlayer->GetNumObjects( g_ValidVehicles[i] ), pLocalPlayer->GetTeamNumber() );
Q_snprintf( buf, sizeof( buf ), "%s : %d", GetObjectInfo( g_ValidVehicles[i] )->m_pStatusName, iCost );
m_pVehicleButtons[i]->SetText( buf );
// Can't build if the game hasn't started
if ( CurrentActIsAWaitingAct() )
{
m_pVehicleButtons[i]->SetEnabled( false );
}
else
{
m_pVehicleButtons[i]->SetEnabled( nBankResources >= iCost );
}
}
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CVehicleBayVGuiScreen::OnCommand( const char *command )
{
if (!Q_strnicmp(command, "build", 5))
{
int iButton;
int nCount = sscanf( command, "build%d", &iButton );
if (nCount == 1)
{
char szbuf[64];
Q_snprintf( szbuf, sizeof( szbuf ), "buildvehicle %d %d", GetEntity()->entindex(), g_ValidVehicles[iButton] );
engine->ClientCmd(szbuf);
return;
}
}
BaseClass::OnCommand(command);
}
@@ -0,0 +1,284 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: TF2 Specific C_BaseCombatCharacter code.
//
//=============================================================================//
#include "cbase.h"
#include "c_basecombatcharacter.h"
#include "tf_shareddefs.h"
#include "particles_simple.h"
#include "functionproxy.h"
#include "IEffects.h"
#include "weapon_combatshield.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::Release( void )
{
RemoveAllPowerups();
BaseClass::Release();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::SetDormant( bool bDormant )
{
// If we're going dormant, stop all our powerup sounds
if ( bDormant )
{
RemoveAllPowerups();
}
else
{
// Restart any powerups on him
for ( int i = 0; i < MAX_POWERUPS; i++ )
{
if ( m_iPowerups & (1 << i) )
{
PowerupStart( i, false );
}
}
}
BaseClass::SetDormant( bDormant );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_iPrevPowerups = m_iPowerups;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
// Power state changed?
if ( m_iPowerups != m_iPrevPowerups )
{
for ( int i = 0; i < MAX_POWERUPS; i++ )
{
bool bPoweredNow = ( m_iPowerups & (1 << i) );
bool bPoweredThen = ( m_iPrevPowerups & (1 << i) );
if ( !bPoweredThen && bPoweredNow )
{
PowerupStart( i, true );
}
else if ( bPoweredThen && !bPoweredNow )
{
PowerupEnd( i );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Powerup has just started
// If bInitial is set, the server's just told us this powerup has come on.
// If it's false, the entity had it on when it left PVS, and now it's re-entered
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::PowerupStart( int iPowerup, bool bInitial )
{
Assert( iPowerup >= 0 && iPowerup < MAX_POWERUPS );
switch( iPowerup )
{
case POWERUP_BOOST:
break;
case POWERUP_EMP:
{
// Play the EMP sound
if ( !bInitial )
{
EmitSound( "BaseCombatCharacter.EMPPulse" );
}
}
break;
default:
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: Powerup has just finished
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::PowerupEnd( int iPowerup )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::RemoveAllPowerups( void )
{
// Stop any powerups we have
if ( m_iPowerups )
{
for ( int i = 0; i < MAX_POWERUPS; i++ )
{
if ( m_iPowerups & (1 << i) )
{
PowerupEnd( i );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::ClientThink( void )
{
BaseClass::ClientThink();
if ( !IsDormant() )
{
if ( HasPowerup(POWERUP_EMP) )
{
AddEMPEffect( WorldAlignSize().Length() * 0.15 );
}
if ( HasPowerup(POWERUP_BOOST) )
{
AddBuffEffect( WorldAlignSize().Length() * 0.15 );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Draw an effect to show this entity has been EMPed
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::AddEMPEffect( float flSize )
{
// Don't draw on the local player
if ( this == C_BasePlayer::GetLocalPlayer() )
return;
CSmartPtr<CSimpleEmitter> pEmitter;
PMaterialHandle hParticleMaterial;
TimedEvent pParticleEvent;
pParticleEvent.Init( 300 );
pEmitter = CSimpleEmitter::Create( "ObjectEMPEffect" );
hParticleMaterial = pEmitter->GetPMaterial( "sprites/chargeball" );
// Add particles
float flCur = gpGlobals->frametime;
Vector vCenter = WorldSpaceCenter( );
while ( pParticleEvent.NextEvent( flCur ) )
{
Vector vPos;
Vector vOffset = RandomVector( -1, 1 );
VectorNormalize( vOffset );
vPos = vCenter + (vOffset * RandomFloat( 0, flSize ));
pEmitter->SetSortOrigin( vPos );
SimpleParticle *pParticle = pEmitter->AddSimpleParticle( hParticleMaterial, vPos );
if ( pParticle )
{
// Move the points along the path.
pParticle->m_vecVelocity.Init();
pParticle->m_flRoll = 0;
pParticle->m_flRollDelta = 0;
pParticle->m_flDieTime = 0.4f;
pParticle->m_flLifetime = 0;
pParticle->m_uchColor[0] = 255;
pParticle->m_uchColor[1] = 255;
pParticle->m_uchColor[2] = 255;
pParticle->m_uchStartAlpha = 32;
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartSize = 4;
pParticle->m_uchEndSize = 2;
pParticle->m_iFlags = 0;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Draw an effect to show this entity is being buffed
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::AddBuffEffect( float flSize )
{
// Don't draw on the local player
if ( this == C_BasePlayer::GetLocalPlayer() )
return;
CSmartPtr<CSimpleEmitter> pEmitter;
PMaterialHandle hParticleMaterial;
TimedEvent pParticleEvent;
pParticleEvent.Init( 300 );
pEmitter = CSimpleEmitter::Create( "ObjectBuffEffect" );
hParticleMaterial = pEmitter->GetPMaterial( "sprites/chargeball" );
// Add particles
float flCur = gpGlobals->frametime;
Vector vCenter = WorldSpaceCenter( );
while ( pParticleEvent.NextEvent( flCur ) )
{
Vector vPos;
Vector vOffset = RandomVector( -1, 1 );
VectorNormalize( vOffset );
vPos = vCenter + (vOffset * RandomFloat( 0, flSize ));
SimpleParticle *pParticle = pEmitter->AddSimpleParticle( hParticleMaterial, vPos );
if ( pParticle )
{
// Move the points along the path.
pParticle->m_vecVelocity.Init();
pParticle->m_flRoll = 0;
pParticle->m_flRollDelta = 0;
pParticle->m_flDieTime = 0.4f;
pParticle->m_flLifetime = 0;
pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[0] = pParticle->m_uchColor[2] = 0;
pParticle->m_uchStartAlpha = 128;
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartSize = 3;
pParticle->m_uchEndSize = 1;
pParticle->m_iFlags = 0;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns shield if owned.
//-----------------------------------------------------------------------------
C_WeaponCombatShield *C_BaseCombatCharacter::GetShield( void )
{
C_BaseCombatWeapon *pWeapon;
if ( GetTeamNumber() == TEAM_ALIENS )
{
pWeapon = Weapon_OwnsThisType( "weapon_combat_shield_alien" );
}
else
{
pWeapon = Weapon_OwnsThisType( "weapon_combat_shield" );
}
if ( !pWeapon )
return NULL;
return ( CWeaponCombatShield* )pWeapon;
}
@@ -0,0 +1,89 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "C_BaseFourWheelVehicle.h"
IMPLEMENT_CLIENTCLASS_DT(C_BaseTFFourWheelVehicle, DT_BaseTFFourWheelVehicle, CBaseTFFourWheelVehicle)
RecvPropFloat( RECVINFO( m_flDeployFinishTime ) ),
RecvPropInt( RECVINFO( m_eDeployMode ) ),
RecvPropInt( RECVINFO( m_bBoostUpgrade ) ),
RecvPropInt( RECVINFO( m_nBoostTimeLeft ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseTFFourWheelVehicle::C_BaseTFFourWheelVehicle()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float C_BaseTFFourWheelVehicle::GetDeployFinishTime() const
{
return m_flDeployFinishTime;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
VehicleModeDeploy_e C_BaseTFFourWheelVehicle::GetVehicleModeDeploy() const
{
return m_eDeployMode;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseTFFourWheelVehicle::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
// Start thinking (Baseclass stops it)
ClientThinkList()->SetNextClientThink( GetClientHandle(), CLIENT_THINK_ALWAYS );
}
}
//-----------------------------------------------------------------------------
// Restricts the view within a range of the center...
//-----------------------------------------------------------------------------
void C_BaseTFFourWheelVehicle::RestrictView( int nRole, float flMinYaw, float flMaxYaw, QAngle &vecViewAngles )
{
Assert( nRole >= 0 );
Vector vehicleEyeOrigin;
QAngle vehicleEyeAngles;
GetRoleViewPosition( nRole, &vehicleEyeOrigin, &vehicleEyeAngles );
// Confine the view to the appropriate yaw range...
float flCenterYaw = vehicleEyeAngles[YAW];
// View angles are dealt with in absolute terms here...
float flAngleDiff = AngleDiff( vecViewAngles[YAW], flCenterYaw );
// Here, we must clamp to the cone...
if (flAngleDiff < flMinYaw)
vecViewAngles[YAW] = anglemod(flCenterYaw + flMinYaw);
else if (flAngleDiff > flMaxYaw)
vecViewAngles[YAW] = anglemod(flCenterYaw + flMaxYaw);
}
//-----------------------------------------------------------------------------
// Clamps the view angles while driving the vehicle
//-----------------------------------------------------------------------------
void C_BaseTFFourWheelVehicle::UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd )
{
int nRole = GetPassengerRole( pLocalPlayer );
if ( nRole != VEHICLE_ROLE_DRIVER )
{
RestrictView( nRole, -90, 90, pCmd->viewangles );
}
}
+51
View File
@@ -0,0 +1,51 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASE_FOUR_WHEEL_VEHICLE_H
#define C_BASE_FOUR_WHEEL_VEHICLE_H
#include "basetfvehicle.h"
class C_BasePlayer;
class C_BaseTFFourWheelVehicle : public C_BaseTFVehicle
{
DECLARE_CLASS( C_BaseTFFourWheelVehicle, C_BaseTFVehicle );
DECLARE_CLIENTCLASS();
public:
C_BaseTFFourWheelVehicle();
float GetDeployFinishTime() const;
VehicleModeDeploy_e GetVehicleModeDeploy() const;
// TF2 vehicles are animated by the server
virtual bool IsSelfAnimating() { return false; };
virtual void OnDataChanged( DataUpdateType_t updateType );
// IClientVehicle overrides.
public:
virtual void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd );
protected:
// Restricts the view within a range of the center...
void RestrictView( int nRole, float flMinYaw, float flMaxYaw, QAngle &vecViewAngles );
private:
C_BaseTFFourWheelVehicle( const C_BaseTFFourWheelVehicle & ); // not defined, not accessible
private:
// Used to draw deploy timer on vgui screens.
float m_flDeployFinishTime;
VehicleModeDeploy_e m_eDeployMode;
};
#endif // C_BASE_FOUR_WHEEL_VEHICLE_H
+921
View File
@@ -0,0 +1,921 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Clients CBaseObject
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseobject.h"
#include "c_basetfplayer.h"
#include "hud.h"
#include "c_tfteam.h"
#include "engine/IEngineSound.h"
#include "particles_simple.h"
#include "functionproxy.h"
#include "IEffects.h"
#include "c_hint_events.h"
#include "model_types.h"
#include "particlemgr.h"
#include "particle_collision.h"
#include "env_objecteffects.h"
#include "basetfvehicle.h"
#include "c_weapon_builder.h"
#include "ivrenderview.h"
#include "ObjectControlPanel.h"
#include "engine/ivmodelinfo.h"
#include "c_te_effect_dispatch.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define MAX_VISIBLE_BUILDPOINT_DISTANCE (400 * 400)
// Remove aliasing of name due to shared code
#undef CBaseObject
IMPLEMENT_CLIENTCLASS_DT(C_BaseObject, DT_BaseObject, CBaseObject)
RecvPropInt(RECVINFO(m_iHealth)),
RecvPropInt(RECVINFO(m_iMaxHealth)),
RecvPropInt(RECVINFO(m_bHasSapper)),
RecvPropInt(RECVINFO(m_iObjectType)),
RecvPropInt(RECVINFO(m_bBuilding)),
RecvPropInt(RECVINFO(m_bPlacing)),
RecvPropFloat(RECVINFO(m_flPercentageConstructed)),
RecvPropInt(RECVINFO(m_fObjectFlags)),
RecvPropInt(RECVINFO(m_bDeteriorating)),
RecvPropEHandle(RECVINFO(m_hBuiltOnEntity)),
RecvPropInt(RECVINFO( m_takedamage ) ),
RecvPropInt( RECVINFO( m_bDisabled ) ),
RecvPropEHandle( RECVINFO( m_hBuilder ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseObject::C_BaseObject( )
{
m_flDamageFlash = 0;
m_YawPreviewState = YAW_PREVIEW_OFF;
m_bBuilding = false;
m_bPlacing = false;
m_flPercentageConstructed = 0;
m_flNextEffect = 0;
m_bOldSapper = m_bHasSapper = false;
m_fObjectFlags = 0;
m_bDeteriorating = false;
m_ThermalMaterial.Init("player/thermal/thermal",TEXTURE_GROUP_CLIENT_EFFECTS);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseObject::~C_BaseObject( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::PreDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PreDataUpdate( updateType );
m_iOldHealth = m_iHealth;
m_bOldSapper = m_bHasSapper;
m_hOldOwner = GetOwner();
m_bWasActive = ShouldBeActive();
m_bWasBuilding = m_bBuilding;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::OnDataChanged( DataUpdateType_t updateType )
{
if (updateType == DATA_UPDATE_CREATED)
{
if ( !IS_MINIMAP_PANEL_DEFINED( ) && !(m_fObjectFlags & OF_SUPPRESS_APPEAR_ON_MINIMAP) )
{
CONSTRUCT_MINIMAP_PANEL( "minimap_object", MINIMAP_OBJECTS );
}
CreateBuildPoints();
}
BaseClass::OnDataChanged( updateType );
// Did we just finish building?
if ( m_bWasBuilding && !m_bBuilding )
{
FinishedBuilding();
}
// Did we just go active?
bool bShouldBeActive = ShouldBeActive();
if ( !m_bWasActive && bShouldBeActive )
{
OnGoActive();
}
else if ( m_bWasActive && !bShouldBeActive )
{
OnGoInactive();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::SetDormant( bool bDormant )
{
BaseClass::SetDormant( bDormant );
//ENTITY_PANEL_ACTIVATE( "analyzed_object", !bDormant );
}
#define TF_OBJ_BODYGROUPTURNON 1
#define TF_OBJ_BODYGROUPTURNOFF 0
//-----------------------------------------------------------------------------
// Purpose:
// Input : origin -
// angles -
// event -
// *options -
//-----------------------------------------------------------------------------
void C_BaseObject::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
switch ( event )
{
default:
{
BaseClass::FireEvent( origin, angles, event, options );
}
break;
case TF_OBJ_PLAYBUILDSOUND:
{
EmitSound( options );
}
break;
case TF_OBJ_ENABLEBODYGROUP:
{
int index = FindBodygroupByName( options );
if ( index >= 0 )
{
SetBodygroup( index, TF_OBJ_BODYGROUPTURNON );
}
}
break;
case TF_OBJ_DISABLEBODYGROUP:
{
int index = FindBodygroupByName( options );
if ( index >= 0 )
{
SetBodygroup( index, TF_OBJ_BODYGROUPTURNOFF );
}
}
break;
case TF_OBJ_ENABLEALLBODYGROUPS:
case TF_OBJ_DISABLEALLBODYGROUPS:
{
// Start at 1, because body 0 is the main .mdl body...
// Is this the way we want to do this?
int count = GetNumBodyGroups();
for ( int i = 1; i < count; i++ )
{
int subpartcount = GetBodygroupCount( i );
if ( subpartcount == 2 )
{
SetBodygroup( i,
( event == TF_OBJ_ENABLEALLBODYGROUPS ) ?
TF_OBJ_BODYGROUPTURNON : TF_OBJ_BODYGROUPTURNOFF );
}
else
{
DevMsg( "TF_OBJ_ENABLE/DISABLEBODY GROUP: %s has a group with %i subparts, should be exactly 2\n",
GetClassname(), subpartcount );
}
}
}
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BaseObject::OffsetObjectOrigin( Vector& origin )
{
if ( !m_bBuilding )
return false;
if ( inv_demo.GetBool() )
return false;
Vector vecWorldMins, vecWorldMaxs;
CollisionProp()->WorldSpaceAABB( &vecWorldMins, &vecWorldMaxs );
float flSize = vecWorldMaxs.z - vecWorldMins.z;
origin.z -= (flSize * (1 - m_flPercentageConstructed));
// If we're building, fake sliding the object out of the ground
return true;
}
const char* C_BaseObject::GetStatusName() const
{
return GetObjectInfo( GetType() )->m_pStatusName;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_BaseObject::DrawModel( int flags )
{
Vector vRealOrigin = GetLocalOrigin();
Vector vOrigin = vRealOrigin;
bool needOriginReset = OffsetObjectOrigin( vOrigin );
if ( needOriginReset )
{
SetLocalOrigin( vOrigin );
InvalidateBoneCache();
}
int drawn;
C_BaseTFPlayer *pLocal = C_BaseTFPlayer::GetLocalPlayer();
if ( pLocal && pLocal->IsUsingThermalVision() )
{
modelrender->ForcedMaterialOverride( m_ThermalMaterial );
drawn = BaseClass::DrawModel(flags);
modelrender->ForcedMaterialOverride( NULL );
}
else
{
// If we're a brush-built, map-defined object chain up to baseentity draw
if ( modelinfo->GetModelType( GetModel() ) == mod_brush )
{
drawn = CBaseEntity::DrawModel(flags);
}
else
{
drawn = BaseClass::DrawModel(flags);
}
}
// Restore faked origin
if ( needOriginReset )
{
SetLocalOrigin( vRealOrigin );
}
// If we were drawn, draw building effects if we're building, or damage effects if we're damaged
if ( drawn && (m_flNextEffect < gpGlobals->curtime) )
{
// Haxory LOD
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr() < lod_effect_distance.GetFloat() )
{
if ( IsBuilding() )
{
DrawBuildEffects();
}
if ( !m_bPlacing && !m_bBuilding )
{
if ( !HasPowerup( POWERUP_EMP ) )
{
DrawRunningEffects();
}
if ( GetHealth() < GetMaxHealth() )
{
DrawDamageEffects();
}
}
}
}
HighlightBuildPoints( flags );
return drawn;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::HighlightBuildPoints( int flags )
{
C_BaseTFPlayer *pLocal = C_BaseTFPlayer::GetLocalPlayer();
if ( !pLocal )
return;
if ( !GetNumBuildPoints() || !InLocalTeam() )
return;
C_WeaponBuilder *pBuilderWpn = dynamic_cast< C_WeaponBuilder * >( pLocal->GetActiveWeaponForSelection() );
if ( !pBuilderWpn )
return;
if ( !pBuilderWpn->IsPlacingObject() )
return;
C_BaseObject *pPlacementObj = pBuilderWpn->GetPlacementModel();
if ( !pPlacementObj || pPlacementObj == this )
return;
// Near enough?
if ( (GetAbsOrigin() - pLocal->GetAbsOrigin()).LengthSqr() < MAX_VISIBLE_BUILDPOINT_DISTANCE )
{
bool bRestoreModel = false;
Vector vecPrevAbsOrigin = pPlacementObj->GetAbsOrigin();
QAngle vecPrevAbsAngles = pPlacementObj->GetAbsAngles();
Vector orgColor;
render->GetColorModulation( orgColor.Base() );
float orgBlend = render->GetBlend();
// Any empty buildpoints?
for ( int i = 0; i < GetNumBuildPoints(); i++ )
{
// Can this object build on this point?
if ( CanBuildObjectOnBuildPoint( i, pPlacementObj->GetType() ) )
{
Vector vecBPOrigin;
QAngle vecBPAngles;
if ( GetBuildPoint(i, vecBPOrigin, vecBPAngles) )
{
pPlacementObj->InvalidateBoneCaches();
Vector color( 0, 255, 0 );
render->SetColorModulation( color.Base() );
float frac = fmod( gpGlobals->curtime, 3 );
frac *= 2 * M_PI;
frac = cos( frac );
render->SetBlend( (175 + (int)( frac * 75.0f )) / 255.0 );
// HACK: Fixup angles on the HL2 model we're using
if ( !strcmp( modelinfo->GetModelName( pPlacementObj->GetModel() ), "models/items/HealthKit.mdl" ) )
{
vecBPAngles.x += 90;
}
// FIXME: This truly sucks! The bone cache should use
// render location for this computation instead of directly accessing AbsAngles
// Necessary for bone cache computations to work
pPlacementObj->SetAbsOrigin( vecBPOrigin );
pPlacementObj->SetAbsAngles( vecBPAngles );
modelrender->DrawModel(
flags,
pPlacementObj,
pPlacementObj->GetModelInstance(),
pPlacementObj->index,
pPlacementObj->GetModel(),
vecBPOrigin,
vecBPAngles,
pPlacementObj->m_nSkin,
pPlacementObj->m_nBody,
pPlacementObj->m_nHitboxSet
);
bRestoreModel = true;
}
}
}
if ( bRestoreModel )
{
pPlacementObj->SetAbsOrigin(vecPrevAbsOrigin);
pPlacementObj->SetAbsAngles(vecPrevAbsAngles);
pPlacementObj->InvalidateBoneCaches();
render->SetColorModulation( orgColor.Base() );
render->SetBlend( orgBlend );
}
}
}
//-----------------------------------------------------------------------------
// Exit points for mounted vehicles....
//-----------------------------------------------------------------------------
void C_BaseObject::GetExitPoint( CBaseEntity *pPlayer, int nBuildPoint, Vector *pAbsPosition, QAngle *pAbsAngles )
{
Assert(0);
}
//-----------------------------------------------------------------------------
// Purpose: Overridden to allow for brush-built map defined objects
//-----------------------------------------------------------------------------
bool C_BaseObject::IsIdentityBrush( void )
{
return false;
}
//-----------------------------------------------------------------------------
// Builder preview...
//-----------------------------------------------------------------------------
void C_BaseObject::ActivateYawPreview( bool enable )
{
m_YawPreviewState = enable ? YAW_PREVIEW_ON : YAW_PREVIEW_WAITING_FOR_UPDATE;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::PreviewYaw( float yaw )
{
m_fYawPreview = yaw;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BaseObject::IsPreviewingYaw() const
{
return m_YawPreviewState != YAW_PREVIEW_OFF;
}
//-----------------------------------------------------------------------------
// Purpose: This is called to get the initial builder yaw...
//-----------------------------------------------------------------------------
float C_BaseObject::GetInitialBuilderYaw()
{
return GetAbsAngles().y;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
bool bNewEntity = (updateType == DATA_UPDATE_CREATED);
if ( bNewEntity )
{
m_flAttackTime = -1000;
}
// Determine if we're under attack
if ( !bNewEntity )
{
if ( m_iHealth < m_iOldHealth )
{
// Deteriorating objects don't play sounds
if ( !IsDeteriorating() )
{
m_flAttackTime = gpGlobals->curtime;
}
}
else if ( m_iHealth > m_iOldHealth && m_iHealth == m_iMaxHealth )
{
// If we were just fully healed, remove all decals
RemoveAllDecals();
}
}
if ( m_bHasSapper )
{
// Play a specific sound for a sapper...
if ( m_bOldSapper != m_bHasSapper )
{
// Don't create these for dragonsteeth
if ( InLocalTeam() && GetType() != OBJ_DRAGONSTEETH )
{
// Play a sound.
CLocalPlayerFilter filter;
EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "BaseObject.SapperDestroyingTeamBuilding" );
MinimapCreateTempTrace( "minimap_under_attack", MINIMAP_PERSONAL_ORDERS, GetAbsOrigin() );
}
}
}
// Notify the hint system of the object being built.
if ( bNewEntity && GetOwner() && ( GetOwner() == C_BasePlayer::GetLocalPlayer() ) )
{
C_HintEvent_ObjectBuiltByLocalPlayer event( this );
GlobalHintEvent( &event );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::Release( void )
{
// Remove any reticles on this entity
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer();
if ( pPlayer )
{
pPlayer->Remove_Target( this );
}
BaseClass::Release();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BaseObject::IsUnderAttack( )
{
// It's under attack for the 3 seconds after the last attack time
return (gpGlobals->curtime - m_flAttackTime) < 5.0f;
}
//-----------------------------------------------------------------------------
// Ownership:
//-----------------------------------------------------------------------------
C_BaseTFPlayer *C_BaseObject::GetOwner()
{
return m_hBuilder;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BaseObject::IsOwnedByLocalPlayer() const
{
if ( !m_hBuilder )
return false;
return ( m_hBuilder == C_BaseTFPlayer::GetLocalPlayer() );
}
//-----------------------------------------------------------------------------
// Purpose: Add entity to visibile entities list
//-----------------------------------------------------------------------------
void C_BaseObject::AddEntity( void )
{
// If set to invisible, skip. Do this before resetting the entity pointer so it has
// valid data to decide whether it's visible.
if ( !ShouldDraw() )
{
return;
}
// Update the entity position
UpdatePosition();
// Yaw preview
if (m_YawPreviewState != YAW_PREVIEW_OFF)
{
// This piece of code makes it so we keep using the preview
// until we get a network update which matches the update value
if (m_YawPreviewState == YAW_PREVIEW_WAITING_FOR_UPDATE)
{
if (fmod( fabs(GetLocalAngles().y - m_fYawPreview), 360.0f) < 1.0f)
{
m_YawPreviewState = YAW_PREVIEW_OFF;
}
}
if (GetLocalOrigin().y != m_fYawPreview)
{
SetLocalAnglesDim( Y_INDEX, m_fYawPreview );
InvalidateBoneCache();
}
}
// Create flashlight effects, etc.
CreateLightEffects();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::Select( void )
{
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer();
pPlayer->SetSelectedObject( this );
}
//-----------------------------------------------------------------------------
// Sends client commands back to the server:
//-----------------------------------------------------------------------------
void C_BaseObject::SendClientCommand( const char *pCmd )
{
char szbuf[128];
Q_snprintf( szbuf, sizeof( szbuf ), "objcmd %d %s", entindex(), pCmd );
engine->ClientCmd(szbuf);
}
//-----------------------------------------------------------------------------
// Purpose: Get a text description for the object target
//-----------------------------------------------------------------------------
const char *C_BaseObject::GetTargetDescription( void ) const
{
return GetStatusName();
}
//-----------------------------------------------------------------------------
// Purpose: Get a text description for the object target (more verbose)
//-----------------------------------------------------------------------------
char *C_BaseObject::GetIDString( void )
{
m_szIDString[0] = 0;
RecalculateIDString();
return m_szIDString;
}
//-----------------------------------------------------------------------------
// It's a valid ID target when it's building
//-----------------------------------------------------------------------------
bool C_BaseObject::IsValidIDTarget( void )
{
return InSameTeam( C_BaseTFPlayer::GetLocalPlayer() ) && m_bBuilding;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseObject::RecalculateIDString( void )
{
// Subclasses may have filled this out with a string
if ( !m_szIDString[0] )
{
Q_strncpy( m_szIDString, GetTargetDescription(), sizeof(m_szIDString) );
}
// Have I taken damage?
if ( m_iHealth < m_iMaxHealth )
{
char szHealth[ MAX_ID_STRING ];
if ( IsDeteriorating() )
{
Q_snprintf( szHealth, sizeof(szHealth), "\nBUILDER LOST, DETERIORATING... %.0f percent", ceil(((float)m_iHealth / (float)m_iMaxHealth) * 100) );
}
else if ( m_bBuilding )
{
Q_snprintf( szHealth, sizeof(szHealth), "\nConstruction at %.0f percent\nHealth at %.0f percent", (m_flPercentageConstructed * 100), ceil(((float)m_iHealth / (float)m_iMaxHealth) * 100) );
}
else
{
Q_snprintf( szHealth, sizeof(szHealth), "\nHealth at %.0f percent", ceil(((float)m_iHealth / (float)m_iMaxHealth) * 100) );
}
Q_strncat( m_szIDString, szHealth, sizeof(m_szIDString), COPY_ALL_CHARACTERS );
}
if ( m_bHasSapper )
{
Q_strncat( m_szIDString, "\nUse it to remove the attached enemy object", sizeof(m_szIDString), COPY_ALL_CHARACTERS );
}
// If it's deteriorating, and I can buy it, tell me
C_BaseTFPlayer *pLocalPlayer = C_BaseTFPlayer::GetLocalPlayer();
if ( IsDeteriorating() && pLocalPlayer && ClassCanBuild( pLocalPlayer->PlayerClass(), GetType() ) )
{
char szBuy[ MAX_ID_STRING ];
int iCost = CalculateObjectCost( GetType(), pLocalPlayer->GetNumObjects( GetType() ), pLocalPlayer->GetTeamNumber() );
Q_snprintf( szBuy, sizeof(szBuy), "\nBUY THIS OBJECT FOR %d RESOURCES", iCost );
Q_strncat( m_szIDString, szBuy, sizeof(m_szIDString), COPY_ALL_CHARACTERS );
}
}
//-----------------------------------------------------------------------------
// Purpose: Effects created when the object's running
//-----------------------------------------------------------------------------
void C_BaseObject::DrawRunningEffects( void )
{
if ( !GetMaxHealth() )
return;
// Get the overall damage percentage
float flDamaged = 1.0 - ((float)GetHealth() / (float)GetMaxHealth());
// Damage attachment points
int iSmokeAttachment, iSparkAttachment;
Vector vecSmoke, vecSpark, vecSmokeDir, dir;
QAngle angSmoke, angSpark;
// Look for damage points
iSmokeAttachment = LookupRandomAttachment( "r_smoke" );
// Get the points
if ( GetAttachment( iSmokeAttachment, vecSmoke, angSmoke ) )
{
AngleVectors( angSmoke, &vecSmokeDir);
float r, g, b;
r = g = b = random->RandomFloat( 16, 92 );
// Smoke
CSmartPtr<CObjectSmokeParticles> pSmokeEmitter = CObjectSmokeParticles::Create( "DrawRunningEffects 1" );
pSmokeEmitter->SetSortOrigin( vecSmoke );
ObjectSmokeParticle *pParticle = (ObjectSmokeParticle *) pSmokeEmitter->AddParticle( sizeof(ObjectSmokeParticle), g_Mat_DustPuff[1], vecSmoke );
if ( pParticle )
{
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f );
pParticle->m_uchStartSize = random->RandomFloat( 2, 3 );
pParticle->m_uchEndSize = random->RandomFloat( 5, 10 );
dir[0] = vecSmokeDir[0] + random->RandomFloat( -0.1f, 0.1f );
dir[1] = vecSmokeDir[1] + random->RandomFloat( -0.1f, 0.1f );
dir[2] = vecSmokeDir[2] + random->RandomFloat( -0.1f, 0.1f );
pParticle->m_vecVelocity = dir * random->RandomFloat( 30.0f, 40.0f );
pParticle->m_uchStartAlpha = random->RandomFloat( 128,255 );
pParticle->m_uchEndAlpha = 0;
pParticle->m_flRoll = random->RandomFloat( 180, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );
pParticle->m_uchColor[0] = r;
pParticle->m_uchColor[1] = g;
pParticle->m_uchColor[2] = b;
pParticle->m_vecAcceleration = Vector(0,0,10);
}
}
// Sparks
for ( float flSparks = flDamaged - 0.3; flSparks > 0; flSparks -= 0.3 )
{
// Get random spark attachment point
iSparkAttachment = LookupRandomAttachment( "r_spark" );
if ( GetAttachment( iSparkAttachment, vecSpark, angSpark ) )
{
g_pEffects->Sparks( vecSpark );
}
}
m_flNextEffect = gpGlobals->curtime + random->RandomFloat( 0.05, 0.1 );
}
//-----------------------------------------------------------------------------
// Purpose: Effects created while the object's building itself
//-----------------------------------------------------------------------------
void C_BaseObject::DrawBuildEffects( void )
{
m_flNextEffect = gpGlobals->curtime + 10;
}
//-----------------------------------------------------------------------------
// Purpose: Effects created when the object's damaged
//-----------------------------------------------------------------------------
void C_BaseObject::DrawDamageEffects( void )
{
if ( !GetMaxHealth() )
return;
// Get the overall damage percentage
float flDamaged = 1.0 - ((float)GetHealth() / (float)GetMaxHealth());
// Damage attachment points
int iSmokeAttachment, iFireAttachment, iSparkAttachment;
Vector vecSmoke, vecFire, vecSpark, vecSmokeDir, dir;
QAngle angSmoke, angFire, angSpark;
// HACK: Calculate a random origin
// This can go away when we require all objects to have damage attachment points
Vector vecOrigin;
CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecOrigin );
// Look for damage points
iSmokeAttachment = LookupRandomAttachment( "d_smoke" );
iFireAttachment = LookupRandomAttachment( "d_fire" );
// Get the points, and if we can't find 'em, use the random origin
if ( GetAttachment( iSmokeAttachment, vecSmoke, angSmoke ) )
{
AngleVectors( angSmoke, &vecSmokeDir );
}
else
{
vecSmoke = vecOrigin;
vecSmokeDir = Vector(0,0,1);
}
if ( !GetAttachment( iFireAttachment, vecFire, angFire ) )
{
vecFire = vecOrigin;
angFire = QAngle(0,0,0);
}
float r, g, b;
r = g = b = random->RandomFloat( 16, 92 );
// Smoke
CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create( "DrawDamageEffects 1" );
pSmokeEmitter->SetSortOrigin( vecSmoke );
SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[1], vecSmoke );
if ( pParticle )
{
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f );
pParticle->m_uchStartSize = MAX( 1, 20 * flDamaged );
pParticle->m_uchEndSize = MAX( 10, 80 * flDamaged );
dir[0] = vecSmokeDir[0] + random->RandomFloat( -0.2f, 0.2f );
dir[1] = vecSmokeDir[1] + random->RandomFloat( -0.2f, 0.2f );
dir[2] = vecSmokeDir[2] + random->RandomFloat( -0.2f, 0.2f );
pParticle->m_vecVelocity = dir * random->RandomFloat( 60.0f, 80.0f );
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 0;
pParticle->m_flRoll = random->RandomFloat( 180, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );
pParticle->m_uchColor[0] = r;
pParticle->m_uchColor[1] = g;
pParticle->m_uchColor[2] = b;
}
// If we're really hurt, start burning
if ( flDamaged > 0.25 )
{
CSmartPtr<CObjectFireParticles> pFireEmitter = CObjectFireParticles::Create( "DrawDamageEffects 1" );
pFireEmitter->SetSortOrigin( vecFire );
PMaterialHandle hSphereMaterial = pFireEmitter->GetPMaterial( "sprites/floorflame" );
ObjectFireParticle *pParticle = (ObjectFireParticle *) pFireEmitter->AddParticle( sizeof(ObjectFireParticle), hSphereMaterial, vecFire );
if ( pParticle )
{
pParticle->m_hParent = this;
pParticle->m_iAttachmentPoint = iFireAttachment;
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = 1.0;
pParticle->m_uchStartSize = MAX( 5, 30 * (flDamaged - 0.25) );
pParticle->m_uchEndSize = pParticle->m_uchStartSize;
pParticle->m_vecVelocity = Vector(0,0,1);
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 255;
pParticle->m_flRoll = 0;
pParticle->m_flRollDelta = 0;
}
}
// Sparks
for ( float flSparks = flDamaged - 0.3; flSparks > 0; flSparks -= 0.3 )
{
// Get random spark attachment point
iSparkAttachment = LookupRandomAttachment( "d_spark" );
if ( !GetAttachment( iSparkAttachment, vecSpark, angSpark ) )
{
vecSpark = vecOrigin;
angSpark = QAngle(0,0,0);
}
g_pEffects->Sparks( vecSpark );
}
m_flNextEffect = gpGlobals->curtime + random->RandomFloat( 0.2, 0.5 );
}
//============================================================================================================
// POWER PROXY
//============================================================================================================
class CObjectPowerProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Factor;
};
bool CObjectPowerProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 ))
return false;
return true;
}
void CObjectPowerProxy::OnBind( void *pRenderable )
{
// Find the view angle between the player and this entity....
IClientRenderable *pRend = (IClientRenderable *)pRenderable;
C_BaseEntity *pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
C_BaseObject *pObject = dynamic_cast<C_BaseObject*>(pEntity);
if (!pObject)
return;
int iPowered = pObject->IsPowered();
SetFloatResult( iPowered * m_Factor.GetFloat() );
}
EXPOSE_INTERFACE( CObjectPowerProxy, IMaterialProxy, "ObjectPower" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CBasicControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CBasicControlPanel, CObjectControlPanel );
public:
CBasicControlPanel( vgui::Panel *parent, const char *panelName );
};
DECLARE_VGUI_SCREEN_FACTORY( CBasicControlPanel, "basic_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CBasicControlPanel::CBasicControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CBasicControlPanel" )
{
}
+223
View File
@@ -0,0 +1,223 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Clients CBaseObject
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASEOBJECT_H
#define C_BASEOBJECT_H
#ifdef _WIN32
#pragma once
#endif
#include "baseobject_shared.h"
#include <vgui_controls/Panel.h>
#include <vgui_controls/Label.h>
#include "vgui_healthbar.h"
#include "commanderoverlay.h"
#include "hud_minimap.h"
#include "particlemgr.h"
#include "particle_prototype.h"
#include "particle_util.h"
#include "c_basecombatcharacter.h"
#include "ihasbuildpoints.h"
class C_BaseTFPlayer;
// Max Length of ID Strings
#define MAX_ID_STRING 256
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BaseObject : public C_BaseCombatCharacter, public IHasBuildPoints
{
DECLARE_CLASS( C_BaseObject, C_BaseCombatCharacter );
public:
DECLARE_CLIENTCLASS();
DECLARE_ENTITY_PANEL();
DECLARE_MINIMAP_PANEL();
C_BaseObject();
~C_BaseObject( void );
virtual bool IsBaseObject( void ) const { return true; }
virtual bool IsAnUpgrade(void ) const { return false; }
virtual bool IsAVehicle( void ) const { return false; }
virtual void SetType( int iObjectType );
virtual void AddEntity();
virtual void Select( void );
void SetActivity( Activity act );
Activity GetActivity( ) const;
void SetObjectSequence( int sequence );
virtual void OnActivityChanged( Activity act );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void Release( void );
virtual int GetHealth() const { return m_iHealth; }
void SetHealth( int health ) { m_iHealth = health; }
virtual int GetMaxHealth() const { return m_iMaxHealth; }
int GetObjectFlags( void ) { return m_fObjectFlags; }
void SetObjectFlags( int flags ) { m_fObjectFlags = flags; }
// Derive to customize an object's attached version
virtual void SetupAttachedVersion( void ) { return; }
virtual void SetupUnattachedVersion( void ) { return; }
virtual void OnLostPower( void ) { return; };
virtual const char *GetTargetDescription( void ) const;
virtual char *GetIDString( void );
virtual bool IsValidIDTarget( void );
void AttemptToGoActive( void );
virtual bool ShouldBeActive( void );
virtual void OnGoActive( void );
virtual void OnGoInactive( void );
virtual void SetDormant( bool bDormant );
void SendClientCommand( const char *pCmd );
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
// Builder preview...
void ActivateYawPreview( bool enable );
void PreviewYaw( float yaw );
bool IsPreviewingYaw() const;
// This is called to get the initial builder yaw...
virtual float GetInitialBuilderYaw();
virtual void RecalculateIDString( void );
int GetType() const { return m_iObjectType; }
bool IsOwnedByLocalPlayer() const;
C_BaseTFPlayer *GetOwner();
// Are we under attack?
bool IsUnderAttack( );
virtual int DrawModel( int flags );
virtual bool IsIdentityBrush( void );
// Effects
void DrawRunningEffects( void );
void DrawBuildEffects( void );
void DrawDamageEffects( void );
// Deterioration
bool IsDeteriorating( void ) { return m_bDeteriorating; };
float GetPercentageConstructed( void ) { return m_flPercentageConstructed; }
bool IsPlacing( void ) const { return m_bPlacing; }
bool IsBuilding( void ) const { return m_bBuilding; }
virtual void FinishedBuilding( void ) { return; }
virtual bool OffsetObjectOrigin( Vector& origin );
virtual const char* GetStatusName() const;
// Object Previews
void HighlightBuildPoints( int flags );
public:
// Client/Server shared build point code
void CreateBuildPoints( void );
void AddAndParseBuildPoint( int iAttachmentNumber, KeyValues *pkvBuildPoint );
virtual int AddBuildPoint( int iAttachmentNum );
virtual void AddValidObjectToBuildPoint( int iPoint, int iObjectType );
virtual CBaseObject *GetBuildPointObject( int iPoint );
bool IsBuiltOnAttachment( void ) { return (m_hBuiltOnEntity != NULL); }
void AttachObjectToObject( CBaseEntity *pEntity, int iPoint, Vector &vecOrigin );
CBaseObject *GetParentObject( void );
void SetBuildPointPassenger( int iPoint, int iPassenger );
int GetBuildPointPassenger( int iPoint ) const;
// Build points
CUtlVector<BuildPoint_t> m_BuildPoints;
// Power
bool IsPowered( void );
virtual bool CanPowerupEver( int iPowerup );
virtual bool CanPowerupNow( int iPowerup );
bool IsDisabled( void ) { return m_bDisabled; }
virtual float GetSapperAttachTime( void );
// IHasBuildPoints
public:
virtual int GetNumBuildPoints( void ) const;
virtual bool GetBuildPoint( int iPoint, Vector &vecOrigin, QAngle &vecAngles );
virtual int GetBuildPointAttachmentIndex( int iPoint ) const;
virtual bool CanBuildObjectOnBuildPoint( int iPoint, int iObjectType );
virtual void SetObjectOnBuildPoint( int iPoint, CBaseObject *pObject );
virtual float GetMaxSnapDistance( int iBuildPoint );
virtual bool ShouldCheckForMovement( void ) { return true; }
virtual int GetNumObjectsOnMe( void );
virtual CBaseEntity *GetFirstObjectOnMe( void );
virtual CBaseObject *GetObjectOfTypeOnMe( int iObjectType );
virtual void RemoveAllObjects( void );
virtual int FindObjectOnBuildPoint( CBaseObject *pObject );
virtual void GetExitPoint( CBaseEntity *pPlayer, int iPoint, Vector *pAbsOrigin, QAngle *pAbsAngles );
virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
protected:
char m_szIDString[ MAX_ID_STRING ];
private:
enum
{
YAW_PREVIEW_OFF = 0,
YAW_PREVIEW_ON,
YAW_PREVIEW_WAITING_FOR_UPDATE
};
Activity m_Activity;
int m_fObjectFlags;
float m_fYawPreview;
char m_YawPreviewState;
CHandle< C_BaseTFPlayer > m_hOldOwner;
CHandle< C_BaseTFPlayer > m_hBuilder;
bool m_bWasActive;
int m_iOldHealth;
bool m_bHasSapper;
bool m_bOldSapper;
int m_iObjectType;
int m_iHealth;
int m_iMaxHealth;
bool m_bWasBuilding;
bool m_bBuilding;
bool m_bPlacing;
bool m_bDeteriorating;
bool m_bDisabled;
float m_flPercentageConstructed;
EHANDLE m_hBuiltOnEntity;
CHealthBarPanel *m_pHealthBar;
vgui::Label *m_pNameLabel;
float m_flDamageFlash; // Used to flash the panel when the object takes damage
int m_iFlashes;
float m_flAttackTime;
CMaterialReference m_ThermalMaterial;
// Effects
float m_flNextEffect;
private:
C_BaseObject( const C_BaseObject & ); // not defined, not accessible
};
#endif // C_BASEOBJECT_H
File diff suppressed because it is too large Load Diff
+386
View File
@@ -0,0 +1,386 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if !defined( C_BASETFPLAYER_H )
#define C_BASETFPLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_vehicleshared.h"
#include "c_baseplayer.h"
#include "CommanderOverlay.h"
#include "hud_minimap.h"
#include "hud_targetreticle.h"
#include "c_tfplayerlocaldata.h"
#include "particlemgr.h"
#include "particle_prototype.h"
#include "particle_util.h"
#include "tf_playeranimstate.h"
class C_VehicleTeleportStation;
class CViewSetup;
class IMaterial;
class C_Order;
class C_BaseObject;
class C_PlayerClass;
class CPersonalShieldEffect;
class CBasePredictedWeapon;
class C_BaseViewModel;
class CUserCmd;
class C_WeaponCombatShield;
//-----------------------------------------------------------------------------
// Purpose: Client Side TF Player entity
//-----------------------------------------------------------------------------
class C_BaseTFPlayer : public C_BasePlayer
{
public:
DECLARE_CLASS( C_BaseTFPlayer, C_BasePlayer );
DECLARE_CLIENTCLASS();
DECLARE_ENTITY_PANEL();
DECLARE_MINIMAP_PANEL();
DECLARE_PREDICTABLE();
C_BaseTFPlayer();
virtual ~C_BaseTFPlayer();
private:
void Clear(); // Clear all elements.
public:
bool IsHidden() const;
bool IsDamageBoosted() const;
bool HasNamedTechnology( const char *name );
float LastAttackTime() const { return m_flLastAttackTime; }
void SetLastAttackTime( float flTime ) { m_flLastAttackTime = flTime; }
// Return this client's C_BaseTFPlayer pointer
static C_BaseTFPlayer* GetLocalPlayer( void )
{
return ( static_cast< C_BaseTFPlayer * >( C_BasePlayer::GetLocalPlayer() ) );
}
virtual void ClientThink( void );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void ReceiveMessage( int classID, bf_read &msg );
virtual void Release( void );
virtual void ItemPostFrame( void );
virtual bool ShouldDraw();
virtual int DrawModel( int flags );
virtual void SetDormant( bool bDormant );
virtual void GetBoneControllers(float controllers[MAXSTUDIOBONES]);
virtual int GetRenderTeamNumber( void );
virtual void ComputeFxBlend( void );
virtual bool IsTransparent( void );
// Called by the view model if its rendering is being overridden.
virtual bool ViewModel_IsTransparent( void );
virtual bool IsOverridingViewmodel( void );
virtual int DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags );
virtual void CreateMove( float flInputSampleTime, CUserCmd *pCmd );
virtual float GetDefaultAnimSpeed( void );
int GetClass( void );
// Called when not in tactical mode. Allows view to be overriden for things like driving a tank.
void OverrideView( CViewSetup *pSetup );
// Called when not in tactical mode. Allows view model drawing to be disabled for things like driving a tank.
bool ShouldDrawViewModel();
void GetTargetDescription( char *pDest, int bufferSize );
// Orders
void SetPersonalOrder( C_Order *pOrder );
void RemoveOrderTarget();
// Resources
int GetBankResources( void );
// Objects
void SetSelectedObject( C_BaseObject *pObject );
C_BaseObject *GetSelectedObject( void );
int GetNumObjects( int iObjectType );
int GetObjectCount( void );
C_BaseObject *GetObject( int index );
// Targets
void Add_Target( C_BaseEntity *pTarget, const char *sName );
void Remove_Target( C_BaseEntity *pTarget );
void Remove_Target( CTargetReticle *pTargetReticle );
void UpdateTargetReticles( void );
bool IsUsingThermalVision( void ) const;
// Weapon handling
virtual bool IsAllowedToSwitchWeapons( void );
virtual bool Weapon_ShouldSetLast( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
virtual bool Weapon_ShouldSelectItem( CBaseCombatWeapon *pWeapon );
virtual C_BaseCombatWeapon *GetActiveWeaponForSelection( void );
virtual C_BaseCombatWeapon *GetLastWeaponBeforeObject( void ) { return m_hLastWeaponBeforeObject; }
virtual C_BaseAnimating* GetRenderedWeaponModel();
// ID Target
void SetIDEnt( C_BaseEntity *pEntity );
int GetIDTarget( void ) const;
void UpdateIDTarget( void );
bool IsKnockedDown( void ) const;
void CheckKnockdownState( void );
bool CheckKnockdownAngleOverride( void ) const;
void SetKnockdownAngles( const QAngle& ang );
void GetKnockdownAngles( QAngle& outAngles );
float GetKnockdownViewheightAdjust( void ) const;
// Team handling
virtual void TeamChange( int iNewTeam );
// Camouflage effect
virtual bool IsCamouflaged( void );
virtual float GetCamouflageAmount( void );
virtual float ComputeCamoEffectAmount( void ); // 0 - visible, 1 = invisible
virtual int ComputeCamoAlpha( void );
virtual void CheckCamoDampening( void );
virtual void SetCamoDampening( float amount );
virtual float GetDampeningAmount( void );
virtual void CheckCameraMovement( void );
IMaterial *GetCamoMaterial( void );
virtual float GetMovementCamoSuppression( void );
virtual void CheckMovementCamoSuppression( void );
virtual void SetMovementCamoSuppression( float amount );
// Adrenalin
void CheckAdrenalin( void );
void CheckLastMovement( void );
float GetLastMoveTime( void );
float GetOverlayAlpha( void );
float GetLastDamageTime( void ) const;
float GetLastGainHealthTime( void ) const;
// Powerups
virtual void PowerupStart( int iPowerup, bool bInitial );
virtual void PowerupEnd( int iPowerup );
// Sniper
bool IsDeployed( void );
bool IsDeploying( void );
bool IsUnDeploying( void );
virtual void AddEntity( void );
// Vertification
inline bool HasClass( void ) { return GetPlayerClass() != NULL; }
bool IsClass( TFClass iClass );
virtual int GetMaxHealth() const { return m_iMaxHealth; }
bool ClassProxyUpdate( int nClassID );
// Should this object cast shadows?
virtual ShadowType_t ShadowCastType();
// Prediction stuff
virtual void PreThink( void );
virtual void PostThink( void );
// Combat prototyping
bool IsBlocking( void ) const { return m_bIsBlocking; }
bool IsParrying( void ) const { return m_bIsParrying; }
void SetBlocking( bool bBlocking ) { m_bIsBlocking = bBlocking; }
void SetParrying( bool bParrying ) { m_bIsParrying = bParrying; }
// Vehicles
void SetVehicleRole( int nRole );
bool CanGetInVehicle( void );
// Returns true if we're in a vehicle and it's mounted on another vehicle
// (ie: are we in a manned gun that's mounted on a tank).
bool IsVehicleMounted() const;
virtual bool IsUseableEntity( CBaseEntity *pEntity );
// Shared Client / Server code
public:
bool IsHittingShield( const Vector &vecVelocity, float *flDamage );
C_WeaponCombatShield *GetCombatShield( void );
virtual void PainSound( void );
public:
// Data for only the local player
CTFPlayerLocalData m_TFLocal;
// Accessors...
const QAngle& DeployedAngles() const { return m_vecDeployedAngles; }
int ZoneState() const { return m_iCurrentZoneState; }
float CamouflageAmount() const { return m_flCamouflageAmount; }
int PlayerClass() const { return m_iPlayerClass; }
C_PlayerClass *GetPlayerClass();
C_Order *PersonalOrder() { return m_hPersonalOrder; }
C_BaseEntity *SpawnPoint() { return m_hSpawnPoint.Get(); }
C_VehicleTeleportStation* GetSelectedMCV() const;
// Object sapper placement handling
//float m_flSapperAttachmentFinishTime;
//float m_flSapperAttachmentStartTime;
//CHandle< CGrenadeObjectSapper > m_hSapper;
//CHandle< CBaseObject > m_hSappedObject;
CHealthBarPanel *m_pSapperAttachmentStatus;
private:
C_BaseTFPlayer( const C_BaseTFPlayer & );
// Client-side obstacle avoidance
void PerformClientSideObstacleAvoidance( float flFrameTime, CUserCmd *pCmd );
float m_flLastAttackTime;
EHANDLE m_hSelectedMCV;
// Weapon used before switching to an object placement
CHandle<C_BaseCombatWeapon> m_hLastWeaponBeforeObject;
float m_flCamouflageAmount;
// Movement.
Vector m_vecPosDelta;
enum { MOMENTUM_MAXSIZE = 10 };
float m_aMomentum[MOMENTUM_MAXSIZE];
int m_iMomentumHead;
// Player Class
int m_iPlayerClass;
C_AllPlayerClasses m_PlayerClasses;
// Spawn location...
EHANDLE m_hSpawnPoint;
// Orders
CHandle< C_Order > m_hSelectedOrder;
CHandle< C_Order > m_hPersonalOrder;
int m_iSelectedTarget;
int m_iPersonalTarget;
CUtlVector< CTargetReticle * > m_aTargetReticles; // A list of entities to show target reticles for
// Objects
CHandle< C_BaseObject > m_hSelectedObject;
int m_iLastHealth;
bool m_bIsBlocking;
bool m_bIsParrying;
bool m_bUnderAttack;
int m_iMaxHealth;
bool m_bDeployed;
bool m_bDeploying;
bool m_bUnDeploying;
QAngle m_vecDeployedAngles;
int m_iCurrentZoneState;
int m_TFPlayerFlags;
int m_nOldTacticalView;
int m_nOldPlayerClass;
float m_flNextUseCheck;
bool m_bOldThermalVision;
bool m_bOldAttachingSapper;
bool m_bOldKnockDownState;
float m_flStartKnockdown;
float m_flEndKnockdown;
QAngle m_vecOriginalViewAngles;
QAngle m_vecCurrentKnockdownAngles;
QAngle m_vecKnockDownGoalAngles;
bool m_bKnockdownOverrideAngles;
float m_flKnockdownViewheightAdjust;
CPlayerAnimState m_PlayerAnimState;
// For sniper hiding
float m_flLastMoveTime;
Vector m_vecLastOrigin;
// For material proxies
float m_flLastDamageTime;
float m_flLastGainHealthTime;
IMaterial *m_pThermalMaterial;
IMaterial *m_pCamoEffectMaterial;
// Camouflage
float m_flDampeningAmount;
float m_flGoalDampeningAmount;
float m_flDampeningStayoutTime;
// Suppression of camo based on movement
float m_flMovementCamoSuppression;
float m_flGoalMovementCamoSuppressionAmount;
float m_flMovementCamoSuppressionStayoutTime;
// Adrenalin
float m_flNextAdrenalinEffect;
bool m_bFadingIn;
// ID Target
int m_iIDEntIndex;
CMaterialReference m_BoostMaterial;
CMaterialReference m_EMPMaterial;
float m_BoostModelAngles[3];
// Personal shield effects.
CUtlLinkedList<CPersonalShieldEffect*, int> m_PersonalShieldEffects;
CHandle< C_WeaponCombatShield > m_hWeaponCombatShield;
// No one should call this
C_BaseTFPlayer& operator=( const C_BaseTFPlayer& src );
friend void RecvProxy_PlayerClass( const CRecvProxyData *pData, void *pStruct, void *pOut );
friend class CTFPrediction;
};
int GetLocalPlayerClass( void );
bool IsLocalPlayerClass( int iClass );
bool IsLocalPlayerInTactical( );
inline C_BaseTFPlayer *ToBaseTFPlayer( C_BaseEntity *pEntity )
{
if ( !pEntity || !pEntity->IsPlayer() )
return NULL;
#if _DEBUG
return dynamic_cast<C_BaseTFPlayer *>( pEntity );
#else
return static_cast<C_BaseTFPlayer *>( pEntity );
#endif
}
#endif // C_BASETFPLAYER_H
+67
View File
@@ -0,0 +1,67 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_controlzone.h"
#include "mapdata.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ControlZone::C_ControlZone()
{
m_nZoneNumber = 0;
m_pShowTriggers = cvar->FindVar("showtriggers");
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ControlZone::~C_ControlZone()
{
}
//-----------------------------------------------------------------------------
// Purpose: Are we using showtriggers?
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_ControlZone::ShouldDraw()
{
if ( !m_pShowTriggers )
return false;
return m_pShowTriggers->GetInt() != 0 ? true : false;
}
//-----------------------------------------------------------------------------
// Purpose: Update global map state based on data received
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_ControlZone::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
CMapZones *zone;
if ( m_nZoneNumber < 1 ||
m_nZoneNumber > MAX_ZONES )
return;
zone = &MapData().m_Zones[ m_nZoneNumber -1 ];
zone->m_nControllingTeam = GetTeamNumber();
}
IMPLEMENT_CLIENTCLASS_DT(C_ControlZone, DT_ControlZone, CControlZone)
RecvPropInt( RECVINFO(m_nZoneNumber )),
END_RECV_TABLE()
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#if !defined( C_CONTROLZONE_H )
#define C_CONTROLZONE_H
#ifdef _WIN32
#pragma once
#endif
class ConVar;
//-----------------------------------------------------------------------------
// Purpose: Client side rep of control zone entity ( trigger, so not usually visible )
//-----------------------------------------------------------------------------
class C_ControlZone : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ControlZone, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_ControlZone();
virtual ~C_ControlZone();
virtual bool ShouldDraw();
virtual void OnDataChanged( DataUpdateType_t updateType );
public:
int m_nZoneNumber;
private:
const ConVar *m_pShowTriggers;
};
#endif // C_CONTROLZONE_H
+35
View File
@@ -0,0 +1,35 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_demo_entities.h"
IMPLEMENT_CLIENTCLASS_DT(C_Cycler_TF2Commando, DT_Cycler_TF2Commando, CCycler_TF2Commando)
RecvPropInt( RECVINFO(m_bShieldActive) ),
RecvPropFloat( RECVINFO(m_flShieldRaiseTime) ),
RecvPropFloat( RECVINFO(m_flShieldLowerTime) ),
END_RECV_TABLE()
C_Cycler_TF2Commando::C_Cycler_TF2Commando()
{
}
float C_Cycler_TF2Commando::GetShieldRaiseTime() const
{
return m_bShieldActive ? gpGlobals->curtime - m_flShieldRaiseTime : 0.0f;
}
float C_Cycler_TF2Commando::GetShieldLowerTime() const
{
return !m_bShieldActive ? gpGlobals->curtime - m_flShieldLowerTime : 0.0f;
}
bool C_Cycler_TF2Commando::IsShieldActive() const
{
return m_bShieldActive;
}
+36
View File
@@ -0,0 +1,36 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_DEMO_ENTITIES_H
#define C_DEMO_ENTITIES_H
#include "c_ai_basenpc.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_Cycler_TF2Commando : public C_AI_BaseNPC
{
DECLARE_CLASS( C_Cycler_TF2Commando, C_AI_BaseNPC );
public:
DECLARE_CLIENTCLASS();
C_Cycler_TF2Commando();
float GetShieldRaiseTime() const;
float GetShieldLowerTime() const;
bool IsShieldActive() const;
private:
C_Cycler_TF2Commando( const C_Cycler_TF2Commando& );
bool m_bShieldActive;
float m_flShieldRaiseTime;
float m_flShieldLowerTime;
};
#endif // C_DEMO_ENTITIES_H
+179
View File
@@ -0,0 +1,179 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's Meteor
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_effect_shootingstar.h"
#include "clienteffectprecachesystem.h"
//=============================================================================
//
// Shooting Star Spawner Functionality
//
IMPLEMENT_CLIENTCLASS_DT( C_ShootingStarSpawner, DT_ShootingStarSpawner, CShootingStarSpawner )
RecvPropFloat( RECVINFO( m_flSpawnInterval ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ShootingStarSpawner::C_ShootingStarSpawner( void )
{
SetNextClientThink( gpGlobals->curtime + m_flSpawnInterval );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ShootingStarSpawner::ClientThink( void )
{
// Spawn a number of shooting stars.
SpawnShootingStars();
// Randomly generate a next think time.
SetNextClientThink( gpGlobals->curtime + random->RandomFloat( 0.25, m_flSpawnInterval ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ShootingStarSpawner::SpawnShootingStars( void )
{
C_ShootingStar *pShootingStar = new C_ShootingStar;
if ( pShootingStar )
{
// In Space.
pShootingStar->SetFriction( 1.0f );
pShootingStar->SetGravity( 0.0f );
// Randomize the velocity. -- This isn't right, but works for the test!
Vector vecVelocity;
vecVelocity.x = ( GetAbsAngles().x ) * random->RandomFloat( 1.0f, 10.0f );
vecVelocity.y = ( GetAbsAngles().y ) * random->RandomFloat( 1.0f, 10.0f );
vecVelocity.z = ( GetAbsAngles().z ) * random->RandomFloat( 1.0f, 10.0f );
pShootingStar->Init( GetAbsOrigin(), vecVelocity, random->RandomFloat( 10.0f, 100.0f ), random->RandomFloat( 10.0f, 30.0f ) );
}
}
//=============================================================================
//
// Shooting Star Functionality
//
//Precahce the effects
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectShootingStars )
CLIENTEFFECT_MATERIAL( "effects/redflare" )
CLIENTEFFECT_REGISTER_END()
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
C_ShootingStar::C_ShootingStar( void ) : CSimpleEmitter( "ShootingStar" )
{
m_flScale = 1.0f;
SetDynamicallyAllocated( false );
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
C_ShootingStar::~C_ShootingStar( void )
{
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
void C_ShootingStar::Init( const Vector vecOrigin, const Vector vecVelocity, int nSize,
float flLifeTime )
{
// Set the sort origin.
SetSortOrigin( vecOrigin );
// Create the initial particle and set the data.
SimpleParticle *pParticle = ( SimpleParticle* )AddParticle( sizeof( SimpleParticle ), GetPMaterial( "effects/redflare" ), vecOrigin );
if ( pParticle )
{
pParticle->m_vecVelocity = vecVelocity;
pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = 255;
pParticle->m_flRoll = random->RandomInt( 0, 360 );
pParticle->m_flRollDelta = random->RandomFloat( 1.0f, 4.0f );
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = flLifeTime;
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartSize = nSize;
pParticle->m_uchEndSize = ( nSize / 3 );
}
int iParticle = m_aParticles.AddToTail();
m_aParticles[iParticle] = pParticle;
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
void C_ShootingStar::Destroy( void )
{
// Destroy shooting star particles.
int nParticleCount = m_aParticles.Count();
for ( int iParticle = ( nParticleCount - 1 ); iParticle >= 0; iParticle-- )
{
SimpleParticle *pParticle = m_aParticles[iParticle];
m_aParticles.Remove( iParticle );
CSimpleEmitter::NotifyDestroyParticle( pParticle );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ShootingStar::SetSortOrigin( const Vector &vSortOrigin )
{
CSimpleEmitter::SetSortOrigin( vSortOrigin );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : timeDelta -
//-----------------------------------------------------------------------------
void C_ShootingStar::Update( float timeDelta )
{
// Parent update.
CSimpleEmitter::Update( timeDelta );
// Don't update if the console is down.
if ( timeDelta <= 0.0f )
return;
// Are we still alive? Get the tail of the shooting star (last valid index)
// and test.
int nParticleCount = m_aParticles.Count();
if ( nParticleCount <= 0 )
return;
SimpleParticle *pParticle = m_aParticles[nParticleCount-1];
if ( pParticle->m_flLifetime >= pParticle->m_flDieTime )
{
Destroy();
return;
}
// Update the particles lifetime.
pParticle->m_flLifetime += timeDelta;
// Update the particle position.
pParticle->m_Pos += ( pParticle->m_vecVelocity * timeDelta );
SetLocalOrigin( pParticle->m_Pos );
SetSortOrigin( GetAbsOrigin() );
}
+72
View File
@@ -0,0 +1,72 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's Meteor
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_EFFECT_SHOOTINGSTAR_H
#define C_EFFECT_SHOOTINGSTAR_H
#pragma once
#include "c_baseanimating.h"
#include "particles_simple.h"
class C_ShootingStar;
//=============================================================================
//
// Client-side shooting star spawner.
//
class C_ShootingStarSpawner : public C_BaseEntity
{
DECLARE_CLASS( C_ShootingStarSpawner, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_ShootingStarSpawner();
void ClientThink( void );
void SpawnShootingStars( void );
public:
float m_flSpawnInterval; // How often do I spawn meteors?
};
//=============================================================================
//
// Shooting Star Effect
//
class C_ShootingStar : public C_BaseAnimating, CSimpleEmitter
{
DECLARE_CLASS( C_ShootingStar, C_BaseAnimating );
public:
C_ShootingStar( );
~C_ShootingStar( void );
void Init( const Vector vecOrigin, const Vector vecVelocity, int nSize, float flLifeTime );
void Destroy( void );
void Update( float timeDelta );
public:
float m_flScale;
private:
void SetSortOrigin( const Vector &vSortOrigin );
private:
C_ShootingStar( const C_ShootingStar & );
CUtlVector<SimpleParticle*> m_aParticles;
};
#endif // C_EFFECT_SHOOTINGSTAR_H
+85
View File
@@ -0,0 +1,85 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_entity_burn_effect.h"
#define NUM_BURN_PARTICLES_PER_SEC 50
IMPLEMENT_CLIENTCLASS_DT( C_EntityBurnEffect, DT_EntityBurnEffect, CEntityBurnEffect )
RecvPropInt( RECVINFO( m_hBurningEntity ) )
END_RECV_TABLE()
C_EntityBurnEffect::C_EntityBurnEffect()
{
m_pEmitter = CSimpleEmitter::Create( "Entity burn effect" );
if ( m_pEmitter.IsValid() )
{
m_hFireMaterial = m_pEmitter->GetPMaterial( "particle/fire" );
}
else
{
m_hFireMaterial = INVALID_MATERIAL_HANDLE;
}
m_Timer.Init( NUM_BURN_PARTICLES_PER_SEC );
}
void C_EntityBurnEffect::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
void C_EntityBurnEffect::ClientThink()
{
if ( !m_pEmitter.IsValid() || IsDormant() )
return;
// Add some burning particles to our target entity.
C_BaseEntity *pEnt = ClientEntityList().GetBaseEntity( m_hBurningEntity );
if ( !pEnt )
return;
float dt = gpGlobals->frametime;
while ( m_Timer.NextEvent( dt ) )
{
Vector vDims = (pEnt->WorldAlignMaxs() - pEnt->WorldAlignMins()) * 0.5f;
Vector vCenter = pEnt->GetAbsOrigin() + pEnt->WorldAlignMins() + vDims;
Vector vPos = vCenter + vDims * RandomVector( -0.7, 0.7 );
float flLifetime = 1;
float flRadius = 3;
unsigned char uchColor[4] = { 255, 100, 0, 100 };
SimpleParticle *pParticle = m_pEmitter->AddSimpleParticle( m_hFireMaterial, vPos, flLifetime, flRadius );
if ( pParticle )
{
pParticle->m_uchColor[0] = uchColor[0];
pParticle->m_uchColor[1] = uchColor[1];
pParticle->m_uchColor[2] = uchColor[2];
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartAlpha = uchColor[3];
pParticle->m_vecVelocity.x = RandomFloat( -2, 2 );
pParticle->m_vecVelocity.y = RandomFloat( -2, 2 );
pParticle->m_vecVelocity.z = RandomFloat( 3, 29 );
// Pick up some velocity from the burning guy running around.
pParticle->m_vecVelocity += pEnt->GetAbsVelocity() * 0.6;
}
}
}
+44
View File
@@ -0,0 +1,44 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ENTITY_BURN_EFFECT_H
#define C_ENTITY_BURN_EFFECT_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "particle_util.h"
#include "particles_simple.h"
class C_EntityBurnEffect : public C_BaseEntity
{
public:
DECLARE_CLASS( C_EntityBurnEffect, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_EntityBurnEffect();
// Overrides.
public:
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink();
private:
int m_hBurningEntity; // todo: this should be an ehandle but base networkables aren't setup for ehandles yet.
TimedEvent m_Timer;
CSmartPtr<CSimpleEmitter> m_pEmitter;
PMaterialHandle m_hFireMaterial;
};
#endif // C_ENTITY_BURN_EFFECT_H
+651
View File
@@ -0,0 +1,651 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "C_Env_Meteor.h"
#include "fx_explosion.h"
#include "tempentity.h"
#include "c_tracer.h"
//=============================================================================
//
// Meteor Factory Functions
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_MeteorFactory::CreateMeteor( int nID, int iType,
const Vector &vecPosition, const Vector &vecDirection,
float flSpeed, float flStartTime, float flDamageRadius,
const Vector &vecTriggerMins, const Vector &vecTriggerMaxs )
{
C_EnvMeteor::Create( nID, iType, vecPosition, vecDirection, flSpeed, flStartTime, flDamageRadius,
vecTriggerMins, vecTriggerMaxs );
}
//=============================================================================
//
// Meteor Spawner Functions
//
void RecvProxy_MeteorTargetPositions( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CEnvMeteorSpawnerShared *pSpawner = ( CEnvMeteorSpawnerShared* )pStruct;
pSpawner->m_aTargets[pData->m_iElement].m_vecPosition.x = pData->m_Value.m_Vector[0];
pSpawner->m_aTargets[pData->m_iElement].m_vecPosition.y = pData->m_Value.m_Vector[1];
pSpawner->m_aTargets[pData->m_iElement].m_vecPosition.z = pData->m_Value.m_Vector[2];
}
void RecvProxy_MeteorTargetRadii( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CEnvMeteorSpawnerShared *pSpawner = ( CEnvMeteorSpawnerShared* )pStruct;
pSpawner->m_aTargets[pData->m_iElement].m_flRadius = pData->m_Value.m_Float;
}
void RecvProxyArrayLength_MeteorTargets( void *pStruct, int objectID, int currentArrayLength )
{
CEnvMeteorSpawnerShared *pSpawner = ( CEnvMeteorSpawnerShared* )pStruct;
if ( pSpawner->m_aTargets.Count() < currentArrayLength )
{
pSpawner->m_aTargets.SetSize( currentArrayLength );
}
}
BEGIN_RECV_TABLE_NOBASE( CEnvMeteorSpawnerShared, DT_EnvMeteorSpawnerShared )
// Setup (read from) Worldcraft.
RecvPropInt ( RECVINFO( m_iMeteorType ) ),
RecvPropInt ( RECVINFO( m_bSkybox ) ),
RecvPropFloat ( RECVINFO( m_flMinSpawnTime ) ),
RecvPropFloat ( RECVINFO( m_flMaxSpawnTime ) ),
RecvPropInt ( RECVINFO( m_nMinSpawnCount ) ),
RecvPropInt ( RECVINFO( m_nMaxSpawnCount ) ),
RecvPropFloat ( RECVINFO( m_flMinSpeed ) ),
RecvPropFloat ( RECVINFO( m_flMaxSpeed ) ),
// Setup through Init.
RecvPropFloat ( RECVINFO( m_flStartTime ) ),
RecvPropInt ( RECVINFO( m_nRandomSeed ) ),
RecvPropVector ( RECVINFO( m_vecMinBounds ) ),
RecvPropVector ( RECVINFO( m_vecMaxBounds ) ),
RecvPropVector ( RECVINFO( m_vecTriggerMins ) ),
RecvPropVector ( RECVINFO( m_vecTriggerMaxs ) ),
// Target List
RecvPropArray2( RecvProxyArrayLength_MeteorTargets,
RecvPropVector( "meteortargetposition_array_element", 0, 0, 0, RecvProxy_MeteorTargetPositions ),
16, 0, "meteortargetposition_array" ),
RecvPropArray2( RecvProxyArrayLength_MeteorTargets,
RecvPropFloat( "meteortargetradius_array_element", 0, 0, 0, RecvProxy_MeteorTargetRadii ),
16, 0, "meteortargetradius_array" )
END_RECV_TABLE()
// This table encodes the CBaseEntity data.
IMPLEMENT_CLIENTCLASS_DT( C_EnvMeteorSpawner, DT_EnvMeteorSpawner, CEnvMeteorSpawner )
RecvPropDataTable ( RECVINFO_DT( m_SpawnerShared ), 0, &REFERENCE_RECV_TABLE( DT_EnvMeteorSpawnerShared ) ),
RecvPropInt ( RECVINFO( m_fDisabled ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
C_EnvMeteorSpawner::C_EnvMeteorSpawner()
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorSpawner::OnDataChanged( DataUpdateType_t updateType )
{
// Initialize the client side spawner.
m_SpawnerShared.Init( &m_Factory, m_SpawnerShared.m_nRandomSeed, m_SpawnerShared.m_flStartTime,
m_SpawnerShared.m_vecMinBounds, m_SpawnerShared.m_vecMaxBounds,
m_SpawnerShared.m_vecTriggerMins, m_SpawnerShared.m_vecTriggerMaxs );
// Set the next think to be the next spawn interval.
if ( !m_fDisabled )
{
SetNextClientThink( m_SpawnerShared.m_flNextSpawnTime );
}
}
#if 0
// Will probably be used later!!
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorSpawner::ReceiveMessage( int classID, bf_read &msg )
{
if ( classID != GetClientClass()->m_ClassID )
{
// message is for subclass
BaseClass::ReceiveMessage( classID, msg );
return;
}
m_SpawnerShared.m_flStartTime = msg.ReadLong();
m_SpawnerShared.m_flNextSpawnTime = msg.ReadLong();
SetNextClientThink( m_SpawnerShared.m_flNextSpawnTime );
}
#endif
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorSpawner::ClientThink( void )
{
SetNextClientThink( m_SpawnerShared.MeteorThink( gpGlobals->curtime ) );
}
//=============================================================================
//
// Meteor Tail Functions
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
C_EnvMeteorHead::C_EnvMeteorHead()
{
m_vecPos.Init();
m_vecPrevPos.Init();
m_flParticleScale = 1.0f;
m_pSmokeEmitter = NULL;
m_flSmokeSpawnInterval = 0.0f;
m_hSmokeMaterial = INVALID_MATERIAL_HANDLE;
m_flSmokeLifetime = 2.5f;
m_bEmitSmoke = true;
m_hFlareMaterial = INVALID_MATERIAL_HANDLE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
C_EnvMeteorHead::~C_EnvMeteorHead()
{
Destroy();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorHead::Start( const Vector &vecOrigin, const Vector &vecDirection )
{
// Emitters.
m_pSmokeEmitter = CSimpleEmitter::Create( "MeteorTrail" );
// m_pFireEmitter = CSimpleEmitter::Create( "MeteorFire" );
if ( !m_pSmokeEmitter /*|| !m_pFireEmitter*/ )
return;
// Smoke
m_pSmokeEmitter->SetSortOrigin( vecOrigin );
m_hSmokeMaterial = m_pSmokeEmitter->GetPMaterial( "particle/SmokeStack" );
Assert( m_hSmokeMaterial != INVALID_MATERIAL_HANDLE );
// Fire
// m_pFireEmitter->SetSortOrigin( vecOrigin );
// m_hFireMaterial = m_pFireEmitter->GetPMaterial( "particle/particle_fire" );
// Assert( m_hFireMaterial != INVALID_MATERIAL_HANDLE );
// Flare
// m_hFlareMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/redflare" );
VectorCopy( vecDirection, m_vecDirection );
VectorCopy( vecOrigin, m_vecPos );
m_bInitThink = true;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorHead::Destroy( void )
{
m_pSmokeEmitter = NULL;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorHead::MeteorHeadThink( const Vector &vecOrigin, float flTime )
{
if ( m_bInitThink )
{
VectorCopy( vecOrigin, m_vecPrevPos );
m_bInitThink = false;
}
// Update the position of the emitters.
VectorCopy( vecOrigin, m_vecPos );
// Update Smoke
if ( m_pSmokeEmitter.IsValid() && m_bEmitSmoke )
{
m_pSmokeEmitter->SetSortOrigin( m_vecPos );
// Get distance covered
Vector vecDelta;
VectorSubtract( m_vecPos, m_vecPrevPos, vecDelta );
float flLength = vecDelta.Length();
int nParticleCount = flLength / 35.0f;
if ( nParticleCount < 1 )
{
nParticleCount = 1;
}
flLength /= nParticleCount;
Vector vecPos;
for( int iParticle = 0; iParticle < nParticleCount; ++iParticle )
{
vecPos = m_vecPrevPos + ( m_vecDirection * ( flLength * iParticle ) );
// Add some noise to the position.
Vector vecPosOffset;
vecPosOffset.Random( -m_flSmokeSpawnRadius, m_flSmokeSpawnRadius );
VectorAdd( vecPosOffset, vecPos, vecPosOffset );
SimpleParticle *pParticle = ( SimpleParticle* )m_pSmokeEmitter->AddParticle( sizeof( SimpleParticle ),
m_hSmokeMaterial,
vecPosOffset );
if ( pParticle )
{
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = m_flSmokeLifetime;
// Add just a little movement.
pParticle->m_vecVelocity.Random( -5.0f, 5.0f );
pParticle->m_uchColor[0] = 255.0f;
pParticle->m_uchColor[1] = 255.0f;
pParticle->m_uchColor[2] = 255.0f;
pParticle->m_uchStartSize = 70 * m_flParticleScale;
pParticle->m_uchEndSize = 25 * m_flParticleScale;
float flAlpha = random->RandomFloat( 0.5f, 1.0f );
pParticle->m_uchStartAlpha = flAlpha * 255;
pParticle->m_uchEndAlpha = 0;
pParticle->m_flRoll = random->RandomInt( 0, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f );
}
}
}
// Update Fire
// if ( m_pFireEmitter && m_bEmitFire )
// {
// }
// Flare
// Save off position.
VectorCopy( m_vecPos, m_vecPrevPos );
}
//=============================================================================
//
// Meteor Tail Functions
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
C_EnvMeteorTail::C_EnvMeteorTail()
{
m_TailMaterialHandle = INVALID_MATERIAL_HANDLE;
m_pParticleMgr = NULL;
m_pParticle = NULL;
m_flFadeTime = 0.5f;
m_flWidth = 3.0f;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
C_EnvMeteorTail::~C_EnvMeteorTail()
{
Destroy();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorTail::Start( const Vector &vecOrigin, const Vector &vecDirection,
float flSpeed )
{
// Set the particle manager.
m_pParticleMgr = ParticleMgr();
m_pParticleMgr->AddEffect( &m_ParticleEffect, this );
m_TailMaterialHandle = m_ParticleEffect.FindOrAddMaterial( "particle/guidedplasmaprojectile" );
m_pParticle = m_ParticleEffect.AddParticle( sizeof( StandardParticle_t ), m_TailMaterialHandle );
if ( m_pParticle )
{
m_pParticle->m_Pos = vecOrigin;
}
VectorCopy( vecDirection, m_vecDirection );
m_flSpeed = flSpeed;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorTail::Destroy( void )
{
if ( m_pParticleMgr )
{
m_pParticleMgr->RemoveEffect( &m_ParticleEffect );
m_pParticleMgr = NULL;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteorTail::DrawFragment( ParticleDraw* pDraw,
const Vector &vecStart, const Vector &vecDelta,
const Vector4D &vecStartColor, const Vector4D &vecEndColor,
float flStartV, float flEndV )
{
if( !pDraw->GetMeshBuilder() )
return;
// Clip the fragment.
Vector vecVerts[4];
if ( !Tracer_ComputeVerts( vecStart, vecDelta, m_flWidth, vecVerts ) )
return;
// NOTE: Gotta get the winding right so it's not backface culled
// (we need to turn of backface culling for these bad boys)
CMeshBuilder* pMeshBuilder = pDraw->GetMeshBuilder();
pMeshBuilder->Position3f( vecVerts[0].x, vecVerts[0].y, vecVerts[0].z );
pMeshBuilder->TexCoord2f( 0, 0.0f, flStartV );
pMeshBuilder->Color4fv( vecStartColor.Base() );
pMeshBuilder->AdvanceVertex();
pMeshBuilder->Position3f( vecVerts[1].x, vecVerts[1].y, vecVerts[1].z );
pMeshBuilder->TexCoord2f( 0, 1.0f, flStartV );
pMeshBuilder->Color4fv( vecStartColor.Base() );
pMeshBuilder->AdvanceVertex();
pMeshBuilder->Position3f( vecVerts[3].x, vecVerts[3].y, vecVerts[3].z );
pMeshBuilder->TexCoord2f( 0, 1.0f, flEndV );
pMeshBuilder->Color4fv( vecEndColor.Base() );
pMeshBuilder->AdvanceVertex();
pMeshBuilder->Position3f( vecVerts[2].x, vecVerts[2].y, vecVerts[2].z );
pMeshBuilder->TexCoord2f( 0, 0.0f, flEndV );
pMeshBuilder->Color4fv( vecEndColor.Base() );
pMeshBuilder->AdvanceVertex();
}
void C_EnvMeteorTail::SimulateParticles( CParticleSimulateIterator *pIterator )
{
Particle *pParticle = (Particle*)pIterator->GetFirst();
while ( pParticle )
{
// Update the particle position.
pParticle->m_Pos = GetLocalOrigin();
pParticle = (Particle*)pIterator->GetNext();
}
}
void C_EnvMeteorTail::RenderParticles( CParticleRenderIterator *pIterator )
{
const Particle *pParticle = (const Particle *)pIterator->GetFirst();
while ( pParticle )
{
// Now draw the tail fragments...
Vector4D vecStartColor( 1.0f, 1.0f, 1.0f, 1.0f );
Vector4D vecEndColor( 1.0f, 1.0f, 1.0f, 0.0f );
Vector vecDelta, vecStartPos, vecEndPos;
// Calculate the tail.
Vector vecTailEnd;
vecTailEnd = GetLocalOrigin() + ( m_vecDirection * -m_flSpeed );
// Transform particles into camera space.
TransformParticle( m_pParticleMgr->GetModelView(), GetLocalOrigin(), vecStartPos );
TransformParticle( m_pParticleMgr->GetModelView(), vecTailEnd, vecEndPos );
float sortKey = vecStartPos.z;
// Draw the tail fragment.
VectorSubtract( vecStartPos, vecEndPos, vecDelta );
DrawFragment( pIterator->GetParticleDraw(), vecEndPos, vecDelta, vecEndColor, vecStartColor,
1.0f - vecEndColor[3], 1.0f - vecStartColor[3] );
pParticle = (const Particle *)pIterator->GetNext( sortKey );
}
}
//=============================================================================
//
// Meteor Functions
//
static g_MeteorCounter = 0;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
C_EnvMeteor::C_EnvMeteor()
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
C_EnvMeteor::~C_EnvMeteor()
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteor::ClientThink( void )
{
// Get the current time.
float flTime = gpGlobals->curtime;
// Update the meteor.
if ( m_Meteor.IsInSkybox( flTime ) )
{
if ( m_Meteor.m_nLocation == METEOR_LOCATION_WORLD )
{
WorldToSkyboxThink( flTime );
}
else
{
SkyboxThink( flTime );
}
}
else
{
if ( m_Meteor.m_nLocation == METEOR_LOCATION_SKYBOX )
{
SkyboxToWorldThink( flTime );
}
else
{
WorldThink( flTime );
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteor::SkyboxThink( float flTime )
{
float flDeltaTime = flTime - m_Meteor.m_flStartTime;
if ( flDeltaTime > METEOR_MAX_LIFETIME )
{
Destroy( this );
return;
}
// Check to see if the object is passive or not - act accordingly!
if ( !m_Meteor.IsPassive( flTime ) )
{
// Update meteor position.
Vector origin;
m_Meteor.GetPositionAtTime( flTime, origin );
SetLocalOrigin( origin );
// Update the position of the tail effect.
m_TailEffect.SetLocalOrigin( GetLocalOrigin() );
m_HeadEffect.MeteorHeadThink( GetLocalOrigin(), flTime );
}
// Add the entity to the active list - update!
AddEntity();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteor::WorldToSkyboxThink( float flTime )
{
// Move the meteor from the world into the skybox.
m_Meteor.ConvertFromWorldToSkybox();
// Destroy the head effect. Recreate it.
m_HeadEffect.Destroy();
m_HeadEffect.Start( m_Meteor.m_vecStartPosition, m_vecTravelDir );
m_HeadEffect.SetSmokeEmission( true );
m_HeadEffect.SetParticleScale( 1.0f / 16.0f );
m_HeadEffect.m_bInitThink = true;
// Update to world model.
SetModel( "models/props/common/meteorites/meteor05.mdl" );
// Update the meteor position (move into the skybox!)
SetLocalOrigin( m_Meteor.m_vecStartPosition );
// Update (think).
SkyboxThink( flTime );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteor::SkyboxToWorldThink( float flTime )
{
// Move the meteor from the skybox into the world.
m_Meteor.ConvertFromSkyboxToWorld();
// Destroy the head effect. Recreate it.
m_HeadEffect.Destroy();
m_HeadEffect.Start( m_Meteor.m_vecStartPosition, m_vecTravelDir );
m_HeadEffect.SetSmokeEmission( true );
m_HeadEffect.SetParticleScale( 1.0f );
m_HeadEffect.m_bInitThink = true;
// Update to world model.
SetModel( "models/props/common/meteorites/meteor04.mdl" );
SetLocalOrigin( m_Meteor.m_vecStartPosition );
// Update (think).
WorldThink( flTime );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteor::WorldThink( float flTime )
{
// Update meteor position.
Vector vecEndPosition;
m_Meteor.GetPositionAtTime( flTime, vecEndPosition );
// m_Meteor must return the end position in world space for the trace to work.
Assert( GetMoveParent() == NULL );
// Msg( "Client: Time = %lf, Position: %4.2f %4.2f %4.2f\n", flTime, vecEndPosition.x, vecEndPosition.y, vecEndPosition.z );
// Check to see if we struck the world. If so, cause an explosion.
trace_t trace;
Vector vecMin, vecMax;
GetRenderBounds( vecMin, vecMax );
// NOTE: This code works only if we aren't in hierarchy!!!
Assert( !GetMoveParent() );
CTraceFilterWorldOnly traceFilter;
UTIL_TraceHull( GetAbsOrigin(), vecEndPosition, vecMin, vecMax,
MASK_SOLID_BRUSHONLY, &traceFilter, &trace );
// Collision.
if ( ( trace.fraction < 1.0f ) && !( trace.surface.flags & SURF_SKY ) )
{
// Move up to the end.
Vector vecEnd = GetAbsOrigin() + ( ( vecEndPosition - GetAbsOrigin() ) * trace.fraction );
// Create an explosion effect!
BaseExplosionEffect().Create( vecEnd, 10, 32, TE_EXPLFLAG_NONE );
// Debugging Info!!!!
// debugoverlay->AddBoxOverlay( vecEnd, Vector( -10, -10, -10 ), Vector( 10, 10, 10 ), QAngle( 0.0f, 0.0f, 0.0f ), 255, 0, 0, 0, 100 );
Destroy( this );
return;
}
else
{
// Move to the end.
SetLocalOrigin( vecEndPosition );
}
m_TailEffect.SetLocalOrigin( GetLocalOrigin() );
m_HeadEffect.MeteorHeadThink( GetLocalOrigin(), flTime );
// Add the entity to the active list - update!
AddEntity();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
C_EnvMeteor *C_EnvMeteor::Create( int nID, int iMeteorType, const Vector &vecOrigin,
const Vector &vecDirection, float flSpeed, float flStartTime,
float flDamageRadius,
const Vector &vecTriggerMins, const Vector &vecTriggerMaxs )
{
C_EnvMeteor *pMeteor = new C_EnvMeteor;
if ( pMeteor )
{
pMeteor->m_Meteor.Init( nID, flStartTime, METEOR_PASSIVE_TIME, vecOrigin, vecDirection, flSpeed, flDamageRadius,
vecTriggerMins, vecTriggerMaxs );
// Initialize the meteor.
pMeteor->InitializeAsClientEntity( "models/props/common/meteorites/meteor05.mdl", RENDER_GROUP_OPAQUE_ENTITY );
// Handle forward simulation.
if ( ( pMeteor->m_Meteor.m_flStartTime + METEOR_MAX_LIFETIME ) < gpGlobals->curtime )
{
Destroy( pMeteor );
}
// Meteor Head and Tail
pMeteor->SetTravelDirection( vecDirection );
pMeteor->m_HeadEffect.SetSmokeEmission( true );
pMeteor->m_HeadEffect.Start( vecOrigin, vecDirection );
pMeteor->m_HeadEffect.SetParticleScale( 1.0f / 16.0f );
pMeteor->m_TailEffect.Start( vecOrigin, vecDirection, flSpeed );
pMeteor->SetNextClientThink( CLIENT_THINK_ALWAYS );
}
return pMeteor;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void C_EnvMeteor::Destroy( C_EnvMeteor *pMeteor )
{
Assert( pMeteor->GetClientHandle() != INVALID_CLIENTENTITY_HANDLE );
ClientThinkList()->AddToDeleteList( pMeteor->GetClientHandle() );
}
+189
View File
@@ -0,0 +1,189 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ENV_METEOR_H
#define C_ENV_METEOR_H
#pragma once
#include "utlvector.h"
#include "env_meteor_shared.h"
#include "baseparticleentity.h"
#include "c_effect_shootingstar.h"
//=============================================================================
//
// Client-side Meteor Factory Class
//
class C_MeteorFactory : public IMeteorFactory
{
public:
void CreateMeteor( int nID, int iType, const Vector &vecPosition,
const Vector &vecDirection, float flSpeed, float flStartTime,
float flDamageRadius,
const Vector &vecTriggerMins, const Vector &vecTriggerMaxs );
};
//=============================================================================
//
// Meteor Spawner Class
//
class C_EnvMeteorSpawner : public C_BaseEntity
{
public:
DECLARE_CLASS( C_EnvMeteorSpawner, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_EnvMeteorSpawner();
// Will more than likely be used for meteor input(s) later!
// void ReceiveMessage( const char *msgname, int length, void *data );
//-------------------------------------------------------------------------
// Networking
//-------------------------------------------------------------------------
void OnDataChanged( DataUpdateType_t updateType );
//-------------------------------------------------------------------------
// Think
//-------------------------------------------------------------------------
void ClientThink( void );
private:
C_MeteorFactory m_Factory;
CEnvMeteorSpawnerShared m_SpawnerShared;
bool m_fDisabled;
};
//=============================================================================
//
// Meteor Tail Class - Effect
//
class C_EnvMeteorHead
{
public:
C_EnvMeteorHead();
~C_EnvMeteorHead();
void Start( const Vector &vecOrigin, const Vector &vecDirection );
void Destroy( void );
void MeteorHeadThink( const Vector &vecOrigin, float flTime );
void SetSmokeEmission( bool bEmit ) { m_bEmitSmoke = bEmit; }
bool EmitSmoke( void ) { return m_bEmitSmoke; }
void SetParticleScale( float flScale ) { m_flParticleScale = flScale; }
bool m_bInitThink;
private:
Vector m_vecPos;
Vector m_vecPrevPos;
Vector m_vecDirection;
float m_flParticleScale;
CSmartPtr<CSimpleEmitter> m_pSmokeEmitter;
float m_flSmokeSpawnInterval;
float m_flSmokeSpawnRadius;
PMaterialHandle m_hSmokeMaterial;
float m_flSmokeLifetime; // How long do the particles live?
bool m_bEmitSmoke;
PMaterialHandle m_hFlareMaterial;
};
//=============================================================================
//
// Meteor Tail Class - Effect
//
class C_EnvMeteorTail : public C_BaseParticleEntity
{
public:
DECLARE_CLASS( C_EnvMeteorTail, C_BaseParticleEntity );
C_EnvMeteorTail();
~C_EnvMeteorTail();
void Start( const Vector &vecOrigin, const Vector &vecDirection, float flSpeed );
void Destroy( void );
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
//protected:
void DrawFragment( ParticleDraw* pDraw, const Vector &vecStart, const Vector &vecDelta,
const Vector4D &vecStartColor, const Vector4D &vecEndColor,
float flStartV, float flEndV );
CParticleMgr *m_pParticleMgr;
Particle *m_pParticle;
PMaterialHandle m_TailMaterialHandle;
// Properties.
float m_flFadeTime;
float m_flWidth;
float m_flSpeed;
Vector m_vecDirection;
private:
C_EnvMeteorTail( const C_EnvMeteorTail & );
};
//=============================================================================
//
// Meteor Class (Client-side only!)
//
class C_EnvMeteor : public C_BaseAnimating
{
public:
DECLARE_CLASS( C_EnvMeteor, C_BaseAnimating );
//-------------------------------------------------------------------------
// Initialization/Destruction
//-------------------------------------------------------------------------
C_EnvMeteor();
~C_EnvMeteor();
static C_EnvMeteor *Create( int nID, int iMeteorType, const Vector &vecOrigin,
const Vector &vecDirection, float flSpeed, float flStartTime,
float flDamageRadius,
const Vector &vecTriggerMins, const Vector &vecTriggerMaxs );
static void Destroy( C_EnvMeteor *pMeteor );
//-------------------------------------------------------------------------
// Think
//-------------------------------------------------------------------------
void ClientThink( void );
void SkyboxThink( float flTime );
void WorldThink( float flTime );
void WorldToSkyboxThink( float flTime );
void SkyboxToWorldThink( float flTime );
void SetTravelDirection( const Vector &vecDir ) { m_vecTravelDir = vecDir; }
private:
C_EnvMeteor( const C_EnvMeteor & );
CEnvMeteorShared m_Meteor;
// Effects
Vector m_vecTravelDir;
C_EnvMeteorHead m_HeadEffect;
C_EnvMeteorTail m_TailEffect;
};
#endif // C_ENV_METEOR_H
@@ -0,0 +1,42 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A place where vehicles can be built
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
//-----------------------------------------------------------------------------
// Purpose: A place where vehicles can be built
//-----------------------------------------------------------------------------
class C_FuncConstructionYard : public C_BaseEntity
{
DECLARE_CLASS( C_FuncConstructionYard, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
// DECLARE_MINIMAP_PANEL();
C_FuncConstructionYard();
const char *GetTargetDescription( void ) const;
};
IMPLEMENT_CLIENTCLASS_DT(C_FuncConstructionYard, DT_FuncConstructionYard, CFuncConstructionYard)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_FuncConstructionYard::C_FuncConstructionYard()
{
// CONSTRUCT_MINIMAP_PANEL( "minimap_construction_yard", MINIMAP_RESOURCE_ZONES );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_FuncConstructionYard::GetTargetDescription( void ) const
{
return "Construction Yard";
}
+263
View File
@@ -0,0 +1,263 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CResourceZone.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "engine/IEngineSound.h"
#include "c_func_resource.h"
#include "techtree.h"
#include "fx.h"
#include "fx_sparks.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Chunk movement
#define CHUNK_FLECK_MIN_SPEED 25.0f
#define CHUNK_FLECK_MAX_SPEED 100.0f
#define CHUNK_FLECK_GRAVITY 800.0f
#define CHUNK_FLECK_DAMPEN 0.3f
#define CHUNK_FLECK_ANGULAR_SPRAY 0.8f
IMPLEMENT_CLIENTCLASS_DT(C_ResourceZone, DT_ResourceZone, CResourceZone)
RecvPropFloat(RECVINFO(m_flClientResources)),
RecvPropInt(RECVINFO(m_nResourcesLeft)),
END_RECV_TABLE()
LINK_ENTITY_TO_CLASS( trigger_resourcezone, C_ResourceZone );
BEGIN_PREDICTION_DATA( C_ResourceZone )
END_PREDICTION_DATA();
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ResourceZone::C_ResourceZone()
{
CONSTRUCT_MINIMAP_PANEL( "minimap_resource_zone", MINIMAP_RESOURCE_ZONES );
}
//-----------------------------------------------------------------------------
// Add, remove object from the panel
//-----------------------------------------------------------------------------
void C_ResourceZone::SetDormant( bool bDormant )
{
BaseClass::SetDormant( bDormant );
ENTITY_PANEL_ACTIVATE( "resourcezone", (!bDormant && m_flClientResources > 0) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ResourceZone::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( gpGlobals->curtime + 1.0 );
}
// If I've just dried up, remove me from the minimap
if ( m_flClientResources <= 0 )
{
ENTITY_PANEL_ACTIVATE( "resourcezone", false );
DESTRUCT_MINIMAP_PANEL();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_ResourceZone::GetTargetDescription( void ) const
{
return "Resource Zone";
}
//==========================================================================================================
// Resource Spawner
//==========================================================================================================
IMPLEMENT_CLIENTCLASS_DT(C_ResourceSpawner, DT_ResourceSpawner, CResourceSpawner)
RecvPropInt(RECVINFO(m_bActive)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ResourceSpawner::C_ResourceSpawner( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ResourceSpawner::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( gpGlobals->curtime + random->RandomFloat( 2.0, 4.0 ) );
}
}
//-----------------------------------------------------------------------------
// Purpose: Receive a spawn message from the server
//-----------------------------------------------------------------------------
void C_ResourceSpawner::ReceiveMessage( int classID, bf_read &msg )
{
if ( classID != GetClientClass()->m_ClassID )
{
// message is for subclass
BaseClass::ReceiveMessage( classID, msg );
return;
}
// Make some particles
SpawnEffect( true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ResourceSpawner::ClientThink( void )
{
SetNextClientThink( gpGlobals->curtime + random->RandomFloat( 2.0, 10.0 ) );
// Don't do random puffs if I'm not active
if ( !m_bActive )
return;
// Occasionally spurt as if I was making a chunk
if ( random->RandomInt(0, 20) == 5 )
{
SpawnEffect( true );
}
else
{
SpawnEffect( false );
}
}
//-----------------------------------------------------------------------------
// Purpose: Particle effects created when we spawn a chunk
//-----------------------------------------------------------------------------
void C_ResourceSpawner::SpawnEffect( bool bSpawningChunk )
{
Vector normal = Vector(0,0,1);
Vector offset = GetAbsOrigin() + (normal * 16);
Vector dir;
float r = sResourceColor.r;
float g = sResourceColor.g;
float b = sResourceColor.b;
// Play a random puff sound
if ( bSpawningChunk )
{
EmitSound( "ResourceSpawner.BigPuff" );
}
else
{
EmitSound( "ResourceSpawner.Puff" );
}
// Chunks o'dirt
CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "SpawnEffect 1", offset, Vector(5,5,5) );
if ( !fleckEmitter )
return;
// Setup our collision information
fleckEmitter->m_ParticleCollision.Setup( offset, &normal, CHUNK_FLECK_ANGULAR_SPRAY, CHUNK_FLECK_MIN_SPEED, CHUNK_FLECK_MAX_SPEED, CHUNK_FLECK_GRAVITY, CHUNK_FLECK_DAMPEN );
int numFlecks;
if ( bSpawningChunk )
numFlecks = random->RandomInt( 48, 64 );
else
numFlecks = random->RandomInt( 1, 3 );
// Dump out flecks
int i;
for ( i = 0; i < numFlecks; i++ )
{
FleckParticle *pParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), g_Mat_Fleck_Cement[random->RandomInt(0,1)], offset );
if ( pParticle == NULL )
break;
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = random->RandomFloat(3.0f,5.0f);
if ( bSpawningChunk )
{
pParticle->m_uchSize = random->RandomInt( 4, 8 );
dir[0] = normal[0] + random->RandomFloat( -CHUNK_FLECK_ANGULAR_SPRAY, CHUNK_FLECK_ANGULAR_SPRAY );
dir[1] = normal[1] + random->RandomFloat( -CHUNK_FLECK_ANGULAR_SPRAY, CHUNK_FLECK_ANGULAR_SPRAY );
dir[2] = normal[2] + random->RandomFloat( -CHUNK_FLECK_ANGULAR_SPRAY, CHUNK_FLECK_ANGULAR_SPRAY );
pParticle->m_vecVelocity = dir * ( random->RandomFloat( CHUNK_FLECK_MIN_SPEED, CHUNK_FLECK_MAX_SPEED ) * ( 9 - pParticle->m_uchSize ) );
}
else
{
pParticle->m_uchSize = random->RandomInt( 2, 4 );
dir[0] = normal[0] + (random->RandomFloat( -CHUNK_FLECK_ANGULAR_SPRAY, CHUNK_FLECK_ANGULAR_SPRAY ) * 0.5);
dir[1] = normal[1] + (random->RandomFloat( -CHUNK_FLECK_ANGULAR_SPRAY, CHUNK_FLECK_ANGULAR_SPRAY ) * 0.5);
dir[2] = normal[2] + (random->RandomFloat( -CHUNK_FLECK_ANGULAR_SPRAY, CHUNK_FLECK_ANGULAR_SPRAY ) * 0.5);
pParticle->m_vecVelocity = dir * ( random->RandomFloat( CHUNK_FLECK_MIN_SPEED, CHUNK_FLECK_MAX_SPEED ) * 3);
}
pParticle->m_flRoll = random->RandomFloat( 0, 360 );
pParticle->m_flRollDelta = random->RandomFloat( 0, 360 );
pParticle->m_uchColor[0] = r;
pParticle->m_uchColor[1] = g;
pParticle->m_uchColor[2] = b;
}
// Create a couple of big, floating smoke clouds
if ( bSpawningChunk || random->RandomInt(0,10) == 0 )
{
CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create( "SpawnEffect 2" );
pSmokeEmitter->SetSortOrigin( offset );
int iSmokeClouds = 2;
if ( !bSpawningChunk )
iSmokeClouds = 1;
for ( i = 0; i < iSmokeClouds; i++ )
{
SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[1], offset );
if ( pParticle == NULL )
break;
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f );
if ( bSpawningChunk )
{
pParticle->m_uchStartSize = 32;
pParticle->m_uchEndSize = 128;
}
else
{
pParticle->m_uchStartSize = 16;
pParticle->m_uchEndSize = 64;
}
dir[0] = normal[0] + random->RandomFloat( -0.4f, 0.4f );
dir[1] = normal[1] + random->RandomFloat( -0.4f, 0.4f );
dir[2] = normal[2] + random->RandomFloat( 0, 0.6f );
pParticle->m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f )*(i+1);
pParticle->m_uchStartAlpha = 160;
pParticle->m_uchEndAlpha = 0;
pParticle->m_flRoll = random->RandomFloat( 180, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );
pParticle->m_uchColor[0] = r;
pParticle->m_uchColor[1] = g;
pParticle->m_uchColor[2] = b;
}
}
}
+57
View File
@@ -0,0 +1,57 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CObjectSentrygun
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_FUNC_RESOURCE_H
#define C_FUNC_RESOURCE_H
#include "commanderoverlay.h"
#include "hud_minimap.h"
//-----------------------------------------------------------------------------
// Purpose: A resource zone
//-----------------------------------------------------------------------------
class C_ResourceZone : public C_BaseEntity
{
DECLARE_CLASS( C_ResourceZone, C_BaseEntity );
public:
DECLARE_PREDICTABLE();
DECLARE_CLIENTCLASS();
DECLARE_ENTITY_PANEL();
DECLARE_MINIMAP_PANEL();
C_ResourceZone();
virtual void SetDormant( bool bDormant );
virtual void OnDataChanged( DataUpdateType_t updateType );
const char *GetTargetDescription( void ) const;
public:
float m_flClientResources; // Amount of resources left
int m_nResourcesLeft;
};
//-----------------------------------------------------------------------------
// Purpose: A resource chunk spawning point in a resource zone
//-----------------------------------------------------------------------------
class C_ResourceSpawner : public C_BaseAnimating
{
DECLARE_CLASS( C_ResourceSpawner, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_ResourceSpawner();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ReceiveMessage( int classID, bf_read &msg );
virtual void SpawnEffect( bool bSpawningChunk );
virtual void ClientThink( void );
public:
bool m_bActive;
};
#endif // C_FUNC_RESOURCE_H
+350
View File
@@ -0,0 +1,350 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_gasoline_blob.h"
#include "gasoline_shared.h"
#include "engine/IEngineSound.h"
#include "clienteffectprecachesystem.h"
static CUtlLinkedList<C_GasolineBlob*, int> g_GasolineBlobs;
// If multiple blobs are within this distance to each other, then only one will
// play a sound.
#define BLOB_SOUND_RELATED_DISTANCE 600
#define PUDDLE_START_SIZE 35
#define PUDDLE_END_SIZE 65
#define PUDDLE_GROW_TIME 0.5
#define PUDDLE_FADE_TIME 1.0
CLIENTEFFECT_REGISTER_BEGIN( PrecacheGasolineBlob )
CLIENTEFFECT_MATERIAL( "decals/puddle" )
CLIENTEFFECT_REGISTER_END()
// ------------------------------------------------------------------------------------------------ //
// CGasolineEmitter.
// ------------------------------------------------------------------------------------------------ //
CSmartPtr<CGasolineEmitter> CGasolineEmitter::Create( C_GasolineBlob *pBlob )
{
CGasolineEmitter *pEmitter = new CGasolineEmitter;
pEmitter->m_pBlob = pBlob;
pEmitter->m_hFireMaterial = pEmitter->GetPMaterial( "particle/fire" );
pEmitter->m_hUnlitMaterial = pEmitter->GetPMaterial( "sprites/env_particles" );
pEmitter->m_Timer.Init( 40 );
return pEmitter;
}
void CGasolineEmitter::UpdateFire( float frametime )
{
float flLifetime = gpGlobals->curtime - m_pBlob->m_flCreateTime;
float litPercent = 1;
if ( m_pBlob->IsLit() )
{
litPercent = 1 - (flLifetime / m_pBlob->m_flMaxLifetime);
if ( litPercent <= 0 )
return;
}
else
{
return;
}
// Don't show a burn effect for a blob that hasn't hit anything yet.
// If you do, it tends to make the flamethrower effect look weird.
if ( !m_pBlob->IsStopped() )
return;
// Make a coordinate system in which to spawn the particles. It
Vector vUp, vRight;
vUp.Init();
vRight.Init();
if ( m_pBlob->IsStopped() )
{
QAngle angles;
VectorAngles( m_pBlob->GetSurfaceNormal(), angles );
AngleVectors( angles, NULL, &vRight, &vUp );
}
PMaterialHandle hMaterial = m_hFireMaterial;
float flParticleLifetime = 1;
float flRadius = 7;
unsigned char uchColor[4] = { 255, 128, 0, 128 };
float flMaxZVel = 29;
float curDelta = frametime;
while ( m_Timer.NextEvent( curDelta ) )
{
// Based on how close we are to expiring, show less particles.
if ( RandomFloat( 0, 1 ) > litPercent )
continue;
Vector vPos = m_pBlob->GetAbsOrigin();
if ( m_pBlob->IsStopped() )
{
float flAngle = RandomFloat( 0, M_PI * 2 );
float flDist = RandomFloat( 0, GASOLINE_BLOB_RADIUS );
vPos += vRight * (cos( flAngle ) * flDist);
vPos += vUp * ( sin( flAngle ) * flDist );
}
else
{
vPos += RandomVector( -GASOLINE_BLOB_RADIUS, GASOLINE_BLOB_RADIUS );
}
SimpleParticle *pParticle = AddSimpleParticle( hMaterial, vPos, flParticleLifetime, flRadius );
if ( pParticle )
{
pParticle->m_uchColor[0] = uchColor[0];
pParticle->m_uchColor[1] = uchColor[1];
pParticle->m_uchColor[2] = uchColor[2];
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartAlpha = uchColor[3];
pParticle->m_vecVelocity.x = RandomFloat( -2, 2 );
pParticle->m_vecVelocity.y = RandomFloat( -2, 2 );
pParticle->m_vecVelocity.z = RandomFloat( 3, flMaxZVel );
}
}
}
// ------------------------------------------------------------------------------------------------ //
// C_GasolineBlob.
// ------------------------------------------------------------------------------------------------ //
IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_GasolineBlob, DT_GasolineBlob, CGasolineBlob )
RecvPropInt( RECVINFO( m_BlobFlags ) ),
RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ),
RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
RecvPropFloat( RECVINFO( m_flLitStartTime ) ),
RecvPropFloat( RECVINFO( m_flCreateTime ) ),
RecvPropFloat( RECVINFO( m_flMaxLifetime ) ),
RecvPropInt( RECVINFO( m_iTeamNum ) ),
RecvPropVector( RECVINFO( m_vSurfaceNormal ) )
END_RECV_TABLE()
C_GasolineBlob::C_GasolineBlob()
{
m_pEmitter = CGasolineEmitter::Create( this );
m_vSurfaceNormal.Init();
m_flLitStartTime = 0;
m_bSoundOn = false;
g_GasolineBlobs.AddToTail( this );
m_flPuddleSize = PUDDLE_START_SIZE;
m_flPuddleFade = 1;
}
C_GasolineBlob::~C_GasolineBlob()
{
g_GasolineBlobs.FindAndRemove( this );
StopSound();
// If a bunch of nearby blobs weren't playing a sound because we were, have them start their sound now.
FOR_EACH_LL( g_GasolineBlobs, i )
{
C_GasolineBlob *pBlob = g_GasolineBlobs[i];
if ( pBlob->IsSoundRelatedTo( this ) )
pBlob->CheckStartSound();
}
}
bool C_GasolineBlob::IsLit() const
{
return (m_BlobFlags & BLOBFLAG_LIT) != 0;
}
bool C_GasolineBlob::IsStopped() const
{
return (m_BlobFlags & BLOBFLAG_STOPPED) != 0;
}
const Vector& C_GasolineBlob::GetSurfaceNormal() const
{
return m_vSurfaceNormal;
}
float C_GasolineBlob::GetLitStartTime() const
{
return m_flLitStartTime;
}
void C_GasolineBlob::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
if ( type == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
CheckStartSound();
}
void C_GasolineBlob::ClientThink()
{
if ( m_pEmitter.IsValid() )
m_pEmitter->UpdateFire( gpGlobals->frametime );
// Grow the puddle a little.
if ( IsStopped() )
{
if ( IsLit() )
{
// Fade out after we get lit.
m_flPuddleFade -= gpGlobals->frametime / PUDDLE_FADE_TIME;
m_flPuddleFade = MAX( m_flPuddleFade, 0 );
}
else
{
// Grow the puddle until it's at its max size.
m_flPuddleSize += gpGlobals->frametime * ( PUDDLE_END_SIZE - PUDDLE_START_SIZE ) / PUDDLE_GROW_TIME;
m_flPuddleSize = MIN( m_flPuddleSize, PUDDLE_END_SIZE );
}
}
}
bool C_GasolineBlob::ShouldDraw()
{
return IsStopped() && (m_flPuddleFade > 0);
}
int C_GasolineBlob::DrawModel( int flags )
{
// Generate a basis.
QAngle angles;
VectorAngles( m_vSurfaceNormal, angles );
Vector vRight, vUp;
AngleVectors( angles, NULL, &vRight, &vUp );
float flAlpha = m_flPuddleFade * RemapVal( m_flPuddleSize, PUDDLE_START_SIZE, PUDDLE_END_SIZE, 0, 1 );
if ( flAlpha <= 0 )
return 0;
// Draw the puddle.
IMaterial *pMat = materials->FindMaterial( "decals/puddle", TEXTURE_GROUP_DECAL );
IMesh *pMesh = materials->GetDynamicMesh( true, NULL, NULL, pMat );
CMeshBuilder mb;
mb.Begin( pMesh, MATERIAL_QUADS, 1 );
Vector v;
v = GetAbsOrigin() + m_vSurfaceNormal + vRight*m_flPuddleSize - vUp*m_flPuddleSize;
mb.Position3f( v.x, v.y, v.z );
mb.Color4f( 1, 1, 1, flAlpha );
mb.Normal3f( VectorExpand( m_vSurfaceNormal ) );
mb.TexCoord2f( 0, 1, 0 );
mb.AdvanceVertex();
v = GetAbsOrigin() + m_vSurfaceNormal + vRight*m_flPuddleSize + vUp*m_flPuddleSize;
mb.Position3f( v.x, v.y, v.z );
mb.Color4f( 1, 1, 1, flAlpha );
mb.Normal3f( VectorExpand( m_vSurfaceNormal ) );
mb.TexCoord2f( 0, 1, 1 );
mb.AdvanceVertex();
v = GetAbsOrigin() + m_vSurfaceNormal - vRight*m_flPuddleSize + vUp*m_flPuddleSize;
mb.Position3f( v.x, v.y, v.z );
mb.Color4f( 1, 1, 1, flAlpha );
mb.Normal3f( VectorExpand( m_vSurfaceNormal ) );
mb.TexCoord2f( 0, 0, 1 );
mb.AdvanceVertex();
v = GetAbsOrigin() + m_vSurfaceNormal - vRight*m_flPuddleSize - vUp*m_flPuddleSize;
mb.Position3f( v.x, v.y, v.z );
mb.Color4f( 1, 1, 1, flAlpha );
mb.Normal3f( VectorExpand( m_vSurfaceNormal ) );
mb.TexCoord2f( 0, 0, 0 );
mb.AdvanceVertex();
mb.End( false, true );
return 0;
}
bool C_GasolineBlob::IsSoundRelatedTo( const C_GasolineBlob *pBlob ) const
{
return pBlob->GetAbsOrigin().DistTo( GetAbsOrigin() ) < BLOB_SOUND_RELATED_DISTANCE;
}
bool C_GasolineBlob::IsPlayingBurningSound() const
{
return m_bSoundOn;
}
void C_GasolineBlob::CheckStartSound()
{
if ( IsPlayingBurningSound() || (m_BlobFlags & BLOBFLAG_STOPPED) == 0 || !IsLit() )
return;
// First, make sure no nearby blob is playing the sound.
FOR_EACH_LL( g_GasolineBlobs, i )
{
C_GasolineBlob *pBlob = g_GasolineBlobs[i];
if ( pBlob != this && pBlob->IsSoundRelatedTo( this ) )
{
// If it's already playing a sound, then don't start our sound.
if ( pBlob->IsPlayingBurningSound() )
return;
}
}
StartSound();
}
void C_GasolineBlob::StartSound()
{
if ( !m_bSoundOn )
{
EmitSound( "GasolineBlob.FlameSound" );
m_bSoundOn = true;
}
}
void C_GasolineBlob::StopSound()
{
if ( m_bSoundOn )
{
BaseClass::StopSound( "GasolineBlob.FlameSound" );
m_bSoundOn = false;
}
}
+107
View File
@@ -0,0 +1,107 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_GASOLINE_BLOB_H
#define C_GASOLINE_BLOB_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "particles_simple.h"
#include "particle_util.h"
class C_GasolineBlob;
class CGasolineEmitter : public CSimpleEmitter
{
public:
static CSmartPtr<CGasolineEmitter> Create( C_GasolineBlob *pBlob );
void UpdateFire( float frametime );
private:
CGasolineEmitter() : CSimpleEmitter( "Gasoline" ){}
CGasolineEmitter( const CGasolineEmitter & );
C_GasolineBlob *m_pBlob;
PMaterialHandle m_hFireMaterial;
PMaterialHandle m_hUnlitMaterial;
TimedEvent m_Timer;
};
class C_GasolineBlob : public C_BaseEntity
{
friend class CGasolineEmitter;
public:
DECLARE_CLASS( C_GasolineBlob, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_GasolineBlob();
virtual ~C_GasolineBlob();
bool IsLit() const;
bool IsStopped() const;
const Vector& GetSurfaceNormal() const;
float GetLitStartTime() const;
// Overrides.
public:
virtual void OnDataChanged( DataUpdateType_t type );
virtual void ClientThink();
virtual int DrawModel( int flags );
virtual bool ShouldDraw();
private:
// Returns true if the two blobs relate their sound, meaning one blob won't play
// its sound if the other one is playing it.
bool IsSoundRelatedTo( const C_GasolineBlob *pBlob ) const;
bool IsPlayingBurningSound() const;
// Starts the burning sound if no other flames are playing the sound nearby.
void CheckStartSound();
// Make the burning sound.
void StartSound();
void StopSound();
private:
bool m_bSoundOn;
float m_flPuddleSize;
float m_flPuddleFade;
CSmartPtr<CGasolineEmitter> m_pEmitter;
float m_flLitStartTime;
float m_flCreateTime;
float m_flMaxLifetime;
Vector m_vSurfaceNormal;
int m_BlobFlags; // Combination of BLOBFLAG_ defines.
};
#endif // C_GASOLINE_BLOB_H
@@ -0,0 +1,84 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "grenade_base_empable.h"
#include "particles_simple.h"
//-----------------------------------------------------------------------------
// Purpose: Client side entity for the antipersonnel grenades
//-----------------------------------------------------------------------------
class C_GrenadeAntiPersonnel : public C_BaseEMPableGrenade
{
DECLARE_CLASS( C_GrenadeAntiPersonnel, C_BaseEMPableGrenade );
public:
DECLARE_CLIENTCLASS();
C_GrenadeAntiPersonnel();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
public:
C_GrenadeAntiPersonnel( const C_GrenadeAntiPersonnel & );
};
IMPLEMENT_CLIENTCLASS_DT(C_GrenadeAntiPersonnel, DT_GrenadeAntiPersonnel, CGrenadeAntiPersonnel)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_GrenadeAntiPersonnel::C_GrenadeAntiPersonnel( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_GrenadeAntiPersonnel::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// Only think when sapping
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//-----------------------------------------------------------------------------
// Purpose: Spawn effects if I'm sapping
//-----------------------------------------------------------------------------
void C_GrenadeAntiPersonnel::ClientThink( void )
{
// Fire smoke puffs out the side
CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create( "AntipersonnelGrenade::Effect" );
pSmokeEmitter->SetSortOrigin( GetAbsOrigin() );
int iSmokeClouds = random->RandomInt(1,2);
for ( int i = 0; i < iSmokeClouds; i++ )
{
SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[1], GetAbsOrigin() );
if ( pParticle == NULL )
return;
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = random->RandomFloat( 0.1f, 0.3f );
pParticle->m_uchStartSize = random->RandomFloat(2,5);
pParticle->m_uchEndSize = pParticle->m_uchStartSize + 2;
pParticle->m_vecVelocity = vec3_origin;
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 64;
pParticle->m_flRoll = random->RandomFloat( 180, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );
pParticle->m_uchColor[0] = 50;
pParticle->m_uchColor[1] = 250;
pParticle->m_uchColor[2] = 50;
}
}
+109
View File
@@ -0,0 +1,109 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "basegrenade_shared.h"
#include "minimap_trace.h"
#include "particles_simple.h"
//-----------------------------------------------------------------------------
// Purpose: Client side entity for the ferry target items
//-----------------------------------------------------------------------------
class C_LimpetMine : public C_BaseGrenade
{
DECLARE_CLASS( C_LimpetMine, C_BaseGrenade );
public:
DECLARE_CLIENTCLASS();
DECLARE_MINIMAP_PANEL();
C_LimpetMine();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
public:
C_LimpetMine( const C_LimpetMine & );
private:
bool m_bLive;
};
IMPLEMENT_CLIENTCLASS_DT(C_LimpetMine, DT_LimpetMine, CLimpetMine)
RecvPropInt(RECVINFO(m_bLive)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_LimpetMine::C_LimpetMine( void )
{
CONSTRUCT_MINIMAP_PANEL( "minimap_limpet", MINIMAP_OBJECTS );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_LimpetMine::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// Only think when live
if ( m_bLive )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
else
{
SetNextClientThink( CLIENT_THINK_NEVER );
}
}
//-----------------------------------------------------------------------------
// Purpose: Spawn effects if I'm live
//-----------------------------------------------------------------------------
void C_LimpetMine::ClientThink( void )
{
if ( !InLocalTeam() )
return;
Vector up;
GetVectors( NULL, NULL, &up );
up *= 8.0f;
Vector vecOrg = GetAbsOrigin() + up;
// Make a single sprite
CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create( "C_LimpetMine::Effect" );
pSmokeEmitter->SetSortOrigin( vecOrg );
PMaterialHandle hSphereMaterial = g_Mat_DustPuff[0];
SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle( sizeof(SimpleParticle), hSphereMaterial, vecOrg );
if ( pParticle == NULL )
return;
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = 0.1f;
pParticle->m_uchStartSize = RandomInt(4,6);
pParticle->m_uchEndSize = pParticle->m_uchStartSize;
pParticle->m_vecVelocity = vec3_origin;
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 255;
pParticle->m_flRoll = random->RandomFloat( 180, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );
if ( InLocalTeam() )
{
pParticle->m_uchColor[0] = 0;
pParticle->m_uchColor[1] = 255;
pParticle->m_uchColor[2] = 0;
}
else
{
pParticle->m_uchColor[0] = 255;
pParticle->m_uchColor[1] = 50;
pParticle->m_uchColor[2] = 50;
}
}
@@ -0,0 +1,82 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "basegrenade_shared.h"
#include "IEffects.h"
#include "c_baseplayer.h"
extern ConVar lod_effect_distance;
//-----------------------------------------------------------------------------
// Purpose: Client side entity for the ferry target items
//-----------------------------------------------------------------------------
class C_GrenadeObjectSapper : public C_BaseGrenade
{
DECLARE_CLASS( C_GrenadeObjectSapper, C_BaseGrenade );
public:
DECLARE_CLIENTCLASS();
C_GrenadeObjectSapper();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
public:
C_GrenadeObjectSapper( const C_GrenadeObjectSapper & );
bool m_bSapping;
float m_flNextEffectTime;
};
IMPLEMENT_CLIENTCLASS_DT(C_GrenadeObjectSapper, DT_GrenadeObjectSapper, CGrenadeObjectSapper)
RecvPropInt(RECVINFO(m_bSapping)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_GrenadeObjectSapper::C_GrenadeObjectSapper( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_GrenadeObjectSapper::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// Only think when sapping
if ( m_bSapping )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
m_flNextEffectTime = gpGlobals->curtime;
}
else
{
SetNextClientThink( CLIENT_THINK_NEVER );
}
}
//-----------------------------------------------------------------------------
// Purpose: Spawn effects if I'm sapping
//-----------------------------------------------------------------------------
void C_GrenadeObjectSapper::ClientThink( void )
{
if ( m_flNextEffectTime < gpGlobals->curtime )
{
// Haxory LOD
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr() < lod_effect_distance.GetFloat() )
{
g_pEffects->Sparks( GetAbsOrigin() );
}
m_flNextEffectTime = gpGlobals->curtime + 0.3;
}
}
+83
View File
@@ -0,0 +1,83 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "particles_simple.h"
//-----------------------------------------------------------------------------
// Purpose: Client side entity for the antipersonnel grenades
//-----------------------------------------------------------------------------
class C_GrenadeRocket : public C_BaseAnimating
{
DECLARE_CLASS( C_GrenadeRocket, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_GrenadeRocket();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
public:
C_GrenadeRocket( const C_GrenadeRocket & );
};
IMPLEMENT_CLIENTCLASS_DT(C_GrenadeRocket, DT_GrenadeRocket, CGrenadeRocket)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_GrenadeRocket::C_GrenadeRocket( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_GrenadeRocket::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// Only think when sapping
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//-----------------------------------------------------------------------------
// Purpose: Spawn effects if I'm sapping
//-----------------------------------------------------------------------------
void C_GrenadeRocket::ClientThink( void )
{
// Fire smoke puffs out the side
CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create( "C_GrenadeRocket::Effect" );
pSmokeEmitter->SetSortOrigin( GetAbsOrigin() );
int iSmokeClouds = random->RandomInt(1,2);
for ( int i = 0; i < iSmokeClouds; i++ )
{
SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[1], GetAbsOrigin() );
if ( pParticle == NULL )
return;
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = random->RandomFloat( 0.1f, 0.3f );
pParticle->m_uchStartSize = 10;
pParticle->m_uchEndSize = pParticle->m_uchStartSize + 2;
pParticle->m_vecVelocity = GetAbsVelocity();
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 64;
pParticle->m_flRoll = random->RandomFloat( 180, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );
pParticle->m_uchColor[0] = 50;
pParticle->m_uchColor[1] = 250;
pParticle->m_uchColor[2] = 50;
}
}
+95
View File
@@ -0,0 +1,95 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "particles_simple.h"
//-----------------------------------------------------------------------------
// Purpose: Client side entity for the harpoon
//-----------------------------------------------------------------------------
class C_Harpoon : public C_BaseAnimating
{
DECLARE_CLASS( C_Harpoon, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_Harpoon();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void GetAimEntOrigin( IClientEntity *pAttachedTo, Vector *pOrigin, QAngle *pAngles );
public:
C_Harpoon( const C_Harpoon & );
private:
// Impaling
Vector m_vecOffset;
QAngle m_angOffset;
};
IMPLEMENT_CLIENTCLASS_DT(C_Harpoon, DT_Harpoon, CHarpoon)
RecvPropVector( RECVINFO(m_vecOffset) ),
RecvPropVector( RECVINFO(m_angOffset) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_Harpoon::C_Harpoon( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_Harpoon::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
}
//-----------------------------------------------------------------------------
// Returns the attachment render origin + origin
//-----------------------------------------------------------------------------
void C_Harpoon::GetAimEntOrigin( IClientEntity *pAttachedTo, Vector *pOrigin, QAngle *pAngles )
{
C_BaseAnimating *pEnt = dynamic_cast< C_BaseAnimating * >( pAttachedTo->GetBaseEntity() );
if (!pEnt)
return;
float controllers[MAXSTUDIOBONES];
pEnt->GetBoneControllers(controllers);
float headcontroller = controllers[ 0 ];
// Compute angles as well, since parent uses bone controller for rotation
// Convert 0 - 1 to angles
float renderYaw = -180.0f + 360.0f * headcontroller;
matrix3x4_t matrix;
// Convert roll/pitch only to matrix
AngleMatrix( pEnt->GetAbsAngles(), matrix );
// Convert desired yaw to vector
QAngle anglesRotated( 0, renderYaw, 0 );
Vector forward;
AngleVectors( anglesRotated, &forward );
Vector rotatedForward;
// Rotate desired yaw vector by roll/pitch matrix
VectorRotate( forward, matrix, rotatedForward );
// Convert rotated vector back to orientation
VectorAngles( rotatedForward, *pAngles );
//*pAngles -= m_angOffset;
// HACK: Until we have a proper bone solution, hack the origin for all moving objects
*pOrigin = pEnt->WorldSpaceCenter( );
}
+49
View File
@@ -0,0 +1,49 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_hint_events.h"
#include "c_tf_hints.h"
#include "c_tf_hintmanager.h"
#include <KeyValues.h>
#include "c_baseobject.h"
void GlobalHintEvent( C_HintEvent_Base *pEvent )
{
// Call the static registered functions for each hint type.
for ( int i=0; i < GetNumHintDatas(); i++ )
{
CHintData *pData = GetHintData( i );
if ( pData && pData->m_pEventFn )
pData->m_pEventFn( pData, pEvent );
}
}
void HintEventFn_BuildObject( CHintData *pData, C_HintEvent_Base *pEvent )
{
if ( pEvent->GetType() == HINTEVENT_OBJECT_BUILT_BY_LOCAL_PLAYER )
{
C_BaseObject *pObj = ((C_HintEvent_ObjectBuiltByLocalPlayer*)pEvent)->m_pObject;
if ( pObj->GetType() == pData->m_ObjectType )
{
// Ok, they just built the object that any hints of this type are referring to, so disable
// all further hints of this type.
KeyValues *pkvStats = GetHintDisplayStats();
if ( pkvStats )
{
KeyValues *pkvStatSection = pkvStats->FindKey( pData->name, true );
if ( pkvStatSection )
{
pkvStatSection->SetString( "times_shown", VarArgs( "%i", 100 ) );
}
}
}
}
}
+62
View File
@@ -0,0 +1,62 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_HINT_EVENTS_H
#define C_HINT_EVENTS_H
#ifdef _WIN32
#pragma once
#endif
class CHintData;
typedef enum
{
HINTEVENT_OBJECT_BUILT_BY_LOCAL_PLAYER=0 // C_HintEvent_ObjectBuiltByLocalPlayer
} HintEventType;
// All hint events derive from this.
class C_HintEvent_Base
{
public:
// Find out what kind of event this is.
virtual HintEventType GetType() = 0;
};
// Fire a global hint event. It goes to all hint types so they can determine if
// they want to react.
void GlobalHintEvent( C_HintEvent_Base *pEvent );
// Hint callbacks for each type of hint.
void HintEventFn_BuildObject( CHintData *pData, C_HintEvent_Base *pEvent );
// This notifies the hint system that an object has been built by the local player so
// it can disable all further hints referring to objects of this type.
class C_BaseObject;
class C_HintEvent_ObjectBuiltByLocalPlayer : public C_HintEvent_Base
{
public:
C_HintEvent_ObjectBuiltByLocalPlayer( C_BaseObject *pObj )
{
m_pObject = pObj;
}
virtual HintEventType GetType() { return HINTEVENT_OBJECT_BUILT_BY_LOCAL_PLAYER; }
public:
C_BaseObject *m_pObject; // The object just built.
};
#endif // C_HINT_EVENTS_H
+196
View File
@@ -0,0 +1,196 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "tf_shareddefs.h"
#include "c_info_act.h"
#include "hud_timer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// We may get act begin messages for acts we haven't yet received entities for (usually during connection)
// We store the current act in this, and if an act arrives matching it, we start that act.
static int g_iCurrentActNumber = -1;
static float g_flActStartTime;
CHandle<C_InfoAct> g_hCurrentAct;
IMPLEMENT_CLIENTCLASS_DT(C_InfoAct, DT_InfoAct, CInfoAct)
RecvPropInt( RECVINFO(m_iActNumber) ),
RecvPropInt( RECVINFO(m_spawnflags) ),
RecvPropFloat( RECVINFO(m_flActTimeLimit) ),
RecvPropInt(RECVINFO(m_nRespawn1Team1Time) ),
RecvPropInt(RECVINFO(m_nRespawn1Team2Time) ),
RecvPropInt(RECVINFO(m_nRespawn2Team1Time) ),
RecvPropInt(RECVINFO(m_nRespawn2Team2Time) ),
RecvPropInt(RECVINFO(m_nRespawnTeam1Delay) ),
RecvPropInt(RECVINFO(m_nRespawnTeam2Delay) ),
END_RECV_TABLE()
typedef CHandle<C_InfoAct> ActHandle_t;
CUtlVector< ActHandle_t > g_hActs;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_InfoAct::C_InfoAct()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_InfoAct::~C_InfoAct()
{
ActHandle_t hAct;
hAct = this;
g_hActs.FindAndRemove( hAct );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_InfoAct::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_flPreviousTimeLimit = m_flActTimeLimit;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_InfoAct::OnDataChanged( DataUpdateType_t updateType )
{
ActHandle_t hAct;
hAct = this;
if ( g_hActs.Find( hAct ) == g_hActs.InvalidIndex() )
{
g_hActs.AddToTail( hAct );
// Is this act the one that's supposed to be going?
if ( GetActNumber() == g_iCurrentActNumber )
{
StartAct( g_flActStartTime );
return;
}
}
// Timer changed?
if ( g_hCurrentAct == this )
{
if ( m_flPreviousTimeLimit != m_flActTimeLimit )
{
CHudTimer *timer = GET_HUDELEMENT( CHudTimer );
if ( timer )
{
timer->SetFixedTimer( m_flStartTime, m_flActTimeLimit );
}
}
}
BaseClass::OnDataChanged( updateType );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_InfoAct::StartAct( float flStartTime )
{
g_hCurrentAct = this;
m_flStartTime = flStartTime;
CHudTimer *timer = GET_HUDELEMENT( CHudTimer );
if ( timer )
{
timer->SetFixedTimer( m_flStartTime, m_flActTimeLimit );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_InfoAct::IsAWaitingAct( void )
{
return (m_spawnflags & SF_ACT_WAITINGFORGAMESTART) != 0;
}
//-----------------------------------------------------------------------------
// PReturns the respawn time remaining
//-----------------------------------------------------------------------------
float C_InfoAct::RespawnTimeRemaining( int nTeam, int nTimer ) const
{
if ((g_hCurrentAct != this) || (nTeam == 0))
return 0;
int nTimerTime;
float flTimeDelta = gpGlobals->curtime - m_flStartTime;
if (flTimeDelta <= 0)
return 0;
if (nTeam == 1)
{
nTimerTime = (nTimer == 1) ? m_nRespawn1Team1Time : m_nRespawn2Team1Time;
flTimeDelta -= m_nRespawnTeam1Delay;
}
else
{
nTimerTime = (nTimer == 1) ? m_nRespawn1Team2Time : m_nRespawn2Team2Time;
flTimeDelta -= m_nRespawnTeam2Delay;
}
if (nTimerTime <= 0)
return 0.0f;
// This case takes care of the initial spawn delay time...
if (flTimeDelta < 0)
{
return nTimerTime - flTimeDelta;
}
int nFactor = flTimeDelta / nTimerTime;
return nTimerTime - (flTimeDelta - nFactor * nTimerTime);
}
//-----------------------------------------------------------------------------
// Purpose: Server's told us to start an act
//-----------------------------------------------------------------------------
void StartAct( int iActNumber, float flStartTime )
{
g_iCurrentActNumber = iActNumber;
g_flActStartTime = flStartTime;
// Find the act
for ( int i = 0; i < g_hActs.Size(); i++ )
{
if ( g_hActs[i] && g_hActs[i]->GetActNumber() == iActNumber )
{
g_hActs[i]->StartAct( flStartTime );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int GetCurrentActNumber( void )
{
if ( g_hCurrentAct )
return g_hCurrentAct->GetActNumber();
return ACT_NONE_SPECIFIED;
}
//-----------------------------------------------------------------------------
// Purpose: Return true if the current act (if any) is a waiting act.
//-----------------------------------------------------------------------------
bool CurrentActIsAWaitingAct( void )
{
if ( g_hCurrentAct )
return g_hCurrentAct->IsAWaitingAct();
return false;
}
+56
View File
@@ -0,0 +1,56 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_INFO_ACT_H
#define C_INFO_ACT_H
#ifdef _WIN32
#pragma once
#endif
#define ACT_NONE_SPECIFIED -1
//-----------------------------------------------------------------------------
// Purpose: Map entity that defines an act
//-----------------------------------------------------------------------------
class C_InfoAct : public C_BaseEntity
{
DECLARE_CLASS( C_InfoAct, C_BaseEntity );
public:
C_InfoAct();
~C_InfoAct();
DECLARE_CLIENTCLASS();
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
void StartAct( float flStartTime );
int GetActNumber( void ) { return m_iActNumber; }
bool IsAWaitingAct( void );
float RespawnTimeRemaining( int nTeam, int nTimer ) const;
private:
int m_iActNumber;
int m_spawnflags;
float m_flActTimeLimit;
int m_nRespawn1Team1Time;
int m_nRespawn1Team2Time;
int m_nRespawn2Team1Time;
int m_nRespawn2Team2Time;
int m_nRespawnTeam1Delay;
int m_nRespawnTeam2Delay;
float m_flStartTime;
float m_flPreviousTimeLimit;
};
extern CHandle<C_InfoAct> g_hCurrentAct;
void StartAct( int iActNumber, float flStartTime );
int GetCurrentActNumber( void );
bool CurrentActIsAWaitingAct( void );
#endif // C_INFO_ACT_H
+51
View File
@@ -0,0 +1,51 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud_technologytreedoc.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_InfoCustomTechnology : public C_BaseEntity
{
DECLARE_CLASS( C_InfoCustomTechnology, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_InfoCustomTechnology( void );
virtual void SetDormant( bool bDormant );
public:
// Sent via datatable
char m_szTechTreeFile[128];
};
IMPLEMENT_CLIENTCLASS_DT(C_InfoCustomTechnology, DT_InfoCustomTechnology, CInfoCustomTechnology)
RecvPropString(RECVINFO(m_szTechTreeFile)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_InfoCustomTechnology::C_InfoCustomTechnology( void )
{
}
//-----------------------------------------------------------------------------
// Purpose: Whenever we enter the PVS, add ourselves to the tech tree. This will
// only happen when the player joins a new team.
//-----------------------------------------------------------------------------
void C_InfoCustomTechnology::SetDormant( bool bDormant )
{
if ( IsDormant() && !bDormant )
{
// Tell the techtree to add the file to it's list of technologies
GetTechnologyTreeDoc().AddTechnologyFile( m_szTechTreeFile );
}
BaseClass::SetDormant( bDormant );
}
+109
View File
@@ -0,0 +1,109 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "c_ai_basenpc.h"
#include "IEffects.h"
#include "particles_simple.h"
//-----------------------------------------------------------------------------
// Purpose: Client side entity for the NPC Bug hole
//-----------------------------------------------------------------------------
class C_Maker_Bughole : public C_BaseEntity
{
DECLARE_CLASS( C_Maker_Bughole, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_Maker_Bughole();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
void SpawnEffect( void );
public:
C_Maker_Bughole( const C_Maker_Bughole & );
float m_flNextEffectTime;
};
IMPLEMENT_CLIENTCLASS_DT(C_Maker_Bughole, DT_Maker_Bughole, CMaker_Bughole)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_Maker_Bughole::C_Maker_Bughole( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_Maker_Bughole::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
m_flNextEffectTime = gpGlobals->curtime;
}
}
//-----------------------------------------------------------------------------
// Purpose: Spawn effects if I'm sapping
//-----------------------------------------------------------------------------
void C_Maker_Bughole::ClientThink( void )
{
if ( m_flNextEffectTime < gpGlobals->curtime )
{
SpawnEffect();
m_flNextEffectTime = gpGlobals->curtime + random->RandomFloat( 0.5, 1.0 );
}
}
//-----------------------------------------------------------------------------
// Purpose: Particle effects created when we spawn a chunk
//-----------------------------------------------------------------------------
void C_Maker_Bughole::SpawnEffect( void )
{
Vector normal = Vector(0,0,-1);
Vector offset = GetAbsOrigin() + (normal * 16);
Vector dir;
// Create a couple of big, floating smoke clouds
CSmartPtr<CSimpleEmitter> pSmokeEmitter = CSimpleEmitter::Create( "C_Maker_Bughole::SpawnEffect" );
pSmokeEmitter->SetSortOrigin( offset );
int iSmokeClouds = random->RandomInt(2,5);
for ( int i = 0; i < iSmokeClouds; i++ )
{
SimpleParticle *pParticle = (SimpleParticle *) pSmokeEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[1], offset );
if ( pParticle == NULL )
return;
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f );
pParticle->m_uchStartSize = 8;
pParticle->m_uchEndSize = 48;
dir[0] = normal[0] + random->RandomFloat( -0.4f, 0.4f );
dir[1] = normal[1] + random->RandomFloat( -0.4f, 0.4f );
dir[2] = normal[2] + random->RandomFloat( 0, 0.6f );
pParticle->m_vecVelocity = dir * random->RandomFloat( 8.0f, 20.0f )*(i+1);
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 0;
pParticle->m_flRoll = random->RandomFloat( 180, 360 );
pParticle->m_flRollDelta = random->RandomFloat( -1, 1 );
float flColor = random->RandomFloat( 0,64 );
pParticle->m_uchColor[0] = 100 + flColor;
pParticle->m_uchColor[1] = 50 + flColor;
pParticle->m_uchColor[2] = flColor;
}
}
+110
View File
@@ -0,0 +1,110 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "c_obj_barbed_wire.h"
IMPLEMENT_CLIENTCLASS_DT( C_ObjectBarbedWire, DT_ObjectBarbedWire, CObjectBarbedWire )
RecvPropEHandle( RECVINFO( m_hConnectedTo ) )
END_RECV_TABLE()
ConVar obj_barbed_wire_hang_dist( "obj_barbed_wire_hang_dist", "20" );
C_ObjectBarbedWire::C_ObjectBarbedWire()
{
m_vLastConnectedOrigin.Init( -999999999, -999999999, -999999999 );
m_vLastOrigin = m_vLastConnectedOrigin;
}
C_ObjectBarbedWire::~C_ObjectBarbedWire()
{
// Get rid of our rope if necessary.
if ( m_hRope )
{
m_hRope->Release();
}
}
void C_ObjectBarbedWire::OnDataChanged( DataUpdateType_t type )
{
if ( m_hConnectedTo != m_hLastConnectedTo )
{
m_hLastConnectedTo = m_hConnectedTo;
// Get rid of any old rope we had.
int iAttachment = LookupAttachment( "wire_attachment" );
// Create or delete our rope?
if ( m_hConnectedTo )
{
if ( !m_hRope )
{
m_hRope = C_RopeKeyframe::Create(
this,
m_hConnectedTo,
iAttachment,
iAttachment,
3,
"sprites/physbeam"
);
}
}
else
{
if ( m_hRope )
{
m_hRope->Release();
m_hRope = NULL;
}
}
// Update rope parameters.
if ( m_hRope )
{
int r, g, b, a;
CMapTeamColors *team = &MapData().m_TeamColors[ GetTeamNumber() ];
team->m_clrTeam.GetColor( r, g, b, a );
m_hRope->SetColorMod( Vector( r / 255.0f, g / 255.0f, b / 255.0f ) );
m_hRope->SetEndEntity( m_hConnectedTo );
m_hRope->SetRopeFlags( ROPE_SIMULATE | ROPE_BARBED );
}
}
BaseClass::OnDataChanged( type );
}
void C_ObjectBarbedWire::Spawn()
{
}
void C_ObjectBarbedWire::ClientThink()
{
if ( m_hConnectedTo && m_hRope )
{
if ( m_vLastOrigin != GetAbsOrigin() || m_vLastConnectedOrigin != m_hConnectedTo->GetAbsOrigin() )
{
m_hRope->SetupHangDistance( obj_barbed_wire_hang_dist.GetFloat() );
m_vLastOrigin = GetAbsOrigin();
m_vLastConnectedOrigin = m_hConnectedTo->GetAbsOrigin();
}
}
SetNextClientThink( gpGlobals->curtime + 0.1f );
}
+46
View File
@@ -0,0 +1,46 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_OBJ_BARBED_WIRE_H
#define C_OBJ_BARBED_WIRE_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseobject.h"
#include "c_rope.h"
class C_ObjectBarbedWire : public C_BaseObject
{
public:
DECLARE_CLASS( C_ObjectBarbedWire, C_BaseObject );
DECLARE_CLIENTCLASS();
C_ObjectBarbedWire();
~C_ObjectBarbedWire();
virtual void OnDataChanged( DataUpdateType_t type );
virtual void Spawn();
virtual void ClientThink();
private:
C_ObjectBarbedWire( C_ObjectBarbedWire& ) {}
CHandle<C_ObjectBarbedWire> m_hConnectedTo;
CHandle<C_ObjectBarbedWire> m_hLastConnectedTo;
CHandle<C_RopeKeyframe> m_hRope;
// Used to determine when to recalculate the hang distance.
Vector m_vLastOrigin;
Vector m_vLastConnectedOrigin;
};
#endif // C_OBJ_BARBED_WIRE_H
+122
View File
@@ -0,0 +1,122 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_obj_base_manned_gun.h"
#include "hudelement.h"
#include "tf_movedata.h"
#include "bone_setup.h"
#include "hud_ammo.h"
#include "vgui_bitmapbutton.h"
extern ConVar mannedgun_usethirdperson;
//=================================================================================================
// Control Screen
//=================================================================================================
DECLARE_VGUI_SCREEN_FACTORY( CMannedPlasmagunControlPanel, "manned_plasmagun_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CMannedPlasmagunControlPanel::CMannedPlasmagunControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CMannedPlasmagunControlPanel" )
{
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CMannedPlasmagunControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
m_pMannedLabel = new vgui::Label( this, "MannedReadout", "" );
m_pOccupyButton = new CBitmapButton( this, "OccupyButton", "Occupy" );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
return true;
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CMannedPlasmagunControlPanel::OnTick()
{
BaseClass::OnTick();
C_BaseObject *pObj = GetOwningObject();
if (!pObj)
return;
Assert( dynamic_cast<C_ObjectBaseMannedGun*>(pObj) );
C_ObjectBaseMannedGun *pGun = static_cast<C_ObjectBaseMannedGun*>(pObj);
char buf[256];
// Update the currently manned player label
if ( pGun->GetDriverPlayer() )
{
Q_snprintf( buf, sizeof( buf ), "Manned by %s", pGun->GetDriverPlayer()->GetPlayerName() );
m_pMannedLabel->SetText( buf );
m_pMannedLabel->SetVisible( true );
}
else
{
m_pMannedLabel->SetVisible( false );
}
// Update the get in button
if ( pGun->GetDriverPlayer() )
{
// Owners can boot other players to get in
if ( pGun->GetOwner() == C_BaseTFPlayer::GetLocalPlayer() && C_BaseTFPlayer::GetLocalPlayer() != pGun->GetDriverPlayer() )
{
Q_snprintf( buf, sizeof( buf ), "Get In (Ejecting %s)", pGun->GetDriverPlayer()->GetPlayerName() );
m_pMannedLabel->SetText( buf );
m_pOccupyButton->SetEnabled( true );
}
else
{
// Disable the button
m_pOccupyButton->SetEnabled( false );
}
}
else
{
m_pOccupyButton->SetText( "Get In" );
m_pOccupyButton->SetEnabled( true );
}
}
//-----------------------------------------------------------------------------
// Purpose: Handle clicking on the Occupy button
//-----------------------------------------------------------------------------
void CMannedPlasmagunControlPanel::GetInGun( void )
{
C_BaseObject *pObj = GetOwningObject();
if (pObj)
{
pObj->SendClientCommand( "toggle_use" );
}
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CMannedPlasmagunControlPanel::OnCommand( const char *command )
{
if (!Q_strnicmp(command, "Occupy", 7))
{
GetInGun();
return;
}
BaseClass::OnCommand(command);
}
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_OBJ_BASE_MANNED_GUN_H
#define C_OBJ_BASE_MANNED_GUN_H
#ifdef _WIN32
#pragma once
#endif
#include "basetfvehicle.h"
#include "tf_obj_manned_plasmagun_shared.h"
#include "ObjectControlPanel.h"
#include "tf_obj_base_manned_gun.h"
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CMannedPlasmagunControlPanel : public CRotatingObjectControlPanel
{
DECLARE_CLASS( CMannedPlasmagunControlPanel, CRotatingObjectControlPanel );
public:
CMannedPlasmagunControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick();
virtual void OnCommand( const char *command );
void GetInGun( void );
private:
vgui::Label *m_pMannedLabel;
vgui::Button *m_pOccupyButton;
};
#endif // C_OBJ_BASE_MANNED_GUN_H
+272
View File
@@ -0,0 +1,272 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: The client-side version of the portable power generator
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseobject.h"
#include "tf_shareddefs.h"
#include "C_BaseTFPlayer.h"
#include "ObjectControlPanel.h"
#include "vgui_bitmapbutton.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//=============================================================================
//
// Portable Power Generator Class
//
class C_ObjectBuffStation : public C_BaseObject
{
DECLARE_CLASS( C_ObjectBuffStation, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectBuffStation( void );
virtual void Release( void );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
// Since we have material proxies to show building amount, don't offset origin
virtual bool OffsetObjectOrigin( Vector& origin )
{
return false;
}
int PlayerSocketsLeft() const { return ( BUFF_STATION_MAX_PLAYERS - m_nPlayerCount ); }
int ObjectSocketsLeft() const { return ( BUFF_STATION_MAX_OBJECTS - m_nObjectCount ); }
// Check if the local player is attached
bool IsLocalPlayerAttached( void );
private:
typedef CHandle<C_BaseTFPlayer> CPlayerHandle;
int m_nPlayerCount;
CPlayerHandle m_hPlayers[BUFF_STATION_MAX_PLAYERS];
CPlayerHandle m_hOldPlayers[BUFF_STATION_MAX_PLAYERS];
typedef CHandle<C_BaseObject> CObjectHandle;
int m_nObjectCount;
CObjectHandle m_hObjects[BUFF_STATION_MAX_OBJECTS];
private:
C_ObjectBuffStation( const C_ObjectBuffStation & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT( C_ObjectBuffStation, DT_ObjectBuffStation, CObjectBuffStation )
RecvPropInt( RECVINFO( m_nPlayerCount ) ),
RecvPropArray( RecvPropEHandle( RECVINFO( m_hPlayers[0]) ), m_hPlayers ),
RecvPropInt( RECVINFO( m_nObjectCount ) ),
RecvPropArray( RecvPropEHandle( RECVINFO( m_hObjects[0]) ), m_hObjects ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectBuffStation::C_ObjectBuffStation( void )
{
}
//-----------------------------------------------------------------------------
// Purpose: Check if the local player is attached
//-----------------------------------------------------------------------------
bool C_ObjectBuffStation::IsLocalPlayerAttached( void )
{
C_BaseTFPlayer *pLocalPlayer = C_BaseTFPlayer::GetLocalPlayer();
for ( int iPlayer = 0; iPlayer < m_nPlayerCount; ++iPlayer )
{
if ( m_hPlayers[iPlayer].Get() == pLocalPlayer )
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectBuffStation::Release( void )
{
// Remove any sounds for players attached
for ( int i = 0; i < BUFF_STATION_MAX_PLAYERS; i++ )
{
if ( m_hPlayers[i] )
{
// Stop the startup, in case it's still going
StopSound( m_hPlayers[i]->entindex(), "ObjectPortablePowerGenerator.Startup" );
// Start the shutdown sound
CPASAttenuationFilter filter( m_hPlayers[i], "ObjectPortablePowerGenerator.Shutdown" );
EmitSound( filter, m_hPlayers[i]->entindex(), "ObjectPortablePowerGenerator.Shutdown" );
}
}
BaseClass::Release();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectBuffStation::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
for ( int i = 0; i < BUFF_STATION_MAX_PLAYERS; i++ )
{
m_hOldPlayers[i] = m_hPlayers[i];
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectBuffStation::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// Did a player connect / disconnect?
for ( int i = 0; i < BUFF_STATION_MAX_PLAYERS; i++ )
{
// Something's changed
if ( m_hOldPlayers[i] != m_hPlayers[i] )
{
// Disconnected?
if ( m_hOldPlayers[i] )
{
// Stop the startup, in case it's still going
StopSound( m_hOldPlayers[i]->entindex(), "ObjectPortablePowerGenerator.Startup" );
// Start the shutdown sound
CPASAttenuationFilter filter( m_hOldPlayers[i], "ObjectPortablePowerGenerator.Shutdown" );
EmitSound( filter, m_hOldPlayers[i]->entindex(), "ObjectPortablePowerGenerator.Shutdown" );
}
if ( m_hPlayers[i] )
{
// Start "buff" sound.
CPASAttenuationFilter filter( m_hPlayers[i], "ObjectPortablePowerGenerator.Startup" );
EmitSound( filter, m_hPlayers[i]->entindex(), "ObjectPortablePowerGenerator.Startup" );
}
}
}
}
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CBuffStationControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CBuffStationControlPanel, CObjectControlPanel );
public:
CBuffStationControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick();
virtual void OnCommand( const char *command );
void ConnectToStation( void );
private:
vgui::Label *m_pSocketsLabel;
vgui::Button *m_pConnectButton;
};
DECLARE_VGUI_SCREEN_FACTORY( CBuffStationControlPanel, "buffstation_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CBuffStationControlPanel::CBuffStationControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CBuffStationControlPanel" )
{
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CBuffStationControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
m_pSocketsLabel = new vgui::Label( this, "SocketReadout", "" );
m_pConnectButton = new CBitmapButton( this, "ConnectButton", "Connect" );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
return true;
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CBuffStationControlPanel::OnTick()
{
BaseClass::OnTick();
C_BaseObject *pObj = GetOwningObject();
if (!pObj)
return;
Assert( dynamic_cast<C_ObjectBuffStation*>(pObj) );
C_ObjectBuffStation *pStation = static_cast<C_ObjectBuffStation*>(pObj);
char buf[256];
int nSocketsLeft = pStation->PlayerSocketsLeft();
if (nSocketsLeft > 0)
{
Q_snprintf( buf, sizeof( buf ), "%d sockets left", pStation->PlayerSocketsLeft() );
}
else
{
Q_strncpy( buf, "No sockets left", sizeof( buf ) );
}
m_pSocketsLabel->SetText( buf );
// Make sure the connect/disconnect button is correct
if ( pStation->IsLocalPlayerAttached() )
{
m_pConnectButton->SetText( "Disconnect from Station" );
}
else
{
m_pConnectButton->SetText( "Connect To Station" );
}
}
//-----------------------------------------------------------------------------
// Purpose: Handle clicking on the Connect/Disconnect button
//-----------------------------------------------------------------------------
void CBuffStationControlPanel::ConnectToStation( void )
{
C_BaseObject *pObj = GetOwningObject();
if (pObj)
{
pObj->SendClientCommand( "toggle_connect" );
}
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CBuffStationControlPanel::OnCommand( const char *command )
{
if (!Q_strnicmp(command, "Connect", 7))
{
ConnectToStation();
return;
}
BaseClass::OnCommand(command);
}
+70
View File
@@ -0,0 +1,70 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "commanderoverlay.h"
#include "c_baseobject.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectBunker : public C_BaseObject
{
DECLARE_CLASS( C_ObjectBunker, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectBunker();
private:
C_ObjectBunker( const C_ObjectBunker & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectBunker, DT_ObjectBunker, CObjectBunker)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectBunker::C_ObjectBunker()
{
}
//=============================================================================
// Bunker Ladder
//=============================================================================
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectBunkerLadder : public C_BaseAnimating
{
DECLARE_CLASS( C_ObjectBunkerLadder, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_ObjectBunkerLadder();
private:
C_ObjectBunkerLadder( const C_ObjectBunkerLadder& ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT( C_ObjectBunkerLadder, DT_ObjectBunkerLadder, CObjectBunkerLadder )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectBunkerLadder::C_ObjectBunkerLadder()
{
}
+44
View File
@@ -0,0 +1,44 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "commanderoverlay.h"
#include "c_baseobject.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectDragonsTeeth : public C_BaseObject
{
DECLARE_CLASS( C_ObjectDragonsTeeth, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectDragonsTeeth();
// Since we have material proxies to show building amount, don't offset origin
virtual bool OffsetObjectOrigin( Vector& origin )
{
return false;
}
private:
C_ObjectDragonsTeeth( const C_ObjectDragonsTeeth & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectDragonsTeeth, DT_ObjectDragonsTeeth, CObjectDragonsTeeth)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectDragonsTeeth::C_ObjectDragonsTeeth()
{
}
+99
View File
@@ -0,0 +1,99 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "c_baseobject.h"
#include "particles_simple.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectEMPGenerator : public C_BaseObject
{
DECLARE_CLASS( C_ObjectEMPGenerator, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectEMPGenerator();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
private:
CSmartPtr<CSimpleEmitter> m_pEmitter;
PMaterialHandle m_hParticleMaterial;
TimedEvent m_ParticleEvent;
private:
C_ObjectEMPGenerator( const C_ObjectEMPGenerator & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectEMPGenerator, DT_ObjectEMPGenerator, CObjectEMPGenerator)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectEMPGenerator::C_ObjectEMPGenerator()
{
m_ParticleEvent.Init( 300 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectEMPGenerator::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
m_pEmitter = CSimpleEmitter::Create( "C_ObjectEMPGenerator" );
m_hParticleMaterial = m_pEmitter->GetPMaterial( "sprites/chargeball" );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectEMPGenerator::ClientThink( void )
{
// Add particles at the target.
float flCur = gpGlobals->frametime;
while ( m_ParticleEvent.NextEvent( flCur ) )
{
Vector vPos = WorldSpaceCenter( );
Vector vOffset = RandomVector( -1, 1 );
VectorNormalize( vOffset );
vPos += vOffset * RandomFloat( 0, 50 );
SimpleParticle *pParticle = m_pEmitter->AddSimpleParticle( m_hParticleMaterial, vPos );
if ( pParticle )
{
// Move the points along the path.
pParticle->m_vecVelocity.Init();
pParticle->m_flRoll = 0;
pParticle->m_flRollDelta = 0;
pParticle->m_flDieTime = 0.4f;
pParticle->m_flLifetime = 0;
pParticle->m_uchColor[0] = 255;
pParticle->m_uchColor[1] = 255;
pParticle->m_uchColor[2] = 255;
pParticle->m_uchStartAlpha = 32;
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartSize = 6;
pParticle->m_uchEndSize = 4;
pParticle->m_iFlags = 0;
}
}
}
+36
View File
@@ -0,0 +1,36 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "commanderoverlay.h"
#include "tf_obj_baseupgrade_shared.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectExplosives : public C_BaseObjectUpgrade
{
DECLARE_CLASS( C_ObjectExplosives, C_BaseObjectUpgrade );
public:
DECLARE_CLIENTCLASS();
C_ObjectExplosives();
private:
C_ObjectExplosives( const C_ObjectExplosives & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectExplosives, DT_ObjectExplosives, CObjectExplosives)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectExplosives::C_ObjectExplosives()
{
}
@@ -0,0 +1,28 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "c_obj_base_manned_gun.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectMannedMissileLauncher : public C_ObjectBaseMannedGun
{
DECLARE_CLASS( C_ObjectMannedMissileLauncher, C_ObjectBaseMannedGun );
public:
DECLARE_CLIENTCLASS();
C_ObjectMannedMissileLauncher() {}
private:
C_ObjectMannedMissileLauncher( const C_ObjectMannedMissileLauncher & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectMannedMissileLauncher, DT_ObjectMannedMissileLauncher, CObjectMannedMissileLauncher)
END_RECV_TABLE()
@@ -0,0 +1,27 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_obj_base_manned_gun.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectMannedPlasmagun : public C_ObjectBaseMannedGun
{
DECLARE_CLASS( C_ObjectMannedPlasmagun, C_ObjectBaseMannedGun );
public:
DECLARE_CLIENTCLASS();
C_ObjectMannedPlasmagun() {}
private:
C_ObjectMannedPlasmagun( const C_ObjectMannedPlasmagun & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectMannedPlasmagun, DT_ObjectMannedPlasmagun, CObjectMannedPlasmagun)
END_RECV_TABLE()
+27
View File
@@ -0,0 +1,27 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "c_obj_base_manned_gun.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectMannedShield : public C_ObjectBaseMannedGun
{
DECLARE_CLASS( C_ObjectMannedShield, C_ObjectBaseMannedGun );
public:
DECLARE_CLIENTCLASS();
C_ObjectMannedShield() {}
private:
C_ObjectMannedShield( const C_ObjectMannedShield & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT( C_ObjectMannedShield, DT_ObjectMannedShield, CObjectMannedShield )
END_RECV_TABLE()
+37
View File
@@ -0,0 +1,37 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "tf_shareddefs.h"
#include "c_obj_mapdefined.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT(C_ObjectMapDefined, DT_ObjectMapDefined, CObjectMapDefined)
RecvPropString( RECVINFO(m_szCustomName) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectMapDefined::C_ObjectMapDefined()
{
memset( m_szCustomName, 0, sizeof(m_szCustomName) );
}
//-----------------------------------------------------------------------------
// Purpose: Get a text description for the object target
//-----------------------------------------------------------------------------
const char *C_ObjectMapDefined::GetTargetDescription( void ) const
{
if ( m_szCustomName && m_szCustomName[0] )
return m_szCustomName;
return BaseClass::GetTargetDescription();
}
+35
View File
@@ -0,0 +1,35 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_OBJ_MAPDEFINED_H
#define C_OBJ_MAPDEFINED_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseobject.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectMapDefined : public C_BaseObject
{
DECLARE_CLASS( C_ObjectMapDefined, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectMapDefined();
virtual const char *GetTargetDescription( void ) const;
private:
C_ObjectMapDefined( const C_ObjectMapDefined & ); // not defined, not accessible
char m_szCustomName[ MAX_OBJ_CUSTOMNAME_SIZE ];
};
#endif // C_OBJ_MAPDEFINED_H
@@ -0,0 +1,279 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "c_baseobject.h"
#include "ObjectControlPanel.h"
#include "hud_minimap.h"
#include "vgui_bitmapimage.h"
#include "c_vehicle_teleport_station.h"
#include <vgui/MouseCode.h>
class C_ObjMCVSelectionPanel;
CUtlLinkedList<C_ObjMCVSelectionPanel*,int> g_SelectionPanels;
// ------------------------------------------------------------------------------------------------ //
// C_ObjMCVSelectionPanel
// ------------------------------------------------------------------------------------------------ //
class C_ObjMCVSelectionPanel : public C_BaseObject
{
public:
DECLARE_CLASS( C_ObjMCVSelectionPanel, C_BaseObject );
DECLARE_CLIENTCLASS();
C_ObjMCVSelectionPanel();
~C_ObjMCVSelectionPanel();
typedef CHandle<C_VehicleTeleportStation> VehicleTeleportStationHandle;
CUtlVector<VehicleTeleportStationHandle> m_DeployedTeleportStations;
private:
static C_ObjMCVSelectionPanel *s_pSelectionPanel;
friend void RecvProxy_TeleportStationCount( void *pStruct, int objectID, int currentArrayLength );
friend void RecvProxy_TeleportStationElement( const CRecvProxyData *pData, void *pStruct, void *pOut );
C_ObjMCVSelectionPanel( const C_ObjMCVSelectionPanel & );
};
void RecvProxy_TeleportStationCount( void *pStruct, int objectID, int currentArrayLength )
{
C_ObjMCVSelectionPanel *pPanel = (C_ObjMCVSelectionPanel*)pStruct;
if ( pPanel->m_DeployedTeleportStations.Count() != currentArrayLength )
{
pPanel->m_DeployedTeleportStations.SetSize( currentArrayLength );
}
}
void RecvProxy_TeleportStationElement( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_ObjMCVSelectionPanel *pPanel = (C_ObjMCVSelectionPanel*)pStruct;
Assert( pData->m_iElement < pPanel->m_DeployedTeleportStations.Count() );
RecvProxy_IntToEHandle( pData, pStruct, &pPanel->m_DeployedTeleportStations[pData->m_iElement] );
}
IMPLEMENT_CLIENTCLASS_DT( C_ObjMCVSelectionPanel, DT_MCVSelectionPanel, CObjMCVSelectionPanel )
RecvPropVirtualArray(
RecvProxy_TeleportStationCount,
32,
RecvPropEHandle( "teleport_station_element", 0, 0, RecvProxy_TeleportStationElement ),
"teleport_stations" )
END_RECV_TABLE()
C_ObjMCVSelectionPanel::C_ObjMCVSelectionPanel()
{
g_SelectionPanels.AddToTail( this );
}
C_ObjMCVSelectionPanel::~C_ObjMCVSelectionPanel()
{
g_SelectionPanels.FindAndRemove( this );
}
//-----------------------------------------------------------------------------
// CMCVMinimapPanel
//-----------------------------------------------------------------------------
class CMCVMinimapPanel : public CMinimapPanel
{
public:
DECLARE_CLASS( CMCVMinimapPanel, CMinimapPanel );
CMCVMinimapPanel( vgui::Panel *pParent, const char *pElementName );
virtual ~CMCVMinimapPanel();
virtual void Paint();
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnCursorMoved( int x, int y );
private:
BitmapImage m_MCVImage;
BitmapImage m_SelectedMCVImage;
int m_LastX, m_LastY;
};
CMCVMinimapPanel::CMCVMinimapPanel( vgui::Panel *pParent, const char *pElementName )
: CMinimapPanel( pElementName )
{
SetParent( pParent );
m_MCVImage.Init( GetVPanel(), "hud/minimap/icon_mcv_unselected" );
m_SelectedMCVImage.Init( GetVPanel(), "hud/minimap/icon_mcv_selected" );
m_LastX = m_LastY = 0;
}
CMCVMinimapPanel::~CMCVMinimapPanel()
{
}
void CMCVMinimapPanel::Paint()
{
// Draw the minimap.
BaseClass::Paint();
// Now draw the MCVs.
if ( g_SelectionPanels.Count() > 0 )
{
C_ObjMCVSelectionPanel *pPanel = g_SelectionPanels[ g_SelectionPanels.Head() ];
C_BaseEntity *pSelectedMCV = C_BaseTFPlayer::GetLocalPlayer()->GetSelectedMCV();
for ( int i=0; i < pPanel->m_DeployedTeleportStations.Count(); i++ )
{
C_VehicleTeleportStation *pStation = pPanel->m_DeployedTeleportStations[i];
if ( pStation )
{
float x, y;
if ( WorldToMinimap( MINIMAP_CLAMP, pStation->GetAbsOrigin(), x, y ) )
{
int size = 20;
if ( pStation == pSelectedMCV )
m_SelectedMCVImage.DoPaint( x-size/2, y-size/2, size, size );
else
m_MCVImage.DoPaint( x-size/2, y-size/2, size, size );
}
}
}
}
}
void CMCVMinimapPanel::OnMousePressed( vgui::MouseCode code )
{
BaseClass::OnMousePressed( code );
if ( code != vgui::MOUSE_LEFT )
return;
// Now draw the MCVs.
if ( g_SelectionPanels.Count() > 0 )
{
C_ObjMCVSelectionPanel *pPanel = g_SelectionPanels[ g_SelectionPanels.Head() ];
// Find the closest MCV to their mouse press.
int iClosest = -1;
float flClosest = 1e24;
Vector2D curMousePos( m_LastX, m_LastY );
for ( int i=0; i < pPanel->m_DeployedTeleportStations.Count(); i++ )
{
C_VehicleTeleportStation *pStation = pPanel->m_DeployedTeleportStations[i];
if ( pStation )
{
Vector2D mcvPos;
if ( WorldToMinimap( MINIMAP_CLAMP, pStation->GetAbsOrigin(), mcvPos.x, mcvPos.y ) )
{
float flTestDist = mcvPos.DistTo( curMousePos );
if ( flTestDist < flClosest )
{
flClosest = flTestDist;
iClosest = i;
}
}
}
}
if ( iClosest != -1 && flClosest < 10 )
{
C_VehicleTeleportStation *pClosest = pPanel->m_DeployedTeleportStations[iClosest];
char str[512];
Q_snprintf( str, sizeof( str ), "SelectMCV %d", pClosest->entindex() );
pPanel->SendClientCommand( str );
}
}
}
void CMCVMinimapPanel::OnCursorMoved( int x, int y )
{
BaseClass::OnCursorMoved( x, y );
m_LastX = x;
m_LastY = y;
}
// ------------------------------------------------------------------------------------------------ //
// CMCVSelectionPanel
// ------------------------------------------------------------------------------------------------ //
class CMCVSelectionPanel : public CObjectControlPanel
{
DECLARE_CLASS( CMCVSelectionPanel, CObjectControlPanel );
public:
CMCVSelectionPanel( vgui::Panel *parent, const char *panelName );
virtual ~CMCVSelectionPanel();
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnCommand( const char *command );
private:
CMCVMinimapPanel *m_pMinimapPanel;
};
DECLARE_VGUI_SCREEN_FACTORY( CMCVSelectionPanel, "mcv_selection_panel" );
CMCVSelectionPanel::CMCVSelectionPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CMCVSelectionPanel" )
{
m_pMinimapPanel = new CMCVMinimapPanel( this, "MinimapPanel" );
m_pMinimapPanel->SetZPos( 10 );
m_pMinimapPanel->Init( NULL );
}
CMCVSelectionPanel::~CMCVSelectionPanel()
{
delete m_pMinimapPanel;
}
bool CMCVSelectionPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
if ( !BaseClass::Init( pKeyValues, pInitData ) )
return false;
m_pMinimapPanel->LevelInit( engine->GetLevelName() );
m_pMinimapPanel->SetVisible( true );
return true;
}
void CMCVSelectionPanel::OnCommand( const char *command )
{
BaseClass::OnCommand( command );
}
+389
View File
@@ -0,0 +1,389 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client version of CObjectMortar
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "CommanderOverlay.h"
#include "c_baseobject.h"
#include "tf_shareddefs.h"
#include "c_basetfplayer.h"
#include "ObjectControlPanel.h"
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include "vgui_rotation_slider.h"
#include <vgui/ISurface.h>
#include "vgui_basepanel.h"
#include "vgui_bitmapimage.h"
#include "iusesmortarpanel.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectMortar : public C_BaseObject, public IUsesMortarPanel
{
DECLARE_CLASS( C_ObjectMortar, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
DECLARE_ENTITY_PANEL();
C_ObjectMortar();
virtual void SetDormant( bool bDormant );
virtual void Select( void );
virtual void RecalculateIDString( void );
void FireMortar( void );
// IUsesMortarPanel
public:
// Get the data from this mortar needed by the panel
virtual void GetMortarData( float *flClientMortarYaw, bool *bAllowedToFire, float *flPower, float *flFiringPower, float *flFiringAccuracy, int *iFiringState );
virtual void SendYawCommand( void );
virtual void ForceClientYawCountdown( float flTime );
virtual void ClickFire( void );
public:
int m_iRoundType;
int m_iMortarRounds[ MA_LASTAMMOTYPE ];
// Mortar firing info.
int m_iFiringState; // One of the MORTAR_ defines.
bool m_bMortarReloading;
float m_flPower;
bool m_bAllowedToFire;
// Parameters for the next shot.
float m_flFiringPower;
float m_flFiringAccuracy;
float m_flMortarYaw; // What direction the mortar is aimed in.
float m_flMortarPitch;
// This is what is used on the client to draw the ground line and orient the mortar.
// It is usually copied right over from m_flClientMortarYaw (which comes from the server),
// but this is also used when rotating the mortar so you can see the line move smoothly.
float m_flClientMortarYaw;
// This is set to about 1/4 seconds when you rotate the mortar line so you use the client's
// (smooth, non-lagged) yaw changes instead of the server's.
float m_flForceClientYawCountdown;
private:
C_ObjectMortar( const C_ObjectMortar & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectMortar, DT_ObjectMortar, CObjectMortar)
RecvPropInt( RECVINFO(m_iRoundType) ),
RecvPropArray( RecvPropInt( RECVINFO(m_iMortarRounds[0]) ), m_iMortarRounds )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectMortar::C_ObjectMortar( void )
{
memset( m_iMortarRounds, 0, sizeof( m_iMortarRounds ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectMortar::SetDormant( bool bDormant )
{
BaseClass::SetDormant( bDormant );
ENTITY_PANEL_ACTIVATE( "mortar", !bDormant );
}
//-----------------------------------------------------------------------------
// Purpose: Cycle ammo types on the mortar
//-----------------------------------------------------------------------------
void C_ObjectMortar::Select( void )
{
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer();
if ( pPlayer == NULL )
return;
int iOldType = m_iRoundType++;
// Cycle to the next ammo type
while ( m_iRoundType != iOldType )
{
// Hit the end of the round types?
if ( m_iRoundType == MA_LASTAMMOTYPE )
{
m_iRoundType = MA_SHELL;
break;
}
// Does this round type need a technology?
if ( MortarAmmoTechs[ m_iRoundType ] && MortarAmmoTechs[ m_iRoundType ][0] )
{
// Does the player have the technology?
if ( pPlayer->HasNamedTechnology( MortarAmmoTechs[ m_iRoundType ] ) )
{
// Do we have ammo?
if ( m_iMortarRounds[ m_iRoundType ] > 0 )
break;
}
}
// Go to the next round type
m_iRoundType++;
}
engine->ClientCmd( VarArgs("mortarround %d", m_iRoundType) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectMortar::RecalculateIDString( void )
{
// Only owners get full data
if ( IsOwnedByLocalPlayer() )
{
if ( m_iRoundType >= 0 )
{
// -1 means we have infinite rounds of this type
if ( m_iMortarRounds[ m_iRoundType ] == -1 )
{
Q_snprintf( m_szIDString, sizeof(m_szIDString), "%s - %s", GetTargetDescription(), MortarAmmoNames[ m_iRoundType ] );
}
else
{
Q_snprintf( m_szIDString, sizeof(m_szIDString), "%s - %d %s", GetTargetDescription(), m_iMortarRounds[ m_iRoundType ], MortarAmmoNames[ m_iRoundType ] );
}
Q_strncat( m_szIDString, "\nUse it to change ammo types.", sizeof(m_szIDString), COPY_ALL_CHARACTERS );
}
}
BaseClass::RecalculateIDString();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectMortar::ClickFire( void )
{
switch( m_iFiringState )
{
case MORTAR_IDLE:
m_iFiringState = MORTAR_CHARGING_POWER;
break;
case MORTAR_CHARGING_POWER:
m_flFiringPower = m_flPower;
m_iFiringState = MORTAR_CHARGING_ACCURACY;
break;
case MORTAR_CHARGING_ACCURACY:
m_flFiringAccuracy = m_flPower;
m_iFiringState = MORTAR_IDLE;
FireMortar();
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectMortar::GetMortarData( float *flClientMortarYaw, bool *bAllowedToFire, float *flPower, float *flFiringPower, float *flFiringAccuracy, int *iFiringState )
{
*flClientMortarYaw = m_flClientMortarYaw;
*bAllowedToFire = m_bAllowedToFire;
*flPower = m_flPower;
*flFiringPower = m_flFiringPower;
*flFiringAccuracy = m_flFiringAccuracy;
*iFiringState = m_iFiringState;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectMortar::SendYawCommand( void )
{
char szbuf[48];
Q_snprintf( szbuf, sizeof( szbuf ), "MortarYaw %0.2f\n", m_flClientMortarYaw );
SendClientCommand( szbuf );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectMortar::ForceClientYawCountdown( float flTime )
{
m_flForceClientYawCountdown = flTime;
}
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CMortarControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CMortarControlPanel, CObjectControlPanel );
public:
CMortarControlPanel( vgui::Panel *parent, const char *panelName );
virtual ~CMortarControlPanel();
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnCommand( const char *command );
C_ObjectMortar* GetMortar() const;
protected:
virtual vgui::Panel* TickCurrentPanel();
private:
CMortarMinimapPanel *m_pMinimapPanel;
};
DECLARE_VGUI_SCREEN_FACTORY( CMortarControlPanel, "mortar_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CMortarControlPanel::CMortarControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CMortarControlPanel" )
{
m_pMinimapPanel = new CMortarMinimapPanel( this, "MinimapPanel" );
m_pMinimapPanel->Init( NULL );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMortarControlPanel::~CMortarControlPanel()
{
delete m_pMinimapPanel;
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CMortarControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Make sure all named panels are created up above because BaseClass::Init initializes them
// all from their keyvalues.
if ( !BaseClass::Init( pKeyValues, pInitData ) )
return false;
// Init subpanels.
int x, y, w, h;
GetBounds( x, y, w, h );
m_pMinimapPanel->LevelInit( engine->GetLevelName() );
m_pMinimapPanel->SetVisible( true );
m_pMinimapPanel->InitMortarMinimap( GetMortar() );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectMortar* CMortarControlPanel::GetMortar() const
{
return dynamic_cast< C_ObjectMortar* >( GetOwningObject() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectMortar::FireMortar( void )
{
char cmd[512];
Q_snprintf( cmd, sizeof( cmd ), "FireMortar %.2f %.2f", m_flFiringPower, m_flFiringAccuracy );
SendClientCommand( cmd );
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
vgui::Panel* CMortarControlPanel::TickCurrentPanel()
{
C_BaseObject *pObj = GetOwningObject();
if (!pObj)
return BaseClass::TickCurrentPanel();;
ShowOwnerLabel( true );
ShowHealthLabel( true );
C_ObjectMortar *pMortar = GetMortar();
if ( !pMortar )
return BaseClass::TickCurrentPanel();;
ShowOwnerLabel( false );
ShowHealthLabel( false );
m_pMinimapPanel->Repaint();
float flAccuracySpeed = (1.0 / MORTAR_CHARGE_ACCURACY_RATE);
// Handle power charging
switch( pMortar->m_iFiringState )
{
case MORTAR_IDLE:
pMortar->m_flPower = 0;
break;
case MORTAR_CHARGING_POWER:
pMortar->m_flPower = MIN( pMortar->m_flPower + ( (1.0 / MORTAR_CHARGE_POWER_RATE) * gpGlobals->frametime), 1 );
pMortar->m_flFiringPower = 0;
pMortar->m_flFiringAccuracy = 0;
if ( pMortar->m_flPower >= 1.0 )
{
// Hit Max, start going down
pMortar->m_flFiringPower = pMortar->m_flPower;
pMortar->m_iFiringState = MORTAR_CHARGING_ACCURACY;
}
break;
case MORTAR_CHARGING_ACCURACY:
// Calculate accuracy speed
if ( pMortar->m_flFiringPower > 0.5 )
{
// Shots over halfway suffer an increased speed to the accuracy power, making accurate shots harder
float flAdjustedPower = (pMortar->m_flFiringPower - 0.5) * 3.0;
flAccuracySpeed += (pMortar->m_flFiringPower * flAdjustedPower);
}
pMortar->m_flPower = MAX( pMortar->m_flPower - ( flAccuracySpeed * gpGlobals->frametime), -0.25f);
if ( pMortar->m_flPower <= -0.25 )
{
// Hit Min, fire mortar
pMortar->m_flFiringAccuracy = pMortar->m_flPower;
pMortar->m_iFiringState = MORTAR_IDLE;
pMortar->FireMortar();
}
break;
default:
break;
}
return BaseClass::TickCurrentPanel();
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CMortarControlPanel::OnCommand( const char *command )
{
C_ObjectMortar *pMortar = GetMortar();
if ( !pMortar )
return;
if ( !Q_stricmp( command, "FireMortar" ) )
{
pMortar->ClickFire();
}
BaseClass::OnCommand(command);
}
+340
View File
@@ -0,0 +1,340 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseobject.h"
#include "ObjectControlPanel.h"
#include "tf_shareddefs.h"
#include "tempent.h"
#include "c_te_legacytempents.h"
#include "iviewrender_beams.h"
#include "beamdraw.h"
#include "view.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define NUM_POWERPACK_GLOWS 6
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectPowerPack : public C_BaseObject
{
DECLARE_CLASS( C_ObjectPowerPack, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectPowerPack();
~C_ObjectPowerPack();
int SocketsLeft() const { return (MAX_OBJECTS_PER_PACK - m_iObjectsAttached); }
// Since we have material proxies to show building amount, don't offset origin
virtual bool OffsetObjectOrigin( Vector& origin )
{
return false;
}
virtual void OnGoActive( void );
virtual void OnGoInactive( void );
void RemoveGlows( void );
virtual void ClientThink( void );
virtual int DrawModel( int flags );
private:
int m_iObjectsAttached;
int m_iGlowModelIndex;
C_LocalTempEntity *m_pGlowSprites[ NUM_POWERPACK_GLOWS ];
// Jacob's laddder
Beam_t *m_pJacobsLadderBeam;
float m_flJacobsLeftPoint;
float m_flJacobsRightPoint;
Vector m_vecJacobsStart;
Vector m_vecJacobsEnd;
CMaterialReference m_hJacobsPointMaterial;
private:
C_ObjectPowerPack( const C_ObjectPowerPack & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectPowerPack, DT_ObjectPowerPack, CObjectPowerPack)
RecvPropInt( RECVINFO(m_iObjectsAttached) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectPowerPack::C_ObjectPowerPack()
{
for ( int i = 0; i < NUM_POWERPACK_GLOWS; i++ )
{
m_pGlowSprites[i] = NULL;
}
m_iGlowModelIndex = PrecacheModel( "effects/human_object_glow.vmt" );
m_pJacobsLadderBeam = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectPowerPack::~C_ObjectPowerPack( void )
{
RemoveGlows();
}
//-----------------------------------------------------------------------------
// Purpose: We've just gone active
//-----------------------------------------------------------------------------
void C_ObjectPowerPack::OnGoActive( void )
{
// Turn on our glows
for ( int i = 0; i < NUM_POWERPACK_GLOWS; i++ )
{
// Find the attachment point
int iAttachment = LookupAttachment( VarArgs("glow_%d",(i+1)) );
Vector vecOrigin;
QAngle vecAngles;
if ( GetAttachment( iAttachment, vecOrigin, vecAngles ) )
{
Vector vecForward;
AngleVectors( vecAngles, &vecForward );
m_pGlowSprites[i] = tempents->TempSprite( vecOrigin, vec3_origin, 0.35, m_iGlowModelIndex, kRenderTransAdd, 0, 0.5, 1, FTENT_PERSIST | FTENT_NEVERDIE | FTENT_BEOCCLUDED, vecForward );
}
}
m_flJacobsLeftPoint = 0;
m_flJacobsRightPoint = 0;
m_hJacobsPointMaterial.Init( "sprites/blueflare2", TEXTURE_GROUP_CLIENT_EFFECTS );
}
//-----------------------------------------------------------------------------
// Purpose: We've just gone inactive
//-----------------------------------------------------------------------------
void C_ObjectPowerPack::OnGoInactive( void )
{
// Turn off our glows
RemoveGlows();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectPowerPack::RemoveGlows( void )
{
for ( int i = 0; i < NUM_POWERPACK_GLOWS; i++ )
{
if ( m_pGlowSprites[i] )
{
m_pGlowSprites[i]->die = 0;
m_pGlowSprites[i] = NULL;
}
}
// Stop the jacob's ladder
if ( m_pJacobsLadderBeam )
{
m_pJacobsLadderBeam->flags &= ~FBEAM_FOREVER;
m_pJacobsLadderBeam->die = gpGlobals->curtime;
m_pJacobsLadderBeam = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectPowerPack::ClientThink( void )
{
// Create the jacob's ladder
if ( !m_pJacobsLadderBeam )
{
BeamInfo_t beamInfo;
beamInfo.m_vecStart.Init();
beamInfo.m_vecEnd.Init();
beamInfo.m_pszModelName = "sprites/physbeam.vmt";
beamInfo.m_flHaloScale = 0.0f;
beamInfo.m_flLife = 0.0f;
beamInfo.m_flWidth = 8.0f;
beamInfo.m_flEndWidth = 4.0f;
beamInfo.m_flFadeLength = 0.0f;
beamInfo.m_flAmplitude = 20.0f;
beamInfo.m_flBrightness = 255.0f;
beamInfo.m_flSpeed = 0.0f;
beamInfo.m_nStartFrame = 0;
beamInfo.m_flFrameRate = 0.0f;
beamInfo.m_flRed = 206.0f;
beamInfo.m_flGreen = 181.0f;
beamInfo.m_flBlue = 127.0f;
beamInfo.m_nSegments = 5;
beamInfo.m_bRenderable = true;
m_pJacobsLadderBeam = beams->CreateBeamPoints( beamInfo );
}
// Update the position of the jacob's ladder
BeamInfo_t beamInfo;
QAngle vecAngle;
int iAttachment;
// Setup a color reflecting the amount of power being used
color32 color;
color.r = 206;
color.g = 182;
color.b = 127;
color.a = 255;
// Tesla Effect
Vector vecRightTop, vecRightBottom;
Vector vecLeftTop, vecLeftBottom;
iAttachment = LookupAttachment( "Tesla_ll" );
GetAttachment( iAttachment, vecLeftBottom, vecAngle );
iAttachment = LookupAttachment( "Tesla_ul" );
GetAttachment( iAttachment, vecLeftTop, vecAngle );
iAttachment = LookupAttachment( "Tesla_lr" );
GetAttachment( iAttachment, vecRightBottom, vecAngle );
iAttachment = LookupAttachment( "Tesla_ur" );
GetAttachment( iAttachment, vecRightTop, vecAngle );
float flSpeed = 0.02;
m_flJacobsLeftPoint += random->RandomFloat( flSpeed * 0.25, flSpeed * 2);
m_flJacobsRightPoint += random->RandomFloat( flSpeed * 0.25, flSpeed * 2);
// If they've both hit the end, break the ladder
if ( m_flJacobsLeftPoint >= 1.0f && m_flJacobsRightPoint >= 1.0f )
{
// Snap!
m_flJacobsLeftPoint = 0.0f;
m_flJacobsRightPoint = 0.0f;
}
else if ( m_flJacobsLeftPoint > 1.0f )
{
// Only the left point's made it
m_flJacobsLeftPoint = 1.0f;
}
else if ( m_flJacobsRightPoint > 1.0f )
{
// Only the right point's made it
m_flJacobsRightPoint = 1.0f;
}
Vector vecLeft = vecLeftTop - vecLeftBottom;
Vector vecRight = vecRightTop - vecRightBottom;
m_vecJacobsStart = vecLeftBottom + ( m_flJacobsLeftPoint * vecLeft );
m_vecJacobsEnd = vecRightBottom + ( m_flJacobsRightPoint * vecRight );
beamInfo.m_vecStart = m_vecJacobsStart;
beamInfo.m_vecEnd = m_vecJacobsEnd;
beamInfo.m_flRed = color.r;
beamInfo.m_flGreen = color.g;
beamInfo.m_flBlue = color.b;
beams->UpdateBeamInfo( m_pJacobsLadderBeam, beamInfo );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_ObjectPowerPack::DrawModel( int flags )
{
if ( BaseClass::DrawModel( flags ) )
{
if ( ShouldBeActive() )
{
// Get the distance to the view
float flDistance = (GetAbsOrigin() - MainViewOrigin()).LengthSqr();
if ( flDistance < (1024 * 1024) )
{
// Draw a sprite at the tips.
color32 color;
color.r = 255;
color.g = 255;
color.b = 255;
color.a = 255;
float flSize = 25.0f;
materials->Bind( m_hJacobsPointMaterial, this );
DrawSprite( m_vecJacobsStart, flSize, flSize, color );
DrawSprite( m_vecJacobsEnd, flSize, flSize, color );
}
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CPowerPackControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CPowerPackControlPanel, CObjectControlPanel );
public:
CPowerPackControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick();
private:
vgui::Label *m_pSocketsLabel;
};
DECLARE_VGUI_SCREEN_FACTORY( CPowerPackControlPanel, "powerpack_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CPowerPackControlPanel::CPowerPackControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CPowerPackControlPanel" )
{
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CPowerPackControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
m_pSocketsLabel = new vgui::Label( GetActivePanel(), "SocketReadout", "" );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
return true;
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CPowerPackControlPanel::OnTick()
{
BaseClass::OnTick();
C_BaseObject *pObj = GetOwningObject();
if (!pObj)
return;
Assert( dynamic_cast<C_ObjectPowerPack*>(pObj) );
C_ObjectPowerPack *pPowerPack = static_cast<C_ObjectPowerPack*>(pObj);
char buf[256];
int nSocketsLeft = pPowerPack->SocketsLeft();
if (nSocketsLeft > 0)
{
Q_snprintf( buf, sizeof( buf ), "%d sockets left", pPowerPack->SocketsLeft() );
}
else
{
Q_strncpy( buf, "No sockets left", sizeof( buf ) );
}
m_pSocketsLabel->SetText( buf );
}
+35
View File
@@ -0,0 +1,35 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "c_baseobject.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectRallyFlag : public C_BaseObject
{
DECLARE_CLASS( C_ObjectRallyFlag, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectRallyFlag();
private:
C_ObjectRallyFlag( const C_ObjectRallyFlag & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectRallyFlag, DT_ObjectRallyFlag, CObjectRallyFlag)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectRallyFlag::C_ObjectRallyFlag()
{
}
+164
View File
@@ -0,0 +1,164 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "c_obj_resourcepump.h"
#include "commanderoverlay.h"
#include "vgui_healthbar.h"
#include "ObjectControlPanel.h"
#include "tf_shareddefs.h"
#include "vgui_bitmapbutton.h"
#include "C_Func_Resource.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BEGIN_RECV_TABLE_NOBASE( C_ObjectResourcePump, DT_ResourcePumpTeamOnlyVars )
RecvPropInt( RECVINFO(m_iPumpLevel) ),
RecvPropEHandle( RECVINFO(m_hResourceZone) ),
END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT(C_ObjectResourcePump, DT_ResourcePump, CObjectResourcePump)
RecvPropDataTable( "teamonly", 0, 0, &REFERENCE_RECV_TABLE( DT_ResourcePumpTeamOnlyVars ) )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectResourcePump::C_ObjectResourcePump()
{
m_iPumpLevel = 1;
m_pResourceBar = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectResourcePump::SetDormant( bool bDormant )
{
BaseClass::SetDormant( bDormant );
ENTITY_PANEL_ACTIVATE( "resource_pump", !bDormant );
}
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CResourcePumpControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CResourcePumpControlPanel, CObjectControlPanel );
public:
CResourcePumpControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick();
virtual void OnCommand( const char *command );
void Upgrade( void );
private:
vgui::Button *m_pUpgradeButton;
vgui::Label *m_pResourcesLabel;
};
DECLARE_VGUI_SCREEN_FACTORY( CResourcePumpControlPanel, "resourcepump_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CResourcePumpControlPanel::CResourcePumpControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CResourcePumpControlPanel" )
{
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CResourcePumpControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
m_pUpgradeButton = new CBitmapButton( this, "UpgradeButton", "Upgrade" );
m_pResourcesLabel = new vgui::Label( this, "ResourcesLabel", "Resources: 0" );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
// ROBIN: Removed upgrading for now
m_pUpgradeButton->SetVisible( false );
return true;
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CResourcePumpControlPanel::OnTick()
{
BaseClass::OnTick();
C_BaseObject *pObj = GetOwningObject();
if (!pObj)
return;
Assert( dynamic_cast<C_ObjectResourcePump*>(pObj) );
C_ObjectResourcePump *pPump = static_cast<C_ObjectResourcePump*>(pObj);
char buf[256];
int iPumpLevel = pPump->GetLevel();
int iCost = CalculateObjectUpgrade( OBJ_RESOURCEPUMP, iPumpLevel );
if ( iCost )
{
Q_snprintf( buf, sizeof( buf ), "Upgrade to Level %d\nCost: %d", iPumpLevel+1, iCost );
}
else
{
Q_snprintf( buf, sizeof( buf ), "Level %d", iPumpLevel );
}
m_pUpgradeButton->SetText( buf );
C_ResourceZone *pResourceZone = pPump->GetResourceZone();
if (pResourceZone)
{
Q_snprintf( buf, sizeof( buf ), "Resources: %d", pResourceZone->m_nResourcesLeft );
m_pResourcesLabel->SetText( buf );
}
else
{
m_pResourcesLabel->SetText( "Resources: 0" );
}
}
//-----------------------------------------------------------------------------
// Dismantles the object
//-----------------------------------------------------------------------------
void CResourcePumpControlPanel::Upgrade( void )
{
C_BaseObject *pObj = GetOwningObject();
if (pObj)
{
pObj->SendClientCommand( "upgrade" );
}
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CResourcePumpControlPanel::OnCommand( const char *command )
{
if (!Q_strnicmp(command, "Upgrade", 7))
{
Upgrade();
return;
}
BaseClass::OnCommand(command);
}
+44
View File
@@ -0,0 +1,44 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_OBJ_RESOURCEPUMP_H
#define C_OBJ_RESOURCEPUMP_H
#ifdef _WIN32
#pragma once
#endif
#include "CommanderOverlay.h"
#include "c_baseobject.h"
class C_ResourceZone;
class C_ObjectResourcePump : public C_BaseObject
{
DECLARE_CLASS( C_ObjectResourcePump, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
DECLARE_ENTITY_PANEL();
C_ObjectResourcePump();
virtual void SetDormant( bool bDormant );
int GetLevel( void ) { return m_iPumpLevel; }
C_ResourceZone* GetResourceZone() { return m_hResourceZone.Get(); }
private:
CHealthBarPanel *m_pResourceBar;
int m_iPumpLevel;
CHandle<C_ResourceZone> m_hResourceZone;
private:
C_ObjectResourcePump( const C_ObjectResourcePump & ); // not defined, not accessible
};
#endif // C_OBJ_RESOURCEPUMP_H
+38
View File
@@ -0,0 +1,38 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CObjectSentrygun
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "CommanderOverlay.h"
#include "c_baseobject.h"
#include "vgui_healthbar.h"
#include "c_obj_respawn_station.h"
#include "C_BaseTFPlayer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT(C_ObjectRespawnStation, DT_ObjectRespawnStation, CObjectRespawnStation)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectRespawnStation::C_ObjectRespawnStation( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectRespawnStation::SetDormant( bool bDormant )
{
BaseClass::SetDormant( bDormant );
ENTITY_PANEL_ACTIVATE( "respawn_station", !bDormant );
}
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_OBJ_RESPAWN_STATION_H
#define C_OBJ_RESPAWN_STATION_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Respawn Station object
//-----------------------------------------------------------------------------
class C_ObjectRespawnStation : public C_BaseObject
{
DECLARE_CLASS( C_ObjectRespawnStation, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
DECLARE_ENTITY_PANEL();
C_ObjectRespawnStation();
// Status
virtual void SetDormant( bool bDormant );
protected:
// A special panel to indicate which one's the respawn station
CPanelRegistration m_SelectedRespawnPanel;
private:
C_ObjectRespawnStation( const C_ObjectRespawnStation & ); // not defined, not accessible
};
#endif // C_OBJ_RESPAWN_STATION_H
+151
View File
@@ -0,0 +1,151 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CObjectSentrygun
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseobject.h"
#include "c_basetfplayer.h"
#include "ObjectControlPanel.h"
#include "vgui_bitmapbutton.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Resupply Station object
//-----------------------------------------------------------------------------
class C_ObjectResupply : public C_BaseObject
{
DECLARE_CLASS( C_ObjectResupply, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectResupply();
private:
C_ObjectResupply( const C_ObjectResupply & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectResupply, DT_ObjectResupply, CObjectResupply)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectResupply::C_ObjectResupply()
{
}
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CResupplyControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CResupplyControlPanel, CObjectControlPanel );
public:
CResupplyControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnCommand( const char *command );
protected:
virtual void OnTickActive( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer );
private:
void Buy( ResupplyBuyType_t type );
vgui::Button *m_pBuyAmmoButton;
vgui::Button *m_pBuyGrenadesButton;
vgui::Button *m_pBuyHealthButton;
vgui::Button *m_pBuyAllButton;
};
DECLARE_VGUI_SCREEN_FACTORY( CResupplyControlPanel, "resupply_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CResupplyControlPanel::CResupplyControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CResupplyControlPanel" )
{
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CResupplyControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Grab ahold of certain well-known controls
m_pBuyAmmoButton = new CBitmapButton( GetActivePanel(), "BuyAmmoButton", "" );
m_pBuyGrenadesButton = new CBitmapButton( GetActivePanel(), "BuyGrenadesButton", "" );
m_pBuyHealthButton = new CBitmapButton( GetActivePanel(), "BuyHealthButton", "" );
m_pBuyAllButton = new CBitmapButton( GetActivePanel(), "BuyAllButton", "" );
return BaseClass::Init( pKeyValues, pInitData );
}
//-----------------------------------------------------------------------------
// Deactivates buttons we can't afford
//-----------------------------------------------------------------------------
void CResupplyControlPanel::OnTickActive( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer )
{
BaseClass::OnTickActive( pObj, pLocalPlayer );
int nBankResources = pLocalPlayer ? pLocalPlayer->GetBankResources() : 0;
m_pBuyAmmoButton->SetEnabled( nBankResources >= RESUPPLY_AMMO_COST );
m_pBuyGrenadesButton->SetEnabled( nBankResources >= RESUPPLY_GRENADES_COST );
m_pBuyHealthButton->SetEnabled( nBankResources >= RESUPPLY_HEALTH_COST );
m_pBuyAllButton->SetEnabled( nBankResources >= RESUPPLY_ALL_COST );
}
//-----------------------------------------------------------------------------
// Buys stuff
//-----------------------------------------------------------------------------
void CResupplyControlPanel::Buy( ResupplyBuyType_t type )
{
C_BaseObject *pObj = GetOwningObject();
if (pObj)
{
char szbuf[48];
Q_snprintf( szbuf, sizeof( szbuf ), "buy %d", type );
pObj->SendClientCommand( szbuf );
}
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CResupplyControlPanel::OnCommand( const char *command )
{
if (!Q_strnicmp(command, "BuyAmmo", 8))
{
Buy(RESUPPLY_BUY_AMMO);
}
else if (!Q_strnicmp(command, "BuyHealth", 10))
{
Buy(RESUPPLY_BUY_HEALTH);
}
else if (!Q_strnicmp(command, "BuyGrenades", 12))
{
Buy(RESUPPLY_BUY_GRENADES);
}
else if (!Q_strnicmp(command, "BuyAll", 7))
{
Buy(RESUPPLY_BUY_ALL);
}
else
{
BaseClass::OnCommand(command);
}
}
+38
View File
@@ -0,0 +1,38 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "commanderoverlay.h"
#include "c_baseobject.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectSandbagBunker : public C_BaseObject
{
DECLARE_CLASS( C_ObjectSandbagBunker, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectSandbagBunker();
private:
C_ObjectSandbagBunker( const C_ObjectSandbagBunker & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectSandbagBunker, DT_ObjectSandbagBunker, CObjectSandbagBunker)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectSandbagBunker::C_ObjectSandbagBunker()
{
}
+36
View File
@@ -0,0 +1,36 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "commanderoverlay.h"
#include "tf_obj_baseupgrade_shared.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectSelfHeal : public C_BaseObjectUpgrade
{
DECLARE_CLASS( C_ObjectSelfHeal, C_BaseObjectUpgrade );
public:
DECLARE_CLIENTCLASS();
C_ObjectSelfHeal();
private:
C_ObjectSelfHeal( const C_ObjectSelfHeal & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectSelfHeal, DT_ObjectSelfHeal, CObjectSelfHeal)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectSelfHeal::C_ObjectSelfHeal()
{
}
+106
View File
@@ -0,0 +1,106 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_OBJ_SENTRYGUN_H
#define C_OBJ_SENTRYGUN_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Base Sentrygun
//-----------------------------------------------------------------------------
class C_ObjectSentrygun : public C_BaseObject
{
DECLARE_CLASS( C_ObjectSentrygun, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
DECLARE_ENTITY_PANEL();
C_ObjectSentrygun();
virtual void GetBoneControllers(float controllers[MAXSTUDIOBONES]);
virtual int DrawModel( int flags );
virtual void SetDormant( bool bDormant );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual float GetInitialBuilderYaw();
int GetAmmoLeft( void ) { return m_iAmmo; }
virtual void FinishedBuilding( void );
virtual void ClientThink( void );
private:
bool IsTurtled( void ) { return m_bTurtled; }
// Turret Functions
bool MoveTurret( void );
// Recompute sentrygun orientation...
void RecomputeOrientation();
public:
int m_iRightBound;
int m_iLeftBound;
bool m_bTurningRight;
// Movement
int m_iBaseTurnRate;
float m_fTurnRate;
QAngle m_vecCurAngles;
QAngle m_vecGoalAngles;
Vector m_vecCurDishAngles;
float m_fBoneXRotator;
float m_fBoneYRotator;
int m_iAmmo;
// Turtling
bool m_bTurtled;
bool m_bLastTurtled;
float m_flStartedTurtlingAt;
float m_flStartedUnTurtlingAt;
int m_nAnimationParity;
int m_nLastAnimationParity;
// Networked from server
EHANDLE m_hEnemy;
QAngle m_angPrevLocalAngles;
int m_nOrientationParity;
int m_nPrevOrientationParity;
private:
C_ObjectSentrygun( const C_ObjectSentrygun & ); // not defined, not accessible
};
class C_ObjectSentrygunPlasma : public C_ObjectSentrygun
{
DECLARE_CLASS( C_ObjectSentrygunPlasma, C_ObjectSentrygun );
public:
C_ObjectSentrygunPlasma();
DECLARE_CLIENTCLASS();
private:
C_ObjectSentrygunPlasma( const C_ObjectSentrygunPlasma & ); // not defined, not accessible
};
class C_ObjectSentrygunRocketlauncher : public C_ObjectSentrygun
{
DECLARE_CLASS( C_ObjectSentrygunRocketlauncher, C_ObjectSentrygun );
public:
C_ObjectSentrygunRocketlauncher();
DECLARE_CLIENTCLASS();
private:
C_ObjectSentrygunRocketlauncher( const C_ObjectSentrygunRocketlauncher & ); // not defined, not accessible
};
#endif // C_OBJ_SENTRYGUN_H
+111
View File
@@ -0,0 +1,111 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CObjectSentrygun
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "CommanderOverlay.h"
#include "c_baseobject.h"
#include "vgui_healthbar.h"
#include "ObjectControlPanel.h"
#include "c_shield.h"
//-----------------------------------------------------------------------------
// Purpose: Resupply Station object
//-----------------------------------------------------------------------------
class C_ObjectShieldWallBase : public C_BaseObject
{
DECLARE_CLASS( C_ObjectShieldWallBase, C_BaseObject );
public:
C_ObjectShieldWallBase() {}
public:
CHandle<C_Shield> m_hDeployedShield;
private:
C_ObjectShieldWallBase( const C_ObjectShieldWallBase & ); // not defined, not accessible
};
//-----------------------------------------------------------------------------
//
// Projected shield wall
//
//-----------------------------------------------------------------------------
class C_ObjectShieldWall : public C_ObjectShieldWallBase
{
DECLARE_CLASS( C_ObjectShieldWall, C_ObjectShieldWallBase );
public:
DECLARE_CLIENTCLASS();
DECLARE_ENTITY_PANEL();
C_ObjectShieldWall( void );
virtual void SetDormant( bool bDormant );
virtual void RecalculateIDString( void );
private:
C_ObjectShieldWall( const C_ObjectShieldWall & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectShieldWall, DT_ObjectShieldWall, CObjectShieldWall)
RecvPropEHandle(RECVINFO(m_hDeployedShield)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectShieldWall::C_ObjectShieldWall( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectShieldWall::SetDormant( bool bDormant )
{
BaseClass::SetDormant( bDormant );
ENTITY_PANEL_ACTIVATE( "shield_wall", !bDormant );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectShieldWall::RecalculateIDString( void )
{
if ( m_hDeployedShield )
{
// Report shield strength
Q_snprintf( m_szIDString, sizeof(m_szIDString), "Shield Strength: %.0f percent", m_hDeployedShield->GetPowerLevel() * 100 );
}
BaseClass::RecalculateIDString();
}
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CShieldWallControlPanel : public CRotatingObjectControlPanel
{
DECLARE_CLASS( CShieldWallControlPanel, CRotatingObjectControlPanel );
public:
CShieldWallControlPanel( vgui::Panel *parent, const char *panelName );
};
DECLARE_VGUI_SCREEN_FACTORY( CShieldWallControlPanel, "shieldwall_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CShieldWallControlPanel::CShieldWallControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CShieldWallControlPanel" )
{
}
+69
View File
@@ -0,0 +1,69 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "commanderoverlay.h"
#include "c_baseobject.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectTower : public C_BaseObject
{
DECLARE_CLASS( C_ObjectTower, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectTower();
private:
C_ObjectTower( const C_ObjectTower & ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT(C_ObjectTower, DT_ObjectTower, CObjectTower)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectTower::C_ObjectTower()
{
}
//=============================================================================
// Tower Ladder
//=============================================================================
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectTowerLadder : public C_BaseAnimating
{
DECLARE_CLASS( C_ObjectTowerLadder, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_ObjectTowerLadder();
private:
C_ObjectTowerLadder( const C_ObjectTowerLadder& ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT( C_ObjectTowerLadder, DT_ObjectTowerLadder, CObjectTowerLadder )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectTowerLadder::C_ObjectTowerLadder()
{
}
+143
View File
@@ -0,0 +1,143 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "c_obj_mapdefined.h"
#include "minimap_trace.h"
#include <KeyValues.h>
#include "VGuiMatSurface/IMatSystemSurface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectTunnel : public C_ObjectMapDefined
{
DECLARE_CLASS( C_ObjectTunnel, C_ObjectMapDefined );
public:
DECLARE_PREDICTABLE();
DECLARE_CLIENTCLASS();
C_ObjectTunnel();
private:
C_ObjectTunnel( const C_ObjectTunnel& src );
};
LINK_ENTITY_TO_CLASS( obj_tunnel, C_ObjectTunnel );
BEGIN_PREDICTION_DATA( C_ObjectTunnel )
END_PREDICTION_DATA();
IMPLEMENT_CLIENTCLASS_DT(C_ObjectTunnel, DT_ObjectTunnel, CObjectTunnel)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectTunnel::C_ObjectTunnel()
{
CONSTRUCT_MINIMAP_PANEL( "obj_tunnel", MINIMAP_OBJECTS );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CMinimapObjectTunnelPanel : public CMinimapTraceTeamBitmapPanel
{
DECLARE_CLASS( CMinimapObjectTunnelPanel, CMinimapTraceTeamBitmapPanel );
public:
CMinimapObjectTunnelPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CMinimapObjectTunnelPanel" )
{
}
virtual bool Init( KeyValues* pKeyValues, MinimapInitData_t* pInitData );
virtual void Paint();
private:
enum
{
STATE_ENABLED = 0,
STATE_DISABLED,
NUM_STATES
};
CTeamBitmapImage m_TeamImage[ NUM_STATES ];
};
//-----------------------------------------------------------------------------
//
// A standard minimap renderable that displays a bitmap that changes when team changes
//
//-----------------------------------------------------------------------------
DECLARE_MINIMAP_FACTORY( CMinimapObjectTunnelPanel, "minimap_obj_tunnel_panel" );
//-----------------------------------------------------------------------------
// Purpose:
// Input : pKeyValues -
// pInitData -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CMinimapObjectTunnelPanel::Init( KeyValues* pKeyValues, MinimapInitData_t* pInitData )
{
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
// Load viewcone material
KeyValues *enabled = pKeyValues->FindKey( "EnabledImage" );
if ( enabled )
{
if ( !m_TeamImage[ STATE_ENABLED ].Init( this, enabled, pInitData->m_pEntity ) )
return false;
}
KeyValues *disabled = pKeyValues->FindKey( "DisabledImage" );
if ( disabled )
{
if ( !m_TeamImage[ STATE_DISABLED ].Init( this, disabled, pInitData->m_pEntity ) )
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMinimapObjectTunnelPanel::Paint()
{
// Draw the view cone
C_BaseEntity *pEntity = GetEntity();
Assert( pEntity );
if ( gHUD.IsHidden( HIDEHUD_MISCSTATUS ) )
return;
if ( !pEntity->IsBaseObject() )
return;
C_BaseObject *obj = static_cast< C_BaseObject * >( pEntity );
Assert( obj );
bool enabled = !obj->IsDisabled();
int image = enabled ? STATE_ENABLED : STATE_DISABLED;
if (!m_bClipToMap)
{
g_pMatSystemSurface->DisableClipping( true );
}
m_TeamImage[ image ].SetAlpha( ComputePanelAlpha() );
m_TeamImage[ image ].Paint();
g_pMatSystemSurface->DisableClipping( false );
}
+40
View File
@@ -0,0 +1,40 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "commanderoverlay.h"
#include "tf_obj_baseupgrade_shared.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectVehicleBoost : public C_BaseObjectUpgrade
{
DECLARE_CLASS( C_ObjectVehicleBoost, C_BaseObjectUpgrade );
public:
DECLARE_CLIENTCLASS();
C_ObjectVehicleBoost();
private:
C_ObjectVehicleBoost( const C_ObjectVehicleBoost& ); // not defined, not accessible
};
IMPLEMENT_CLIENTCLASS_DT( C_ObjectVehicleBoost, DT_ObjectVehicleBoost, CObjectVehicleBoost )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectVehicleBoost::C_ObjectVehicleBoost()
{
}
+558
View File
@@ -0,0 +1,558 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CObjectSentrygun
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "bone_setup.h"
#include "CommanderOverlay.h"
#include "c_baseobject.h"
#include "C_Obj_SentryGun.h"
#include "tf_shareddefs.h"
#include "c_basetfplayer.h"
#include "ObjectControlPanel.h"
#include <vgui_controls/Button.h>
inline float UTIL_AngleMod(float a)
{
return anglemod(a);
}
//-----------------------------------------------------------------------------
// Purpose: Base Sentrygun
//-----------------------------------------------------------------------------
BEGIN_RECV_TABLE_NOBASE(C_ObjectSentrygun, DT_SentrygunTeamOnlyVars)
RecvPropInt(RECVINFO( m_iAmmo )),
END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT(C_ObjectSentrygun, DT_ObjectSentrygun, CObjectSentrygun)
RecvPropInt( RECVINFO( m_iBaseTurnRate ) ),
RecvPropEHandle(RECVINFO(m_hEnemy)),
RecvPropDataTable( "teamonly", 0, 0, &REFERENCE_RECV_TABLE( DT_SentrygunTeamOnlyVars )),
RecvPropInt(RECVINFO(m_bTurtled)),
RecvPropInt( RECVINFO( m_nAnimationParity ) ),
RecvPropInt( RECVINFO( m_nOrientationParity ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectSentrygun::C_ObjectSentrygun()
{
m_fBoneXRotator = 0;
m_fBoneYRotator = 0;
m_iAmmo = 0;
m_bTurtled = false;
m_flStartedTurtlingAt = 0;
m_flStartedUnTurtlingAt = 0;
SetViewOffset( Vector(0,0,22) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::SetDormant( bool bDormant )
{
BaseClass::SetDormant( bDormant );
ENTITY_PANEL_ACTIVATE( "sentrygun", !bDormant );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_ObjectSentrygun::DrawModel( int flags )
{
float flRealOriginZ = GetLocalOrigin().z;
// If we're turtling, slide the model into the ground
if ( m_bTurtled )
{
// How far down are we?
float flTime = MIN( gpGlobals->curtime - m_flStartedTurtlingAt, SENTRY_TURTLE_TIME );
float flPercent = 1 - (SENTRY_TURTLE_TIME - flTime) / SENTRY_TURTLE_TIME;
// FIXME: This is totally wrong!!!
Vector vNewOrigin = GetLocalOrigin();
vNewOrigin.z -= (CollisionProp()->OBBSize().z * flPercent);
SetLocalOrigin( vNewOrigin );
InvalidateBoneCache();
}
else if ( !m_bTurtled )
{
if ( m_flStartedUnTurtlingAt )
{
float flTime = MIN( gpGlobals->curtime - m_flStartedUnTurtlingAt, SENTRY_TURTLE_TIME );
float flPercent = (SENTRY_TURTLE_TIME - flTime) / SENTRY_TURTLE_TIME;
// FIXME: This is totally wrong!!!
Vector vNewOrigin = GetLocalOrigin();
vNewOrigin.z -= (CollisionProp()->OBBSize().z * flPercent);
SetLocalOrigin( vNewOrigin );
InvalidateBoneCache();
// Fully unturtled?
if ( flTime >= SENTRY_TURTLE_TIME )
{
m_flStartedUnTurtlingAt = 0;
}
}
}
int drawn = BaseClass::DrawModel( flags );
SetLocalOriginDim( Z_INDEX, flRealOriginZ );
return drawn;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::PreDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PreDataUpdate( updateType );
m_bLastTurtled = m_bTurtled;
m_nLastAnimationParity = m_nAnimationParity;
m_angPrevLocalAngles = GetLocalAngles();
m_nPrevOrientationParity = m_nOrientationParity;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
if ( m_bLastTurtled != m_bTurtled )
{
if ( m_bTurtled )
{
m_flStartedTurtlingAt = gpGlobals->curtime;
m_flStartedUnTurtlingAt = 0;
}
else
{
m_flStartedUnTurtlingAt = gpGlobals->curtime;
m_flStartedTurtlingAt = 0;
}
}
if ( m_nLastAnimationParity != m_nAnimationParity )
{
SetCycle( 0.0f );
}
bool changed = false;
QAngle angleDiff;
angleDiff = ( GetAbsAngles() - m_angPrevLocalAngles );
for (int i = 0;i < 3; i++ )
{
angleDiff[i] = UTIL_AngleMod( angleDiff[ i ] );
}
if ( angleDiff.Length() > 0.1f )
{
changed = true;
}
if ( updateType == DATA_UPDATE_CREATED || changed )
{
// Orient it
m_vecCurAngles.y = UTIL_AngleMod( GetLocalAngles().y );
RecomputeOrientation();
}
else if ( m_nPrevOrientationParity != m_nOrientationParity )
{
if ( changed )
{
RecomputeOrientation();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
// Start thinking (Baseclass stops it)
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::FinishedBuilding( void )
{
BaseClass::FinishedBuilding();
EmitSound( "ObjectSentrygun.Activate" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS])
{
studiohdr_t *pModel = modelinfo->GetStudiomodel( GetModel() );
// When yaw preview is on,
if (!IsPreviewingYaw())
{
Studio_SetController(pModel, 0, m_fBoneXRotator, controllers[0]);
}
else
{
// Bone rotation == 0 here to make it exactly match the preview
Studio_SetController(pModel, 0, 0, controllers[0]);
}
Studio_SetController(pModel, 1, m_fBoneYRotator, controllers[1]);
Studio_SetController(pModel, 2, m_fBoneYRotator, controllers[2]);
Studio_SetController(pModel, 3, m_fBoneYRotator, controllers[3]);
}
//-----------------------------------------------------------------------------
// Purpose: This is called to get the initial builder yaw...
//-----------------------------------------------------------------------------
float C_ObjectSentrygun::GetInitialBuilderYaw()
{
// Take the current rotation into account
return GetAbsAngles().y + m_fBoneXRotator;
}
//-----------------------------------------------------------------------------
// Called when a rotation happens
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::RecomputeOrientation( )
{
m_iRightBound = UTIL_AngleMod( m_vecCurAngles.y - 50);
m_iLeftBound = UTIL_AngleMod( m_vecCurAngles.y + 50);
if ( m_iRightBound > m_iLeftBound )
{
m_iRightBound = m_iLeftBound;
m_iLeftBound = UTIL_AngleMod( m_vecCurAngles.y - 50);
}
// Start it rotating
m_vecGoalAngles.y = m_iRightBound;;
m_vecGoalAngles.x = m_vecCurAngles.x = 0;
m_fBoneXRotator = 0.0f;
m_fBoneYRotator = 0.0f;
m_bTurningRight = true;
}
//-----------------------------------------------------------------------------
// Purpose: Handle movement of the turret
//-----------------------------------------------------------------------------
bool C_ObjectSentrygun::MoveTurret(void)
{
bool bMoved = 0;
float turnrate = (float)(m_iBaseTurnRate) * 10.0f;
turnrate *= gpGlobals->frametime;
// any x movement?
if ( m_vecCurAngles.x != m_vecGoalAngles.x )
{
float flDir = m_vecGoalAngles.x > m_vecCurAngles.x ? 1 : -1 ;
m_vecCurAngles.x += 0.1 * (turnrate * 5) * flDir;
// if we started below the goal, and now we're past, peg to goal
if (flDir == 1)
{
if (m_vecCurAngles.x > m_vecGoalAngles.x)
m_vecCurAngles.x = m_vecGoalAngles.x;
}
else
{
if (m_vecCurAngles.x < m_vecGoalAngles.x)
m_vecCurAngles.x = m_vecGoalAngles.x;
}
m_fBoneYRotator = m_vecCurAngles.x;
bMoved = 1;
}
if ( m_vecCurAngles.y != m_vecGoalAngles.y )
{
float flDir = m_vecGoalAngles.y > m_vecCurAngles.y ? 1 : -1 ;
float flDist = fabs(m_vecGoalAngles.y - m_vecCurAngles.y);
bool bReversed = false;
if (flDist > 180)
{
flDist = 360 - flDist;
flDir = -flDir;
bReversed = true;
}
if (m_hEnemy == NULL )
{
if (flDist > 30)
{
if (m_fTurnRate < turnrate * 20)
{
m_fTurnRate += turnrate;
}
}
else
{
// Slow down
if ( m_fTurnRate > (turnrate * 5) )
m_fTurnRate -= turnrate;
}
}
else
{
// When tracking enemies, move faster and don't slow
if (flDist > 30)
{
if (m_fTurnRate < turnrate * 30)
{
m_fTurnRate += turnrate * 3;
}
}
}
m_vecCurAngles.y += 0.1 * m_fTurnRate * flDir;
// if we passed over the goal, peg right to it now
if (flDir == -1)
{
if ( (bReversed == false && m_vecGoalAngles.y > m_vecCurAngles.y) || (bReversed == true && m_vecGoalAngles.y < m_vecCurAngles.y) )
m_vecCurAngles.y = m_vecGoalAngles.y;
}
else
{
if ( (bReversed == false && m_vecGoalAngles.y < m_vecCurAngles.y) || (bReversed == true && m_vecGoalAngles.y > m_vecCurAngles.y) )
m_vecCurAngles.y = m_vecGoalAngles.y;
}
if (m_vecCurAngles.y < 0)
m_vecCurAngles.y += 360;
else if (m_vecCurAngles.y >= 360)
m_vecCurAngles.y -= 360;
if (flDist < (0.05 * turnrate))
m_vecCurAngles.y = m_vecGoalAngles.y;
m_fBoneXRotator = m_vecCurAngles.y - UTIL_AngleMod( GetAbsAngles().y );
bMoved = 1;
}
if ( !bMoved || !m_fTurnRate )
m_fTurnRate = turnrate;
if ( bMoved )
{
NetworkStateChanged();
}
return bMoved;
}
void C_ObjectSentrygun::ClientThink( void )
{
// Turtling sentryguns don't think
if ( IsTurtled() )
return;
if ( IsPlacing() || IsBuilding() )
return;
if ( m_hEnemy != NULL )
{
// Figure out where we're firing at
Vector vecMid = EyePosition();
Vector vecFireTarget = m_hEnemy->WorldSpaceCenter(); // + vecMid; // BodyTarget( vecMid );
Vector vecDirToEnemy = vecFireTarget - vecMid;
QAngle angToTarget;
VectorAngles(vecDirToEnemy, angToTarget);
angToTarget.y = UTIL_AngleMod( angToTarget.y );
if (angToTarget.x < -180)
angToTarget.x += 360;
if (angToTarget.x > 180)
angToTarget.x -= 360;
// now all numbers should be in [1...360]
// pin to turret limitations to [-50...50]
if (angToTarget.x > 50)
angToTarget.x = 50;
else if (angToTarget.x < -50)
angToTarget.x = -50;
m_vecGoalAngles.y = angToTarget.y;
m_vecGoalAngles.x = angToTarget.x;
MoveTurret();
return;
}
// Rotate
if ( !MoveTurret() )
{
// Play a sound occasionally
if ( random->RandomFloat(0, 1) < 0.02 )
{
EmitSound( "ObjectSentrygun.Idle" );
}
// Switch rotation direction
if (m_bTurningRight)
{
m_bTurningRight = false;
m_vecGoalAngles.y = m_iLeftBound;
}
else
{
m_bTurningRight = true;
m_vecGoalAngles.y = m_iRightBound;
}
// Randomly look up and down a bit
if ( random->RandomFloat(0, 1) < 0.3 )
{
m_vecGoalAngles.x = (int)random->RandomFloat(-10,10);
}
}
}
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CSentrygunControlPanel : public CRotatingObjectControlPanel
{
DECLARE_CLASS( CSentrygunControlPanel, CRotatingObjectControlPanel );
public:
CSentrygunControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick();
virtual void OnCommand( const char *command );
void AddAmmo( void );
private:
vgui::Label *m_pAmmoLabel;
};
DECLARE_VGUI_SCREEN_FACTORY( CSentrygunControlPanel, "sentrygun_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CSentrygunControlPanel::CSentrygunControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CSentrygunControlPanel" )
{
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CSentrygunControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
m_pAmmoLabel = new vgui::Label( this, "AmmoReadout", "" );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
return true;
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CSentrygunControlPanel::OnTick()
{
BaseClass::OnTick();
C_BaseObject *pObj = GetOwningObject();
if (!pObj)
return;
Assert( dynamic_cast<C_ObjectSentrygun*>(pObj) );
C_ObjectSentrygun *pSentrygun = static_cast<C_ObjectSentrygun*>(pObj);
char buf[256];
int iAmmo = pSentrygun->GetAmmoLeft();
if (iAmmo > 0)
{
Q_snprintf( buf, sizeof( buf ), "%d rounds left", iAmmo );
}
else
{
Q_snprintf( buf, sizeof( buf ), "OUT OF AMMO" );
}
m_pAmmoLabel->SetText( buf );
}
//-----------------------------------------------------------------------------
// Purpose: Handle ammo input to the sentrygun
//-----------------------------------------------------------------------------
void CSentrygunControlPanel::AddAmmo( void )
{
C_BaseObject *pObj = GetOwningObject();
if (pObj)
{
pObj->SendClientCommand( "addammo" );
}
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CSentrygunControlPanel::OnCommand( const char *command )
{
if (!Q_strnicmp(command, "AddAmmo", 7))
{
AddAmmo();
return;
}
BaseClass::OnCommand(command);
}
//======================================================================================================
// SENTRYGUN TYPES
//======================================================================================================
// Purpose: Plasma sentrygun
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT(C_ObjectSentrygunPlasma, DT_ObjectSentrygunPlasma, CObjectSentrygunPlasma)
END_RECV_TABLE()
C_ObjectSentrygunPlasma::C_ObjectSentrygunPlasma()
{
}
//-----------------------------------------------------------------------------
// Purpose: Rocket launcher sentrygun
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT(C_ObjectSentrygunRocketlauncher, DT_ObjectSentrygunRocketlauncher, CObjectSentrygunRocketlauncher)
END_RECV_TABLE()
C_ObjectSentrygunRocketlauncher::C_ObjectSentrygunRocketlauncher()
{
}
+462
View File
@@ -0,0 +1,462 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client Side COrder class
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud_orders.h"
#include "c_order.h"
#include <vgui_controls/Controls.h>
#include <vgui/ISurface.h>
#include "minimap_trace.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "c_func_resource.h"
#include "tf_shareddefs.h"
#include "c_baseobject.h"
#include "tf_hints.h"
#include "hud.h"
#include "c_basetfplayer.h"
#include "c_tf_hintmanager.h"
#include "clientmode_tfnormal.h"
#define NEW_ORDER_ANIM_DURATION 1.0f
#define NEW_ORDERS_RIGHT XRES(640-8)
#define NEW_ORDERS_LEFT XRES(8)
#define NEW_ORDERS_WIDTH (ORDERS_RIGHT - NEW_ORDERS_LEFT) //(NEW_ORDERS_RIGHT - ORDERS_LEFT)
class COrderLabel : public vgui::Label
{
public:
COrderLabel( vgui::Panel *pParent, const char *pPanelName, const char *pText )
: vgui::Label( pParent, pPanelName, pText )
{
}
virtual void OnThink()
{
BaseClass::OnThink();
// Resize?
int x, y, w, h;
if( m_flAnimCounter < NEW_ORDER_ANIM_DURATION )
{
int wantedWidth, dummy;
GetContentSize( wantedWidth, dummy );
wantedWidth += 10;
float flPercent = m_flAnimCounter / NEW_ORDER_ANIM_DURATION;
int newWidth = (int)(NEW_ORDERS_WIDTH + (wantedWidth - NEW_ORDERS_WIDTH) * flPercent);
GetBounds( x, y, w, h );
m_flAnimCounter += gpGlobals->frametime;
if( m_flAnimCounter >= NEW_ORDER_ANIM_DURATION )
{
SetBounds( ORDERS_RIGHT - wantedWidth, y, wantedWidth, h );
}
else
{
SetBounds( ORDERS_RIGHT - newWidth, y, newWidth, h );
}
}
}
virtual void PaintBackground()
{
// BaseClass::PaintBackground();
// Draw our background.
int x, y, w, h;
GetBounds( x, y, w, h );
vgui::surface()->DrawSetColor( Color( 0, 0, 0, 160 ) );
vgui::surface()->DrawFilledRect( 0, 0, w, h );
vgui::surface()->DrawSetColor( Color( 63, 63, 63, 255 ) );
vgui::surface()->DrawOutlinedRect( 0, 0, w, h );
}
public:
float m_flAnimCounter;
};
class CMinimapOrderPanel : public CMinimapTraceBitmapPanel
{
DECLARE_CLASS( CMinimapOrderPanel, CMinimapTraceBitmapPanel );
public:
CMinimapOrderPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CMinimapOrderPanel" )
{
}
virtual bool Init( KeyValues* pKeyValues, MinimapInitData_t* pInitData );
virtual void OnTick();
virtual void Paint( );
private:
C_Order *m_pOrder;
};
DECLARE_MINIMAP_FACTORY( CMinimapOrderPanel, "minimap_order_panel" );
bool CMinimapOrderPanel::Init( KeyValues* pKeyValues, MinimapInitData_t* pInitData )
{
m_pOrder = dynamic_cast<C_Order*>(pInitData->m_pEntity);
if (!m_pOrder)
return false;
if (!BaseClass::Init( pKeyValues, pInitData ))
return false;
return true;
}
//-----------------------------------------------------------------------------
// called when we're ticked...
//-----------------------------------------------------------------------------
void CMinimapOrderPanel::OnTick()
{
// NOTE: Do *not* chain down the the base OnTick; it's going to do
// a totally different computation that will conflict with ours
Assert( m_pOrder );
if( m_pOrder->GetTarget() <= 0 )
{
SetVisible(false);
return;
}
C_BaseEntity *pTarget = ClientEntityList().GetEnt( m_pOrder->GetTarget() );
if( !pTarget )
{
SetVisible(false);
return;
}
SetEntity( pTarget );
// Now that we're attached to the correct target, compute position!
BaseClass::OnTick();
}
void CMinimapOrderPanel::Paint( )
{
Assert( m_pOrder );
if( m_pOrder->GetTarget() <= 0 )
return;
C_BaseEntity *pTarget = ClientEntityList().GetEnt( m_pOrder->GetTarget() );
if( !pTarget )
return;
g_pMatSystemSurface->DisableClipping( true );
static float flStrobeDuration = 0.5;
float flShade = sin( gpGlobals->curtime * M_PI / flStrobeDuration ) * 0.5f + 0.5f;
Color color(255*flShade, 0, 0, 255);
m_Image.SetColor( color );
m_Image.Paint();
g_pMatSystemSurface->DisableClipping( false );
}
enum GetTargetDescriptionType_t
{
GETDESC_RESOURCEZONE=0,
GETDESC_OBJECT
};
char* GetTargetDescription( int entindex, GetTargetDescriptionType_t type )
{
static char szDesc[128];
szDesc[0]=0;
// Order target
if ( entindex )
{
C_BaseEntity *pEnt = cl_entitylist->GetEnt( entindex );
if ( pEnt )
{
if( type == GETDESC_RESOURCEZONE )
{
C_ResourceZone *pZone = dynamic_cast<C_ResourceZone*>(pEnt);
if ( pZone )
Q_strncpy( szDesc, pZone->GetTargetDescription(), sizeof( szDesc ) );
}
else if( type == GETDESC_OBJECT )
{
C_BaseObject *pObj = dynamic_cast<C_BaseObject*>( pEnt );
if( pObj )
Q_strncpy( szDesc, pObj->GetTargetDescription(), sizeof( szDesc ) );
}
}
}
return szDesc;
}
IMPLEMENT_CLIENTCLASS_DT(C_Order, DT_Order, COrder)
RecvPropInt( RECVINFO(m_iPriority) ),
RecvPropInt( RECVINFO(m_iOrderType) ),
RecvPropInt( RECVINFO(m_iTargetEntIndex) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_Order::C_Order( void )
{
m_nHintID = TF_HINT_UNDEFINED;
m_pNameLabel = NULL;
CONSTRUCT_MINIMAP_PANEL( "minimap_order", MINIMAP_PERSONAL_ORDERS );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_Order::~C_Order( void )
{
RemoveOrder();
if( C_BaseTFPlayer::GetLocalPlayer() )
C_BaseTFPlayer::GetLocalPlayer()->RemoveOrderTarget();
if ( m_nHintID != TF_HINT_UNDEFINED )
{
DestroyGlobalHint( m_nHintID );
}
}
void C_Order::ClientThink( void )
{
BaseClass::ClientThink();
if ( m_nHintID != TF_HINT_UNDEFINED )
{
switch ( m_iOrderType )
{
case ORDER_REPAIR:
m_nHintID = TF_HINT_REPAIROBJECT;
break;
default:
break;
}
}
if ( m_nHintID != TF_HINT_UNDEFINED )
{
CreateGlobalHint_Panel( m_pNameLabel, m_nHintID, NULL, index );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_Order::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer();
pPlayer->SetPersonalOrder( this );
// Update us if we've changed
if( updateType == DATA_UPDATE_CREATED )
{
CreateStatus( GetClientModeNormal()->GetViewport() );
}
else
{
GetHudOrderList()->RecalculateOrderList();
UpdateStatus();
}
if( m_iTargetEntIndex > 0 )
{
C_BaseEntity *pTarget = ClientEntityList().GetEnt( m_iTargetEntIndex );
m_OverlayPanel.Activate( pTarget, "personal_order", true );
}
if ( (updateType == DATA_UPDATE_CREATED) && ( m_nHintID != TF_HINT_UNDEFINED ) )
{
// Wait for animation to fly all the way in
SetNextClientThink( gpGlobals->curtime + NEW_ORDER_ANIM_DURATION + 0.25f );
}
}
//-----------------------------------------------------------------------------
// Purpose: Clean up a removed order
//-----------------------------------------------------------------------------
void C_Order::RemoveOrder( void )
{
m_OverlayPanel.RemoveOverlay();
DestroyStatus();
if ( m_pNameLabel )
{
delete m_pNameLabel;
m_pNameLabel = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: Get a text description of this order
//-----------------------------------------------------------------------------
void C_Order::GetDescription( char *pDest, int bufferSize )
{
char targetDesc[512];
GetTargetDescription( targetDesc, sizeof( targetDesc ) );
switch ( m_iOrderType )
{
case ORDER_ATTACK:
Q_snprintf( pDest, bufferSize, "Attack %s", targetDesc );
break;
case ORDER_DEFEND:
Q_snprintf( pDest, bufferSize, "Defend %s", targetDesc );
break;
case ORDER_CAPTURE:
Q_snprintf( pDest, bufferSize, "Capture %s", targetDesc );
break;
default:
Q_snprintf( pDest, bufferSize, "INVALID" );
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: Get a text description for the target of this order
//-----------------------------------------------------------------------------
void C_Order::GetTargetDescription( char *pDest, int bufferSize )
{
pDest[0] = 0;
if ( !m_iTargetEntIndex )
return;
C_BaseEntity *pEnt = cl_entitylist->GetEnt( m_iTargetEntIndex );
if ( !pEnt )
return;
C_ResourceZone *pZone = dynamic_cast<C_ResourceZone*>(pEnt);
if ( pZone )
{
Q_strncpy( pDest, pZone->GetTargetDescription(), bufferSize );
}
else
{
C_BaseObject *pObj = dynamic_cast<C_BaseObject*>( pEnt );
if( pObj )
Q_strncpy( pDest, pObj->GetTargetDescription(), bufferSize );
}
}
//-----------------------------------------------------------------------------
// Purpose: Create all elements needed in a status panel for this order
//-----------------------------------------------------------------------------
void C_Order::CreateStatus( vgui::Panel *pParent )
{
// If we already have our elements, we're just moving.
if ( m_pNameLabel )
{
m_pNameLabel->SetParent( pParent );
}
else
{
m_pNameLabel = new COrderLabel( pParent, "NameLabel", "Temp" );
m_pNameLabel->SetBounds( ORDERS_LEFT, ORDERS_TOP, NEW_ORDERS_WIDTH, ORDERS_ELEMENT_HEIGHT );
m_pNameLabel->SetAutoDelete( false );
m_pNameLabel->SetPaintBackgroundEnabled( true );
m_pNameLabel->SetFgColor( Color( 0, 0, 0, 255 ) );
m_pNameLabel->SetContentAlignment( vgui::Label::a_east );
m_pNameLabel->SetTextInset( -2, 0 );
}
UpdateStatus();
}
//-----------------------------------------------------------------------------
// Purpose: Destroy all elements in the status panel for this order
//-----------------------------------------------------------------------------
void C_Order::DestroyStatus( void )
{
if ( m_pNameLabel )
{
delete m_pNameLabel;
m_pNameLabel = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: Update all elements in the status panel for this order
//-----------------------------------------------------------------------------
void C_Order::UpdateStatus( void )
{
if ( m_pNameLabel )
{
char desc[512];
GetDescription( desc, sizeof( desc ) );
m_pNameLabel->SetText( desc );
m_pNameLabel->m_flAnimCounter = 0;
}
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this order wants a target reticle created around it's target
//-----------------------------------------------------------------------------
bool C_Order::ShouldDrawReticle( void )
{
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_Order::GetPriority( void )
{
return m_iPriority;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_Order::GetType( void )
{
return m_iOrderType;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_Order::GetTarget( void )
{
return m_iTargetEntIndex;
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this order is a personal one for this player
//-----------------------------------------------------------------------------
bool C_Order::IsPersonalOrder( void )
{
return (GetPriority() == 0);
}
+73
View File
@@ -0,0 +1,73 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client Side COrder class
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_H
#define C_ORDER_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Label.h>
#include <vgui_controls/Panel.h>
#include "CommanderOverlay.h"
#include "hud_minimap.h"
class COrderLabel;
//-----------------------------------------------------------------------------
// Purpose: Datatable container class for orders
//-----------------------------------------------------------------------------
class C_Order : public C_BaseEntity
{
DECLARE_CLASS( C_Order, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_Order( void );
~C_Order( void );
virtual void ClientThink( void );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void RemoveOrder( void );
virtual void GetDescription( char *pDest, int bufferSize );
virtual void GetTargetDescription( char *pDest, int bufferSize );
// Status drawing
virtual void CreateStatus( vgui::Panel *pParent );
virtual void DestroyStatus( void );
virtual void UpdateStatus( void );
virtual bool ShouldDrawReticle( void );
// Data access
int GetPriority( void );
int GetTarget( void );
int GetType( void );
bool IsPersonalOrder( void );
protected:
// Received via datatable
int m_iPriority;
int m_iOrderType;
int m_iTargetEntIndex;
// Used in status drawing
COrderLabel *m_pNameLabel;
// Animating panel to show the new order.
float m_flNewOrderHighlightTimer;
// Hook up the overlay on the tactical map.
DECLARE_ENTITY_PANEL();
DECLARE_MINIMAP_PANEL();
protected:
int m_nHintID;
};
#endif // C_ORDER_H
+22
View File
@@ -0,0 +1,22 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_assist.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderAssist, DT_OrderAssist, COrderAssist )
END_RECV_TABLE()
void C_OrderAssist::GetDescription( char *pDest, int bufferSize )
{
char targetDesc[512];
GetTargetDescription( targetDesc, sizeof( targetDesc ) );
Q_snprintf( pDest, bufferSize, "Assist %s", targetDesc );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_ASSIST_H
#define C_ORDER_ASSIST_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order_player.h"
class C_OrderAssist : public C_OrderPlayer
{
public:
DECLARE_CLASS( C_OrderAssist, C_OrderPlayer );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_ASSIST_H
@@ -0,0 +1,26 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_buildsentrygun.h"
#include "tf_hints.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderBuildSentryGun, DT_OrderBuildSentryGun, COrderBuildSentryGun )
END_RECV_TABLE()
C_OrderBuildSentryGun::C_OrderBuildSentryGun()
{
m_nHintID = TF_HINT_BUILDSENTRYGUN_PLASMA;
}
void C_OrderBuildSentryGun::GetDescription( char *pDest, int bufferSize )
{
Q_strncpy( pDest, "Build Sentry Gun To Protect Object", bufferSize );
}
+34
View File
@@ -0,0 +1,34 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_BUILDSENTRYGUN_H
#define C_ORDER_BUILDSENTRYGUN_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order.h"
class C_OrderBuildSentryGun : public C_Order
{
public:
DECLARE_CLASS( C_OrderBuildSentryGun, C_Order );
DECLARE_CLIENTCLASS();
C_OrderBuildSentryGun();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_BUILDSENTRYGUN_H
@@ -0,0 +1,19 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_buildshieldwall.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderBuildShieldWall, DT_OrderBuildShieldWall, COrderBuildShieldWall )
END_RECV_TABLE()
void C_OrderBuildShieldWall::GetDescription( char *pDest, int bufferSize )
{
Q_strncpy( pDest, "Build Shield Wall To Protect Object", bufferSize );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_BUILDSHIELDWALL_H
#define C_ORDER_BUILDSHIELDWALL_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order.h"
class C_OrderBuildShieldWall : public C_Order
{
public:
DECLARE_CLASS( C_OrderBuildShieldWall, C_Order );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_BUILDSHIELDWALL_H
+22
View File
@@ -0,0 +1,22 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_heal.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderHeal, DT_OrderHeal, COrderHeal )
END_RECV_TABLE()
void C_OrderHeal::GetDescription( char *pDest, int bufferSize )
{
char targetDesc[512];
GetTargetDescription( targetDesc, sizeof( targetDesc ) );
Q_snprintf( pDest, bufferSize, "Heal %s", targetDesc );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_HEAL_H
#define C_ORDER_HEAL_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order_player.h"
class C_OrderHeal : public C_OrderPlayer
{
public:
DECLARE_CLASS( C_OrderHeal, C_OrderPlayer );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_HEAL_H
+22
View File
@@ -0,0 +1,22 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_killmortarguy.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderKillMortarGuy, DT_OrderKillMortarGuy, COrderKillMortarGuy )
END_RECV_TABLE()
void C_OrderKillMortarGuy::GetDescription( char *pDest, int bufferSize )
{
char targetDesc[512];
GetTargetDescription( targetDesc, sizeof( targetDesc ) );
Q_snprintf( pDest, bufferSize, "Kill Mortar Guy: %s", targetDesc );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_KILLMORTARGUY_H
#define C_ORDER_KILLMORTARGUY_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order_player.h"
class C_OrderKillMortarGuy : public C_OrderPlayer
{
public:
DECLARE_CLASS( C_OrderKillMortarGuy, C_OrderPlayer );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_KILLMORTARGUY_H
+22
View File
@@ -0,0 +1,22 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_mortar_attack.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderMortarAttack, DT_OrderMortarAttack, COrderMortarAttack )
END_RECV_TABLE()
void C_OrderMortarAttack::GetDescription( char *pDest, int bufferSize )
{
char targetDesc[512];
GetTargetDescription( targetDesc, sizeof( targetDesc ) );
Q_snprintf( pDest, bufferSize, "Attack %s with mortar", targetDesc );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_MORTAR_ATTACK_H
#define C_ORDER_MORTAR_ATTACK_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order.h"
class C_OrderMortarAttack : public C_Order
{
public:
DECLARE_CLASS( C_OrderMortarAttack, C_Order );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_MORTAR_ATTACK_H
+38
View File
@@ -0,0 +1,38 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_player.h"
#include "cliententitylist.h"
#include "c_basetfplayer.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderPlayer, DT_OrderPlayer, COrderPlayer )
END_RECV_TABLE()
void C_OrderPlayer::GetTargetDescription( char *pDest, int bufferSize )
{
pDest[0] = 0;
// Order target
if ( !m_iTargetEntIndex )
return;
C_BaseEntity *pEnt = cl_entitylist->GetEnt(m_iTargetEntIndex);
if ( !pEnt )
return;
C_BaseTFPlayer *pPlayer = dynamic_cast<C_BaseTFPlayer*>(pEnt);
if ( pPlayer )
{
pPlayer->GetTargetDescription( pDest, bufferSize );
}
}
+33
View File
@@ -0,0 +1,33 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_PLAYER_H
#define C_ORDER_PLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order.h"
// Orders that point at players.
class C_OrderPlayer : public C_Order
{
public:
DECLARE_CLASS( C_OrderPlayer, C_Order );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetTargetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_PLAYER_H
+19
View File
@@ -0,0 +1,19 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_repair.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderRepair, DT_OrderRepair, COrderRepair )
END_RECV_TABLE()
void C_OrderRepair::GetDescription( char *pDest, int bufferSize )
{
Q_strncpy( pDest, "Repair Structure", bufferSize );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_REPAIR_H
#define C_ORDER_REPAIR_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order.h"
class C_OrderRepair : public C_Order
{
public:
DECLARE_CLASS( C_OrderRepair, C_Order );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_REPAIR_H
+27
View File
@@ -0,0 +1,27 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_resourcepump.h"
#include "tf_hints.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderResourcePump, DT_OrderResourcePump, COrderResourcePump )
END_RECV_TABLE()
C_OrderResourcePump::C_OrderResourcePump()
{
m_nHintID = TF_HINT_BUILDRESOURCEPUMP;
}
void C_OrderResourcePump::GetDescription( char *pDest, int bufferSize )
{
Q_strncpy( pDest, "Build Resource Pump", bufferSize );
}
+34
View File
@@ -0,0 +1,34 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_RESOURCEPUMP_H
#define C_ORDER_RESOURCEPUMP_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order.h"
class C_OrderResourcePump : public C_Order
{
public:
DECLARE_CLASS( C_OrderResourcePump, C_Order );
DECLARE_CLIENTCLASS();
C_OrderResourcePump();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_RESOURCEPUMP_H
@@ -0,0 +1,19 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_respawnstation.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderRespawnStation, DT_OrderRespawnStation, COrderRespawnStation )
END_RECV_TABLE()
void C_OrderRespawnStation::GetDescription( char *pDest, int bufferSize )
{
Q_strncpy( pDest, "Build Respawn Station Near Object", bufferSize );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_RESPAWNSTATION_H
#define C_ORDER_RESPAWNSTATION_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order_player.h"
class C_OrderRespawnStation : public C_Order
{
public:
DECLARE_CLASS( C_OrderRespawnStation, C_Order );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_RESPAWNSTATION_H
+19
View File
@@ -0,0 +1,19 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_order_resupply.h"
IMPLEMENT_CLIENTCLASS_DT( C_OrderResupply, DT_OrderResupply, COrderResupply )
END_RECV_TABLE()
void C_OrderResupply::GetDescription( char *pDest, int bufferSize )
{
Q_strncpy( pDest, "Build Resupply Station Near Object", bufferSize );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ORDER_RESUPPLY_H
#define C_ORDER_RESUPPLY_H
#ifdef _WIN32
#pragma once
#endif
#include "c_order.h"
class C_OrderResupply : public C_Order
{
public:
DECLARE_CLASS( C_OrderResupply, C_Order );
DECLARE_CLIENTCLASS();
// C_Order overrides.
public:
virtual void GetDescription( char *pDest, int bufferSize );
};
#endif // C_ORDER_RESUPPLY_H
+246
View File
@@ -0,0 +1,246 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "model_types.h"
#include "vcollide.h"
#include "vcollide_parse.h"
#include "solidsetdefaults.h"
#include "c_basetfplayer.h"
#include "bone_setup.h"
#include "engine/ivmodelinfo.h"
CPhysCollide *PhysCreateBbox( const Vector &mins, const Vector &maxs );
extern CSolidSetDefaults g_SolidSetup;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_RagdollShadow : public C_BaseAnimating
{
DECLARE_CLASS( C_RagdollShadow, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_RagdollShadow( void );
~C_RagdollShadow( void );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
virtual int DrawModel( int flags );
public:
IPhysicsObject *VPhysicsInitShadow( bool allowPhysicsMovement, bool allowPhysicsRotation );
void VPhysicsSetObject( IPhysicsObject *pPhysics );
void VPhysicsDestroyObject( void );
int m_nPlayer;
EHANDLE m_hPlayer;
IPhysicsObject *m_pPhysicsObject;
IPhysicsSpring *m_pSpring;
};
IMPLEMENT_CLIENTCLASS_DT( C_RagdollShadow, DT_RagdollShadow, CRagdollShadow )
RecvPropInt( RECVINFO( m_nPlayer ) ),
END_RECV_TABLE()
C_RagdollShadow::C_RagdollShadow( void )
{
m_nPlayer = -1;
m_hPlayer = NULL;
m_pPhysicsObject = NULL;
m_pSpring = NULL;
}
C_RagdollShadow::~C_RagdollShadow( void )
{
VPhysicsDestroyObject();
delete m_pSpring;
}
void C_RagdollShadow::VPhysicsDestroyObject( void )
{
if ( m_pPhysicsObject )
{
physenv->DestroyObject( m_pPhysicsObject );
m_pPhysicsObject = NULL;
}
}
// Create a physics thingy based on an existing collision model
IPhysicsObject *PhysModelCreateCustom( C_BaseEntity *pEntity, const CPhysCollide *pModel, const Vector &origin, const QAngle &angles, const char *props )
{
solid_t solid;
solid.params = g_PhysDefaultObjectParams;
solid.params.mass = 85.0f;
solid.params.inertia = 1e24f;
int surfaceProp = -1;
if ( props && props[0] )
{
surfaceProp = physprops->GetSurfaceIndex( props );
}
solid.params.pGameData = static_cast<void *>(pEntity);
IPhysicsObject *pObject = physenv->CreatePolyObject( pModel, surfaceProp, origin, angles, &solid.params );
return pObject;
}
IPhysicsObject *PhysModelCreateRagdoll( C_BaseEntity *pEntity, int modelIndex, const Vector &origin, const QAngle &angles )
{
vcollide_t *pCollide = modelinfo->GetVCollide( modelIndex );
if ( !pCollide )
return NULL;
solid_t solid;
memset( &solid, 0, sizeof(solid) );
solid.params = g_PhysDefaultObjectParams;
IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues );
while ( !pParse->Finished() )
{
const char *pBlock = pParse->GetCurrentBlockName();
if ( !strcmpi( pBlock, "solid" ) )
{
pParse->ParseSolid( &solid, &g_SolidSetup );
break;
}
else
{
pParse->SkipBlock();
}
}
physcollision->VPhysicsKeyParserDestroy( pParse );
// collisions are off by default
solid.params.enableCollisions = true;
int surfaceProp = -1;
if ( solid.surfaceprop[0] )
{
surfaceProp = physprops->GetSurfaceIndex( solid.surfaceprop );
}
solid.params.pGameData = static_cast<void *>(pEntity);
solid.params.pName = "ragdoll_player";
IPhysicsObject *pObject = physenv->CreatePolyObject( pCollide->solids[0], surfaceProp, origin, angles, &solid.params );
//PhysCheckAdd( pObject, STRING(pEntity->m_iClassname) );
return pObject;
}
void C_RagdollShadow::VPhysicsSetObject( IPhysicsObject *pPhysics )
{
if ( m_pPhysicsObject && pPhysics )
{
Warning( "C_RagdollShadow::Overwriting physics object!\n" );
}
m_pPhysicsObject = pPhysics;
}
// This creates a vphysics object with a shadow controller that follows the AI
IPhysicsObject *C_RagdollShadow::VPhysicsInitShadow( bool allowPhysicsMovement, bool allowPhysicsRotation )
{
CStudioHdr *hdr = GetModelPtr();
if ( !hdr )
{
return NULL;
}
// If this entity already has a physics object, then it should have been deleted prior to making this call.
Assert(!m_pPhysicsObject);
// make sure m_vecOrigin / m_vecAngles are correct
const Vector &origin = GetAbsOrigin();
QAngle angles = GetAbsAngles();
IPhysicsObject *pPhysicsObject = NULL;
if ( GetSolid() == SOLID_BBOX )
{
const char *pSurfaceProps = "flesh";
if ( GetModelIndex() && modelinfo->GetModelType( GetModel() ) == mod_studio )
{
pSurfaceProps = Studio_GetDefaultSurfaceProps( hdr );
}
angles = vec3_angle;
CPhysCollide *pCollide = PhysCreateBbox( WorldAlignMins(), WorldAlignMaxs() );
if ( !pCollide )
return NULL;
pPhysicsObject = PhysModelCreateCustom( this, pCollide, origin, angles, pSurfaceProps );
}
else
{
pPhysicsObject = PhysModelCreateRagdoll( this, GetModelIndex(), origin, angles );
}
VPhysicsSetObject( pPhysicsObject );
pPhysicsObject->SetShadow( 1e4, 1e4, allowPhysicsMovement, allowPhysicsRotation );
pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 );
// PhysAddShadow( this );
return pPhysicsObject;
}
void C_RagdollShadow::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// Has to happen *after* the client handle is set
SetNextClientThink( CLIENT_THINK_ALWAYS );
bool bnewentity = (updateType == DATA_UPDATE_CREATED);
if ( bnewentity && ( m_nPlayer != 0 ) )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
Assert( !m_pPhysicsObject );
C_BaseEntity *pl = static_cast< C_BaseEntity * >( cl_entitylist->GetEnt( m_nPlayer ) );
if ( pl )
{
m_hPlayer = pl;
}
m_pPhysicsObject = VPhysicsInitShadow( true, false );
}
if ( m_pPhysicsObject )
{
// Create the spring if we don't have one yet
if ( !m_pSpring )
{
C_BaseTFPlayer *pl = static_cast< C_BaseTFPlayer * >( (C_BaseEntity *)m_hPlayer );
if ( pl && pl->VPhysicsGetObject() )
{
springparams_t spring;
spring.constant = 15000;
spring.damping = 1.0;
spring.naturalLength = 0.0f;
spring.relativeDamping = 100.0f;
VectorCopy( vec3_origin, spring.startPosition );
VectorCopy( vec3_origin, spring.endPosition );
spring.useLocalPositions = true;
m_pSpring = physenv->CreateSpring( m_pPhysicsObject, pl->VPhysicsGetObject(), &spring );
PhysDisableObjectCollisions( m_pPhysicsObject, pl->VPhysicsGetObject() );
}
}
m_pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 );
}
}
void C_RagdollShadow::ClientThink( void )
{
BaseClass::ClientThink();
}
int C_RagdollShadow::DrawModel( int flags )
{
// int drawn = BaseClass::DrawModel( flags );
// return drawn;
return 0;
}
+22
View File
@@ -0,0 +1,22 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "particles_simple.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ResourceChunk : public C_BaseAnimating
{
DECLARE_CLASS( C_ResourceChunk, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
};
IMPLEMENT_CLIENTCLASS_DT( C_ResourceChunk, DT_ResourceChunk, CResourceChunk )
END_RECV_TABLE()
+837
View File
@@ -0,0 +1,837 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's sheild entity
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "C_Shield.h"
#include "clienteffectprecachesystem.h"
#include "clientmode.h"
#include "materialsystem/imesh.h"
#include "mapdata.h"
#include "ivrenderview.h"
#include "tf_shareddefs.h"
#include "collisionutils.h"
#include "functionproxy.h"
// Precache the effects
CLIENTEFFECT_REGISTER_BEGIN( Shield )
CLIENTEFFECT_MATERIAL( "shadertest/wireframevertexcolor" )
CLIENTEFFECT_MATERIAL( "effects/shield/shield" )
CLIENTEFFECT_MATERIAL( "effects/shieldhit" )
CLIENTEFFECT_MATERIAL( "effects/shieldpass" )
CLIENTEFFECT_MATERIAL( "effects/shieldpass2" )
CLIENTEFFECT_REGISTER_END()
//-----------------------------------------------------------------------------
// Stores a list of all active shields
//-----------------------------------------------------------------------------
CUtlVector< C_Shield* > C_Shield::s_Shields;
//-----------------------------------------------------------------------------
// Various important constants:
//-----------------------------------------------------------------------------
#define SHIELD_DAMAGE_CHANGE_FIRST_PASS_TIME 0.3f
#define SHIELD_DAMAGE_CHANGE_TRANSITION_TIME 0.5f
#define SHIELD_DAMAGE_CHANGE_TRANSITION_START_TIME (SHIELD_DAMAGE_CHANGE_TIME - SHIELD_DAMAGE_CHANGE_TRANSITION_TIME)
#define SHIELD_DAMAGE_CHANGE_TOTAL_TIME (SHIELD_DAMAGE_CHANGE_TRANSITION_START_TIME + SHIELD_DAMAGE_CHANGE_TRANSITION_TIME)
#define SHIELD_TRANSITION_MAX_BLEND_AMT 0.2f
//-----------------------------------------------------------------------------
// Data table
//-----------------------------------------------------------------------------
//EXTERN_RECV_TABLE(DT_BaseEntity);
IMPLEMENT_CLIENTCLASS_DT(C_Shield, DT_Shield, CShield)
RecvPropInt( RECVINFO(m_nOwningPlayerIndex) ),
RecvPropFloat( RECVINFO(m_flPowerLevel) ),
RecvPropInt( RECVINFO(m_bIsEMPed) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Shield color for the various protection types
//-----------------------------------------------------------------------------
static unsigned char s_ImpactDecalColor[3] = { 0, 0, 255 };
// ----------------------------------------------------------------------------
// Functions.
// ----------------------------------------------------------------------------
C_Shield::C_Shield()
{
m_pWireframe.Init( "shadertest/wireframevertexcolor", TEXTURE_GROUP_OTHER );
m_pShield.Init( "effects/shield/shield", TEXTURE_GROUP_CLIENT_EFFECTS );
m_pHitDecal.Init( "effects/shieldhit", TEXTURE_GROUP_CLIENT_EFFECTS );
m_pPassDecal.Init( "effects/shieldpass", TEXTURE_GROUP_CLIENT_EFFECTS );
m_pPassDecal2.Init( "effects/shieldpass2", TEXTURE_GROUP_CLIENT_EFFECTS );
m_FadeValue = 1.0f;
m_CurveValue = 1.0f;
m_bCollisionsActive = true;
s_Shields.AddToTail(this);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_Shield::~C_Shield()
{
int i = s_Shields.Find(this);
if ( i >= 0 )
{
s_Shields.FastRemove(i);
}
}
//-----------------------------------------------------------------------------
// Inherited classes should call this in their constructor to indicate size...
//-----------------------------------------------------------------------------
void C_Shield::InitShield( int w, int h, int subdivisions )
{
m_SplinePatch.Init( w, h, 2 );
m_SubdivisionCount = subdivisions;
Assert( m_SubdivisionCount > 1 );
m_InvSubdivisionCount = 1.0f / (m_SubdivisionCount - 1);
}
//-----------------------------------------------------------------------------
// This is called after a network update
//-----------------------------------------------------------------------------
void C_Shield::OnDataChanged( DataUpdateType_t updateType )
{
if (updateType == DATA_UPDATE_CREATED)
{
m_StartTime = engine->GetLastTimeStamp();
}
BaseClass::OnDataChanged( updateType );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : collisionGroup -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_Shield::ShouldCollide( int collisionGroup, int contentsMask ) const
{
return m_bCollisionsActive && ((collisionGroup == TFCOLLISION_GROUP_WEAPON) || (collisionGroup == TFCOLLISION_GROUP_GRENADE));
}
//-----------------------------------------------------------------------------
// Should I draw?
//-----------------------------------------------------------------------------
bool C_Shield::ShouldDraw()
{
// Let the client mode (like commander mode) reject drawing entities.
if (g_pClientMode && !g_pClientMode->ShouldDrawEntity(this) )
return false;
return true;
}
//-----------------------------------------------------------------------------
// Activates/deactivates a shield for collision purposes
//-----------------------------------------------------------------------------
void C_Shield::ActivateCollisions( bool activate )
{
m_bCollisionsActive = activate;
}
//-----------------------------------------------------------------------------
// Activates all shields
//-----------------------------------------------------------------------------
void C_Shield::ActivateShields( bool activate, int team )
{
for (int i = s_Shields.Count(); --i >= 0; )
{
// Activate all shields on the same team
if ( (team == -1) || (team == s_Shields[i]->GetTeamNumber()) )
{
s_Shields[i]->ActivateCollisions( activate );
}
}
}
//-----------------------------------------------------------------------------
// Helper method for collision testing
//-----------------------------------------------------------------------------
#pragma warning ( disable : 4701 )
bool C_Shield::TestCollision( const Ray_t& ray, unsigned int mask, trace_t& trace )
{
// Can't block anything if we're EMPed, or we've got no power left to block
if ( m_bIsEMPed )
return false;
if ( m_flPowerLevel <= 0 )
return false;
// Here, we're gonna test for collision.
// If we don't stop this kind of bullet, we'll generate an effect here
// but we won't change the trace to indicate a collision.
// It's just polygon soup...
int hitgroup;
bool firstTri;
int v1[2], v2[2], v3[2];
float ihit, jhit;
float mint = FLT_MAX;
float t;
int h = Height();
int w = Width();
for (int i = 0; i < h - 1; ++i)
{
for (int j = 0; j < w - 1; ++j)
{
// Don't test if this panel ain't active...
if (!IsPanelActive( j, i ))
continue;
// NOTE: Structure order of points so that our barycentric
// axes for each triangle are along the (u,v) directions of the mesh
// The barycentric coords we'll need below
// Two triangles per quad...
t = IntersectRayWithTriangle( ray,
GetPoint( j, i + 1 ),
GetPoint( j + 1, i + 1 ),
GetPoint( j, i ), true );
if ((t >= 0.0f) && (t < mint))
{
mint = t;
v1[0] = j; v1[1] = i + 1;
v2[0] = j + 1; v2[1] = i + 1;
v3[0] = j; v3[1] = i;
ihit = i; jhit = j;
firstTri = true;
}
t = IntersectRayWithTriangle( ray,
GetPoint( j + 1, i ),
GetPoint( j, i ),
GetPoint( j + 1, i + 1 ), true );
if ((t >= 0.0f) && (t < mint))
{
mint = t;
v1[0] = j + 1; v1[1] = i;
v2[0] = j; v2[1] = i;
v3[0] = j + 1; v3[1] = i + 1;
ihit = i; jhit = j;
firstTri = false;
}
}
}
if (mint == FLT_MAX)
return false;
// Stuff the barycentric coordinates of the triangle hit into the hit group
// For the first triangle, the first edge goes along u, the second edge goes
// along -v. For the second triangle, the first edge goes along -u,
// the second edge goes along v.
const Vector& v1vec = GetPoint(v1[0], v1[1]);
const Vector& v2vec = GetPoint(v2[0], v2[1]);
const Vector& v3vec = GetPoint(v3[0], v3[1]);
float u, v;
bool ok = ComputeIntersectionBarycentricCoordinates( ray,
v1vec, v2vec, v3vec, u, v );
Assert( ok );
if ( !ok )
{
return false;
}
if (firstTri)
v = 1.0 - v;
else
u = 1.0 - u;
v += ihit; u += jhit;
v /= (h - 1);
u /= (w - 1);
// Compress (u,v) into 1 dot 15, v in top bits
hitgroup = (((int)(v * (1 << 15))) << 16) + (int)(u * (1 << 15));
Vector normal;
float intercept;
ComputeTrianglePlane( v1vec, v2vec, v3vec, normal, intercept );
UTIL_SetTrace( trace, ray, this, mint, hitgroup, CONTENTS_SOLID, normal, intercept );
return true;
}
#pragma warning ( default : 4701 )
//-----------------------------------------------------------------------------
// Called when we hit something that we deflect...
//-----------------------------------------------------------------------------
void C_Shield::RegisterDeflection(const Vector& vecDir, int bitsDamageType, trace_t *ptr)
{
Vector normalDir;
VectorCopy( vecDir, normalDir );
VectorNormalize( normalDir );
CreateShieldDeflection( ptr->hitgroup, normalDir, false );
}
//-----------------------------------------------------------------------------
// This is required to get all the decals to animate correctly
//-----------------------------------------------------------------------------
void C_Shield::SetCurrentDecal( int idx )
{
m_CurrentDecal = idx;
}
//-----------------------------------------------------------------------------
// returns the address of a variable that stores the material animation frame
//-----------------------------------------------------------------------------
float C_Shield::GetTextureAnimationStartTime()
{
if( m_CurrentDecal == -1 )
return m_StartTime;
return m_Decals[m_CurrentDecal].m_StartTime;
}
//-----------------------------------------------------------------------------
// Indicates that a texture animation has wrapped
//-----------------------------------------------------------------------------
void C_Shield::TextureAnimationWrapped()
{
if( m_CurrentDecal != -1 )
{
m_Decals[m_CurrentDecal].m_StartTime = -1.0f;
}
}
//-----------------------------------------------------------------------------
// Indicates a collision occurred:
//-----------------------------------------------------------------------------
void C_Shield::ReceiveMessage( int classID, bf_read &msg )
{
if ( classID != GetClientClass()->m_ClassID )
{
// message is for subclass
BaseClass::ReceiveMessage( classID, msg );
return;
}
int hitgroup;
Vector dir;
unsigned char partialBlock;
hitgroup = msg.ReadLong( );
msg.ReadBitVec3Normal( dir );
partialBlock = msg.ReadByte( );
CreateShieldDeflection( hitgroup, dir, partialBlock );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_Shield::CreateShieldDeflection( int hitgroup, const Vector &dir, bool partialBlock )
{
float hitU = (float)(hitgroup & 0xFFFF) / (float)(1 << 15);
float hitV = (float)(hitgroup >> 16) / (float)(1 << 15);
Ripple_t ripple;
ripple.m_RippleU = hitU;
ripple.m_RippleV = hitV;
ripple.m_Amplitude = partialBlock ? 4 : 30;
ripple.m_Radius = 0.08f;
ripple.m_StartTime = engine->GetLastTimeStamp();
ripple.m_Direction = dir;
m_Ripples.AddToTail(ripple);
Decal_t decal;
decal.m_RippleU = hitU;
decal.m_RippleV = hitV;
decal.m_Radius = partialBlock ? 0.03f : 0.08f;
decal.m_StartTime = engine->GetLastTimeStamp();
m_Decals.AddToTail(decal);
}
//-----------------------------------------------------------------------------
// Draws the control points in wireframe
//-----------------------------------------------------------------------------
void C_Shield::DrawWireframeModel( Vector const** ppPositions )
{
IMesh* pMesh = materials->GetDynamicMesh( true, NULL, NULL, m_pWireframe );
int numLines = (Height() - 1) * Width() + Height() * (Width() - 1);
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_LINES, numLines );
Vector const* tmp;
for (int i = 0; i < Height(); ++i)
{
for (int j = 0; j < Width(); ++j)
{
if ( i > 0 )
{
tmp = ppPositions[j + Width() * i];
meshBuilder.Position3fv( tmp->Base() );
meshBuilder.Color4ub( 255, 255, 255, 128 );
meshBuilder.AdvanceVertex();
tmp = ppPositions[j + Width() * (i-1)];
meshBuilder.Position3fv( tmp->Base() );
meshBuilder.Color4ub( 255, 255, 255, 128 );
meshBuilder.AdvanceVertex();
}
if (j > 0)
{
tmp = ppPositions[j + Width() * i];
meshBuilder.Position3fv( tmp->Base() );
meshBuilder.Color4ub( 255, 255, 255, 128 );
meshBuilder.AdvanceVertex();
tmp = ppPositions[j - 1 + Width() * i];
meshBuilder.Position3fv( tmp->Base() );
meshBuilder.Color4ub( 255, 255, 255, 128 );
meshBuilder.AdvanceVertex();
}
}
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Draws the base shield
//-----------------------------------------------------------------------------
#define TRANSITION_REGION_WIDTH 0.5f
extern ConVar mat_wireframe;
void C_Shield::DrawShieldPoints(Vector* pt, Vector* normal, float* opacity)
{
SetCurrentDecal( -1 );
if (mat_wireframe.GetInt() == 0)
materials->Bind( m_pShield, (IClientRenderable*)this );
else
materials->Bind( m_pWireframe, (IClientRenderable*)this );
IMesh* pMesh = materials->GetDynamicMesh( true, NULL, NULL );
int numTriangles = (m_SubdivisionCount - 1) * (m_SubdivisionCount - 1) * 2;
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, numTriangles );
float du = 1.0f * m_InvSubdivisionCount;
float dv = du;
unsigned char color[3];
color[0] = 255;
color[1] = 255;
color[2] = 255;
for ( int i = 0; i < m_SubdivisionCount - 1; ++i)
{
float v = i * dv;
for (int j = 0; j < m_SubdivisionCount - 1; ++j)
{
int idx = i * m_SubdivisionCount + j;
float u = j * du;
meshBuilder.Position3fv( pt[idx].Base() );
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx] );
meshBuilder.Normal3fv( normal[idx].Base() );
meshBuilder.TexCoord2f( 0, u, v );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + m_SubdivisionCount].Base() );
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+m_SubdivisionCount] );
meshBuilder.Normal3fv( normal[idx + m_SubdivisionCount].Base() );
meshBuilder.TexCoord2f( 0, u, v + dv );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + 1].Base() );
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+1] );
meshBuilder.Normal3fv( normal[idx+1].Base() );
meshBuilder.TexCoord2f( 0, u + du, v );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + 1].Base() );
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+1] );
meshBuilder.Normal3fv( normal[idx+1].Base() );
meshBuilder.TexCoord2f( 0, u + du, v );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + m_SubdivisionCount].Base() );
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+m_SubdivisionCount] );
meshBuilder.Normal3fv( normal[idx + m_SubdivisionCount].Base() );
meshBuilder.TexCoord2f( 0, u, v + dv );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + m_SubdivisionCount + 1].Base() );
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+m_SubdivisionCount+1] );
meshBuilder.Normal3fv( normal[idx + m_SubdivisionCount + 1].Base() );
meshBuilder.TexCoord2f( 0, u + du, v + dv );
meshBuilder.AdvanceVertex();
}
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Draws shield decals
//-----------------------------------------------------------------------------
void C_Shield::DrawShieldDecals( Vector* pt, bool hitDecals )
{
if (m_Decals.Size() == 0)
return;
// Compute ripples:
for ( int r = m_Decals.Size(); --r >= 0; )
{
// At the moment, nothing passes!
bool passDecal = false;
if ((!hitDecals) && (passDecal == hitDecals))
continue;
SetCurrentDecal( r );
// We have to force a flush here because we're changing the proxy state
if (!hitDecals)
materials->Bind( m_pPassDecal, (IClientRenderable*)this );
else
materials->Bind( passDecal ? m_pPassDecal2 : m_pHitDecal, (IClientRenderable*)this );
float dtime = gpGlobals->curtime - m_Decals[r].m_StartTime;
float decay = exp( -( 2 * dtime) );
// Retire the animation if it wraps
// This gets set by TextureAnimatedWrapped above
if ((m_Decals[r].m_StartTime < 0.0f) || (decay < 1e-3))
{
m_Decals.Remove(r);
continue;
}
IMesh* pMesh = materials->GetDynamicMesh();
// Figure out the quads we must mod2x....
float u0 = m_Decals[r].m_RippleU - m_Decals[r].m_Radius;
float u1 = m_Decals[r].m_RippleU + m_Decals[r].m_Radius;
float v0 = m_Decals[r].m_RippleV - m_Decals[r].m_Radius;
float v1 = m_Decals[r].m_RippleV + m_Decals[r].m_Radius;
float du = u1 - u0;
float dv = v1 - v0;
int i0 = Floor2Int( v0 * (m_SubdivisionCount - 1) );
int i1 = Ceil2Int( v1 * (m_SubdivisionCount - 1) );
int j0 = Floor2Int( u0 * (m_SubdivisionCount - 1) );
int j1 = Ceil2Int( u1 * (m_SubdivisionCount - 1) );
if (i0 < 0)
i0 = 0;
if (i1 >= m_SubdivisionCount)
i1 = m_SubdivisionCount - 1;
if (j0 < 0)
j0 = 0;
if (j1 >= m_SubdivisionCount)
j1 = m_SubdivisionCount - 1;
int numTriangles = (i1 - i0) * (j1 - j0) * 2;
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, numTriangles );
float decalDu = m_InvSubdivisionCount / du;
float decalDv = m_InvSubdivisionCount / dv;
unsigned char color[3];
color[0] = s_ImpactDecalColor[0] * decay;
color[1] = s_ImpactDecalColor[1] * decay;
color[2] = s_ImpactDecalColor[2] * decay;
for ( int i = i0; i < i1; ++i)
{
float t = (float)i * m_InvSubdivisionCount;
for (int j = j0; j < j1; ++j)
{
float s = (float)j * m_InvSubdivisionCount;
int idx = i * m_SubdivisionCount + j;
// Compute (u,v) into the decal
float decalU = (s - u0) / du;
float decalV = (t - v0) / dv;
meshBuilder.Position3fv( pt[idx].Base() );
meshBuilder.Color3ubv( color );
meshBuilder.TexCoord2f( 0, decalU, decalV );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + m_SubdivisionCount].Base() );
meshBuilder.Color3ubv( color );
meshBuilder.TexCoord2f( 0, decalU, decalV + decalDv );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + 1].Base() );
meshBuilder.Color3ubv( color );
meshBuilder.TexCoord2f( 0, decalU + decalDu, decalV );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + 1].Base() );
meshBuilder.Color3ubv( color );
meshBuilder.TexCoord2f( 0, decalU + decalDu, decalV );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + m_SubdivisionCount].Base() );
meshBuilder.Color3ubv( color );
meshBuilder.TexCoord2f( 0, decalU, decalV + decalDv );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( pt[idx + m_SubdivisionCount + 1].Base() );
meshBuilder.Color3ubv( color );
meshBuilder.TexCoord2f( 0, decalU + decalDu, decalV + decalDv );
meshBuilder.AdvanceVertex();
}
}
meshBuilder.End();
pMesh->Draw();
}
}
//-----------------------------------------------------------------------------
// Computes a single point
//-----------------------------------------------------------------------------
void C_Shield::ComputePoint( float s, float t, Vector& pt, Vector& normal, float& opacity )
{
// Precache some computations for the point on the spline at (s, t).
m_SplinePatch.SetupPatchQuery( s, t );
// Get the position + normal
m_SplinePatch.GetPointAndNormal( pt, normal );
// From here on down is all futzing with opacity
// Check neighbors for activity...
bool active = IsPanelActive(m_SplinePatch.m_is, m_SplinePatch.m_it);
if (m_SplinePatch.m_fs == 0.0f)
active = active || IsPanelActive(m_SplinePatch.m_is - 1, m_SplinePatch.m_it);
if (m_SplinePatch.m_ft == 0.0f)
active = active || IsPanelActive(m_SplinePatch.m_is, m_SplinePatch.m_it - 1);
if (!active)
{
// If the panel's not active, it's transparent.
opacity = 0.0f;
}
else
{
if ((s == 0.0f) || (t == 0.0f) ||
(s == (Width() - 1.0f)) || (t == (Height() - 1.0f)) )
{
// If it's on the edge, it's max opacity
opacity = 192.0f;
}
else
{
// Channel zero is the opacity data
opacity = m_SplinePatch.GetChannel( 0 );
// Make the shield translucent if the owner is the local player...
// Also don't mess with the edges..
if (m_ShieldOwnedByLocalPlayer)
{
// Channel 1 is the opacity blend
float blendFactor = m_SplinePatch.GetChannel( 1 );
blendFactor = clamp( blendFactor, 0.0f, 1.0f );
float blendValue = 1.0f;
Vector delta;
VectorSubtract( pt, GetAbsOrigin(), delta );
float dist = VectorLength( delta );
if (dist != 0.0f)
{
delta *= 1.0f / dist;
float dot = DotProduct( m_ViewDir, delta );
float angle = acos( dot );
float fov = M_PI * render->GetFieldOfView() / 180.0f;
if (angle < fov * .2f)
blendValue = 0.1f;
else if (angle < fov * 0.4f)
{
// Want a cos falloff between .2 and .4
// 0.1 at .2 and 1.0 at .4
angle -= fov * 0.2f;
blendValue = 1.0f - 0.9f * 0.5f * (cos ( M_PI * angle / (fov * 0.2f) ) + 1.0f);
}
}
// Interpolate between 1 and the blend value based on the blend factor...
opacity *= (1.0f - blendFactor) + blendFactor * blendValue;
}
opacity = clamp( opacity, 0.0f, 192.0f );
}
}
opacity *= m_FadeValue;
}
//-----------------------------------------------------------------------------
// Compute the shield points using catmull-rom
//-----------------------------------------------------------------------------
void C_Shield::ComputeShieldPoints( Vector* pt, Vector* normal, float* opacity )
{
int i;
for ( i = 0; i < m_SubdivisionCount; ++i)
{
float t = (Height() - 1) * (float)i * m_InvSubdivisionCount;
for (int j = 0; j < m_SubdivisionCount; ++j)
{
float s = (Width() - 1) * (float)j * m_InvSubdivisionCount;
int idx = i * m_SubdivisionCount + j;
ComputePoint( s, t, pt[idx], normal[idx], opacity[idx] );
}
}
}
//-----------------------------------------------------------------------------
// Compute the shield ripples from being hit
//-----------------------------------------------------------------------------
void C_Shield::RippleShieldPoints( Vector* pt, float* opacity )
{
// Compute ripples:
for ( int r = m_Ripples.Size(); --r >= 0; )
{
float dtime = gpGlobals->curtime - m_Ripples[r].m_StartTime;
float decay = exp( -( 2 * dtime) );
float amplitude = m_Ripples[r].m_Amplitude * decay;
for ( int i = 0; i < m_SubdivisionCount; ++i)
{
float t = i * m_InvSubdivisionCount;
for (int j = 0; j < m_SubdivisionCount; ++j)
{
float s = j * m_InvSubdivisionCount;
int idx = i * m_SubdivisionCount + j;
float ds = s - m_Ripples[r].m_RippleU;
float dt = t - m_Ripples[r].m_RippleV;
float dr = sqrt( ds * ds + dt * dt );
if (dr < m_Ripples[r].m_Radius)
{
// need to apply ripple
float diff = amplitude * cos( 0.5f * M_PI * dr / m_Ripples[r].m_Radius );
VectorMA( pt[idx], diff, m_Ripples[r].m_Direction, pt[idx] );
// Compute opacity at this point...
float impactopacity = 192.0f * decay * dr / m_Ripples[r].m_Radius;
if (impactopacity > opacity[idx])
opacity[idx] = impactopacity;
}
}
}
if (amplitude < 0.1)
m_Ripples.Remove(r);
}
}
//-----------------------------------------------------------------------------
// Main draw entry point
//-----------------------------------------------------------------------------
int C_Shield::DrawModel( int flags )
{
if ( !m_bReadyToDraw )
return 0;
if (m_FadeValue == 0.0f)
return 1;
// If I have no power, don't draw
if ( m_flPowerLevel <= 0 )
return 1;
// Make it curvy or not!!
m_SplinePatch.SetLinearBlend( m_CurveValue );
// Set up the patch with all the data it's going to need
int count = Width() * Height();
Vector const** pControlPoints = (Vector const**)stackalloc(count * sizeof(Vector*));
float* pControlOpacity = (float*)stackalloc(count * sizeof(float));
float* pControlBlend = (float*)stackalloc(count * sizeof(float));
GetShieldData( pControlPoints, pControlOpacity, pControlBlend );
m_SplinePatch.SetControlPositions( pControlPoints );
m_SplinePatch.SetChannelData( 0, pControlOpacity );
m_SplinePatch.SetChannelData( 1, pControlBlend );
// DrawWireframeModel( pControlPoints );
// Allocate space for temporary data
int numSubdivisions = m_SubdivisionCount * m_SubdivisionCount;
Vector* pt = (Vector*)stackalloc(numSubdivisions * sizeof(Vector));
Vector* normal = (Vector*)stackalloc(numSubdivisions * sizeof(Vector));
float* opacity = (float*)stackalloc(numSubdivisions * sizeof(float));
// Do something a little special if this shield is owned by the local player
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
m_ShieldOwnedByLocalPlayer = (player->entindex() == m_nOwningPlayerIndex);
if (m_ShieldOwnedByLocalPlayer)
{
QAngle viewAngles;
engine->GetViewAngles(viewAngles);
AngleVectors( viewAngles, &m_ViewDir );
}
ComputeShieldPoints( pt, normal, opacity );
RippleShieldPoints( pt, opacity );
// Commented out because it causes things to not be drawn behind it
// DrawShieldDecals( pt, false );
DrawShieldPoints( pt, normal, opacity );
DrawShieldDecals( pt, true );
return 1;
}
//============================================================================================================
// SHIELD POWERLEVEL PROXY
//============================================================================================================
class CShieldPowerLevelProxy : public CResultProxy
{
public:
void OnBind( void *pC_BaseEntity );
};
void CShieldPowerLevelProxy::OnBind( void *pRenderable )
{
IClientRenderable *pRend = (IClientRenderable *)pRenderable;
C_BaseEntity *pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
C_Shield *pShield = dynamic_cast<C_Shield*>(pEntity);
if (!pShield)
return;
SetFloatResult( pShield->GetPowerLevel() );
}
EXPOSE_INTERFACE( CShieldPowerLevelProxy, IMaterialProxy, "ShieldPowerLevel" IMATERIAL_PROXY_INTERFACE_VERSION );
+199
View File
@@ -0,0 +1,199 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's sheild entity
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef C_SHIELD_H
#define C_SHIELD_H
#ifdef _WIN32
#pragma once
#endif
#include "SplinePatch.h"
//-----------------------------------------------------------------------------
// Shield:
//-----------------------------------------------------------------------------
class C_Shield : public C_BaseEntity
{
public:
DECLARE_CLASS( C_Shield, C_BaseEntity );
DECLARE_CLIENTCLASS();
// constructor, destructor
C_Shield();
~C_Shield();
// Inherited classes should call this in their constructor to indicate size...
void InitShield( int w, int h, int subdivisions );
void OnDataChanged( DataUpdateType_t updateType );
int DrawModel( int flags );
void ReceiveMessage( int classID, bf_read &msg );
void CreateShieldDeflection( int hitgroup, const Vector &dir, bool partialBlock );
virtual bool ShouldDraw();
virtual bool IsTransparent() { return true; }
virtual void SetAlwaysOrient( bool bOrient ) {}
virtual bool IsAlwaysOrienting( ) { return false; }
virtual void SetCenterAngles( const QAngle & ) {}
virtual void SetAttachmentIndex( int nAttachmentIndex ) {}
// returns the address of a variable that stores the material animation frame
float GetTextureAnimationStartTime();
// Indicates that a texture animation has wrapped
void TextureAnimationWrapped();
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
// Collision detection
// Activates/deactivates a shield for collision purposes
void ActivateCollisions( bool activate );
// Deactivates all shields of players on a particular team
// If you don't specify a team, it'll affect all shields
static void ActivateShields( bool activate, int team = -1 );
virtual const Vector& GetPoint( int x, int y ) { return vec3_origin; }
// For collision testing
bool TestCollision( const Ray_t& ray, unsigned int mask, trace_t& trace );
// Called when we hit something that we deflect...
void RegisterDeflection(const Vector& vecDir, int bitsDamageType, trace_t *ptr);
float GetPowerLevel( void ) { return m_flPowerLevel; }
bool IsEMPed() const;
void SetEMPed( bool bIsEmped );
protected:
//
// Inheriting classes must implement these methods!!!
//
// Return true if the panel is active
virtual bool IsPanelActive( int x, int y ) { assert(0); return false; }
// Gets at the control point data; who knows how it was made?
virtual void GetShieldData( Vector const** ppVerts, float* pOpacity, float* pBlend ) { assert(0); }
private:
void DrawWireframeModel( Vector const** pPositions );
void ComputePoint( float s, float t, Vector& pt, Vector& normal, float& opacity );
void ComputeShieldPoints( Vector* pt, Vector* normal, float* opacity );
void RippleShieldPoints( Vector* pt, float* opacity );
void DrawShieldPoints(Vector* pt, Vector* normal, float* opacity);
void DrawShieldDecals(Vector* pt, bool hitDecals );
void SetCurrentDecal( int idx );
int Width() const;
int Height() const;
protected:
// Used to fade out the shield
float m_FadeValue;
// Used to make the shield more or less curvy
float m_CurveValue;
private:
// no copy constructor
C_Shield( const C_Shield& );
// Data needs to ripple the shield control points
struct Ripple_t
{
float m_RippleU;
float m_RippleV;
float m_Amplitude;
float m_Radius;
float m_StartTime;
Vector m_Direction;
};
struct Decal_t
{
float m_RippleU;
float m_RippleV;
float m_Radius;
float m_StartTime;
};
// Owner entity
int m_nOwningPlayerIndex;
// number of subdivisions
int m_SubdivisionCount;
float m_InvSubdivisionCount;
// Shield powerlevel
float m_flPowerLevel;
// Texture animation
float m_StartTime;
bool m_bCollisionsActive;
bool m_bIsEMPed;
// Used to do spline queries
CSplinePatch m_SplinePatch;
// List of all ripples + decals
int m_CurrentDecal;
CUtlVector< Ripple_t > m_Ripples;
CUtlVector< Decal_t > m_Decals;
// All the various materials we use
CMaterialReference m_pWireframe;
CMaterialReference m_pShield;
CMaterialReference m_pHitDecal;
CMaterialReference m_pPassDecal;
CMaterialReference m_pPassDecal2;
// A little state used only during rendering, but I didn't want
// to pass these as arguments to a bunch of functions
bool m_ShieldOwnedByLocalPlayer;
Vector m_ViewDir;
// List of all active shields
static CUtlVector< C_Shield* > s_Shields;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline int C_Shield::Width() const
{
return m_SplinePatch.Width();
}
inline int C_Shield::Height() const
{
return m_SplinePatch.Height();
}
inline bool C_Shield::IsEMPed() const
{
return m_bIsEMPed;
}
inline void C_Shield::SetEMPed( bool bIsEmped )
{
m_bIsEMPed = bIsEmped;
}
//-----------------------------------------------------------------------------
// Class factory methods to create the various versions of the shield
//-----------------------------------------------------------------------------
C_Shield* CreateMobileShield( C_BaseEntity *owner, float flFrontDistance = 0 );
#endif // C_SHIELD_H
+350
View File
@@ -0,0 +1,350 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's sheild entity
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "C_Shield.h"
#include "tf_shieldshared.h"
#include "c_basetfplayer.h"
enum
{
NUM_SUBDIVISIONS = 21,
};
#define EMP_WAVE_AMPLITUDE 6.0f
#define EMP_GROW_WIDTH_DELAY 0.2f
#define EMP_GROW_TIME 0.6f
#define EMP_GROW_ATTEN 0.5f
#define EMP_MIN_WIDTH 5.0f
//-----------------------------------------------------------------------------
// Flat version of the shield
//-----------------------------------------------------------------------------
class C_ShieldFlat : public C_Shield
{
public:
DECLARE_CLASS( C_ShieldFlat, C_Shield );
DECLARE_CLIENTCLASS();
C_ShieldFlat();
~C_ShieldFlat();
virtual void GetBounds( Vector& mins, Vector& maxs );
virtual void AddEntity( );
virtual void SetDormant( bool bDormant );
// Return true if the panel is active
virtual bool IsPanelActive( int x, int y );
// Gets at the control point data; who knows how it was made?
virtual void GetShieldData( Vector const** ppVerts, float* pOpacity, float* pBlend );
virtual const Vector& GetPoint( int x, int y );
// Draws the model
virtual int DrawModel( int flags );
public:
// networked data
unsigned char m_ShieldState;
float m_Width;
float m_Height;
float m_DeathFade;
float m_EMPFade;
private:
void ShieldMoved( void );
private:
C_ShieldFlat( const C_ShieldFlat& );
void ComputeEMPFade();
void ComputeDeathFade();
void ComputeSize( float& w, float& h );
void PreRender( );
Vector m_pPositions[4];
Vector m_Forward;
float m_EnterPVSTime;
QAngle m_LastAngles;
Vector m_LastPosition;
Vector m_Pos[4];
};
//-----------------------------------------------------------------------------
// Data table
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT(C_ShieldFlat, DT_Shield_Flat, CShieldFlat)
RecvPropInt( RECVINFO(m_ShieldState) ),
RecvPropFloat( RECVINFO(m_Width) ),
RecvPropFloat( RECVINFO(m_Height) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
C_ShieldFlat::C_ShieldFlat()
{
m_DeathFade = 1.0f;
m_EMPFade = 1.0f;
InitShield( 2, 2, 6 );
}
C_ShieldFlat::~C_ShieldFlat()
{
}
//-----------------------------------------------------------------------------
// Leaving/entering the PVS on the server.
//-----------------------------------------------------------------------------
void C_ShieldFlat::SetDormant( bool bDormant )
{
if (!bDormant)
{
if (m_ShieldState & SHIELD_FLAT_EMP)
{
m_EMPFade = 0.0f;
}
else
{
m_EMPFade = 1.0f;
}
m_EnterPVSTime = 0.0f;
if (m_ShieldState & SHIELD_FLAT_INACTIVE)
{
m_DeathFade = 0.0f;
}
else
{
m_EnterPVSTime = gpGlobals->curtime;
m_DeathFade = 1.0f;
}
}
BaseClass::SetDormant(bDormant);
}
//-----------------------------------------------------------------------------
// Figures the EMP fade factor
//-----------------------------------------------------------------------------
void C_ShieldFlat::ComputeEMPFade()
{
if (m_ShieldState & SHIELD_FLAT_EMP)
{
// Decay fade if we've been EMPed or if we're inactive
if (m_EMPFade > 0.0f)
{
m_EMPFade -= gpGlobals->frametime / SHIELD_EMP_FADE_TIME;
if (m_EMPFade < 0.0f)
{
m_EMPFade = 0.0f;
}
else
{
Vector dir;
// Futz with the control points if we've been EMPed
for (int i = 0; i < 4; ++i)
{
float dist = -EMP_WAVE_AMPLITUDE * sin( i * M_PI * 0.5f + gpGlobals->curtime * M_PI / SHIELD_EMP_WOBBLE_TIME );
VectorMA( m_pPositions[i], dist, m_Forward, m_pPositions[i] );
}
}
}
}
else
{
// Fade back in, no longer EMPed
if (m_EMPFade < 1.0f)
{
m_EMPFade += gpGlobals->frametime / SHIELD_EMP_FADE_TIME;
if (m_EMPFade >= 1.0f)
{
m_EMPFade = 1.0f;
}
}
}
}
//-----------------------------------------------------------------------------
// Figures the networked fade factor
//-----------------------------------------------------------------------------
void C_ShieldFlat::ComputeDeathFade()
{
if (m_ShieldState & SHIELD_FLAT_INACTIVE)
{
// Fade out when we become inactive
if (m_DeathFade > 0.0f)
{
m_DeathFade -= gpGlobals->frametime / SHIELD_FLAT_SHUTDOWN_TIME;
if (m_DeathFade < 0.0f)
{
m_DeathFade = 0.0f;
}
}
}
else
{
// Active? We should be visible
m_DeathFade = 1.0f;
}
}
//-----------------------------------------------------------------------------
// A little pre-render processing
//-----------------------------------------------------------------------------
void C_ShieldFlat::ComputeSize( float& w, float& h )
{
w = m_Width;
h = m_Height;
float dt = gpGlobals->curtime - m_EnterPVSTime;
if (dt > EMP_GROW_TIME)
{
return;
}
if (dt < 0)
dt = 0.0f;
// Attenuate it up
w *= 1.0f - pow ( EMP_GROW_ATTEN, 10 * (dt / EMP_GROW_TIME ));
if (w < EMP_MIN_WIDTH)
w = EMP_MIN_WIDTH;
}
//-----------------------------------------------------------------------------
// A little pre-render processing
//-----------------------------------------------------------------------------
void C_ShieldFlat::PreRender( )
{
// Compute the shield positions...
Vector right, up;
AngleVectors( GetRenderAngles(), &m_Forward, &right, &up );
float w, h;
ComputeSize( w, h );
VectorMA( GetRenderOrigin(), -w * 0.5, right, m_pPositions[0] );
VectorMA( m_pPositions[0], -h * 0.5, up, m_pPositions[0] );
VectorMA( m_pPositions[0], w, right, m_pPositions[1] );
VectorMA( m_pPositions[0], h, up, m_pPositions[2] );
VectorMA( m_pPositions[2], w, right, m_pPositions[3] );
ComputeEMPFade();
ComputeDeathFade();
m_FadeValue = m_DeathFade * m_EMPFade;
}
void C_ShieldFlat::AddEntity( )
{
BaseClass::AddEntity( );
PreRender();
}
//-----------------------------------------------------------------------------
// Bounds computation
//-----------------------------------------------------------------------------
void C_ShieldFlat::GetBounds( Vector& mins, Vector& maxs )
{
mins.Init( -1.0/16.0f, -m_Width * 0.5f, -m_Height * 0.5f );
maxs.Init( 1.0/16.0f, m_Width * 0.5f, m_Height * 0.5f );
}
//-----------------------------------------------------------------------------
// Return true if the panel is active
//-----------------------------------------------------------------------------
bool C_ShieldFlat::IsPanelActive( int x, int y )
{
return true;
}
//-----------------------------------------------------------------------------
// Gets at the control point data; who knows how it was made?
//-----------------------------------------------------------------------------
void C_ShieldFlat::GetShieldData( Vector const** ppVerts, float* pOpacity, float* pBlend )
{
for ( int i = 0; i < 4; ++i )
{
ppVerts[i] = &m_pPositions[i];
pOpacity[i] = 32.0f;
pBlend[i] = 0.0f;
}
}
//-----------------------------------------------------------------------------
// Shield points
//-----------------------------------------------------------------------------
const Vector& C_ShieldFlat::GetPoint( int x, int y )
{
if ((m_LastAngles != GetAbsAngles()) || (m_LastPosition != GetAbsOrigin() ))
{
ShieldMoved();
}
int i = (x >= 1);
i += (y >= 1) * 2;
return m_Pos[i];
}
//-----------------------------------------------------------------------------
// Purpose: Computes the shield bounding box
//-----------------------------------------------------------------------------
void C_ShieldFlat::ShieldMoved( void )
{
Vector forward, right, up;
AngleVectors( GetAbsAngles(), &forward, &right, &up );
VectorMA( GetAbsOrigin(), -m_Width * 0.5, right, m_Pos[0] );
VectorMA( m_Pos[0], -m_Height * 0.5, up, m_Pos[0] );
VectorMA( m_Pos[0], m_Width, right, m_Pos[1] );
VectorMA( m_Pos[0], m_Height, up, m_Pos[2] );
VectorMA( m_Pos[2], m_Width, right, m_Pos[3] );
m_LastAngles = GetAbsAngles();
m_LastPosition = GetAbsOrigin();
}
//-----------------------------------------------------------------------------
// Suppress rendering if the player owns it
//-----------------------------------------------------------------------------
int C_ShieldFlat::DrawModel( int flags )
{
if ( !m_bReadyToDraw )
return 0;
// Don't draw it if the owner is the local player
// if ( m_OwnerEntity == C_BasePlayer::GetLocalPlayer()->index )
// return 0;
return BaseClass::DrawModel( flags );
}
+274
View File
@@ -0,0 +1,274 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's sheild entity
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "C_Shield.h"
#include "tf_shieldshared.h"
enum
{
NUM_SUBDIVISIONS = 21,
};
#define EMP_WAVE_AMPLITUDE 8.0f
//-----------------------------------------------------------------------------
// Mobile version of the shield
//-----------------------------------------------------------------------------
class C_ShieldMobile;
class C_ShieldMobileActiveVertList : public IActiveVertList
{
public:
void Init( C_ShieldMobile *pShield, unsigned char *pVertList );
// IActiveVertList overrides.
public:
virtual int GetActiveVertState( int iVert );
virtual void SetActiveVertState( int iVert, int bOn );
private:
C_ShieldMobile *m_pShield;
unsigned char *m_pVertsActive;
};
class C_ShieldMobile : public C_Shield
{
DECLARE_CLASS( C_ShieldMobile, C_Shield );
public:
DECLARE_CLIENTCLASS();
C_ShieldMobile();
~C_ShieldMobile();
void OnDataChanged( DataUpdateType_t updateType );
virtual void GetBounds( Vector& mins, Vector& maxs );
virtual void AddEntity( );
// Return true if the panel is active
virtual bool IsPanelActive( int x, int y );
// Gets at the control point data; who knows how it was made?
virtual void GetShieldData( Vector const** ppVerts, float* pOpacity, float* pBlend );
virtual const Vector& GetPoint( int x, int y ) { return m_ShieldEffect.GetPoint( x, y ); }
virtual void SetThetaPhi( float flTheta, float flPhi ) { m_ShieldEffect.SetThetaPhi(flTheta,flPhi); }
public:
// networked data
unsigned char m_pVertsActive[SHIELD_VERTEX_BYTES];
unsigned char m_ShieldState;
private:
C_ShieldMobile( const C_ShieldMobile& );
// Is a particular panel an edge?
bool IsVertexValid( float s, float t ) const;
void PreRender( );
private:
CShieldEffect m_ShieldEffect;
C_ShieldMobileActiveVertList m_VertList;
float m_flTheta;
float m_flPhi;
};
//-----------------------------------------------------------------------------
// C_ShieldMobileActiveVertList functions
//-----------------------------------------------------------------------------
void C_ShieldMobileActiveVertList::Init( C_ShieldMobile *pShield, unsigned char *pVertList )
{
m_pShield = pShield;
m_pVertsActive = pVertList;
}
int C_ShieldMobileActiveVertList::GetActiveVertState( int iVert )
{
return m_pVertsActive[iVert>>3] & (1 << (iVert & 7));
}
void C_ShieldMobileActiveVertList::SetActiveVertState( int iVert, int bOn )
{
if ( bOn )
m_pVertsActive[iVert>>3] |= (1 << (iVert & 7));
else
m_pVertsActive[iVert>>3] &= ~(1 << (iVert & 7));
}
//-----------------------------------------------------------------------------
// Data table
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT(C_ShieldMobile, DT_Shield_Mobile, CShieldMobile)
RecvPropInt( RECVINFO(m_ShieldState) ),
RecvPropArray(
RecvPropInt( RECVINFO(m_pVertsActive[0])),
m_pVertsActive
),
RecvPropFloat( RECVINFO(m_flTheta) ),
RecvPropFloat( RECVINFO(m_flPhi) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Various raycasting routines
//-----------------------------------------------------------------------------
void ShieldTraceLine(const Vector &vecStart, const Vector &vecEnd,
unsigned int mask, int collisionGroup, trace_t *ptr)
{
UTIL_TraceLine(vecStart, vecEnd, mask, NULL, collisionGroup, ptr );
}
void ShieldTraceHull(const Vector &vecStart, const Vector &vecEnd,
const Vector &hullMin, const Vector &hullMax,
unsigned int mask, int collisionGroup, trace_t *ptr)
{
CTraceFilterWorldOnly traceFilter;
enginetrace->TraceHull( vecStart, vecEnd, hullMin, hullMax, mask, &traceFilter, ptr );
}
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
C_ShieldMobile::C_ShieldMobile() : m_ShieldEffect(ShieldTraceLine, ShieldTraceHull)
{
m_VertList.Init( this, m_pVertsActive );
m_ShieldEffect.SetActiveVertexList( &m_VertList );
m_ShieldEffect.Spawn(vec3_origin, vec3_angle);
InitShield( SHIELD_NUM_HORIZONTAL_POINTS, SHIELD_NUM_VERTICAL_POINTS, NUM_SUBDIVISIONS );
}
C_ShieldMobile::~C_ShieldMobile()
{
}
//-----------------------------------------------------------------------------
// Get this after the data changes
//-----------------------------------------------------------------------------
void C_ShieldMobile::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
m_ShieldEffect.SetCurrentPosition( GetAbsOrigin() );
m_ShieldEffect.SetCurrentAngles( GetAbsAngles() );
m_ShieldEffect.SetThetaPhi( m_flTheta, m_flPhi );
// No need to simulate, just compute active panels from network data
m_ShieldEffect.ComputeControlPoints();
m_ShieldEffect.ComputePanelActivity();
}
//-----------------------------------------------------------------------------
// A little pre-render processing
//-----------------------------------------------------------------------------
void C_ShieldMobile::PreRender( )
{
if (m_ShieldState & SHIELD_MOBILE_EMP)
{
// Decay fade if we've been EMPed or if we're inactive
if (m_FadeValue > 0.0f)
{
m_FadeValue -= gpGlobals->frametime / SHIELD_EMP_FADE_TIME;
if (m_FadeValue < 0.0f)
{
m_FadeValue = 0.0f;
// Reset the shield to un-wobbled state
m_ShieldEffect.ComputeControlPoints();
}
else
{
Vector dir;
AngleVectors( m_ShieldEffect.GetCurrentAngles(), & dir );
// Futz with the control points if we've been EMPed
for (int i = 0; i < SHIELD_NUM_CONTROL_POINTS; ++i)
{
// Get the direction for the point
float factor = -EMP_WAVE_AMPLITUDE * sin( i * M_PI * 0.5f + gpGlobals->curtime * M_PI / SHIELD_EMP_WOBBLE_TIME );
m_ShieldEffect.GetPoint(i) += dir * factor;
}
}
}
}
else
{
// Fade back in, no longer EMPed
if (m_FadeValue < 1.0f)
{
m_FadeValue += gpGlobals->frametime / SHIELD_EMP_FADE_TIME;
if (m_FadeValue >= 1.0f)
{
m_FadeValue = 1.0f;
}
}
}
}
void C_ShieldMobile::AddEntity( )
{
BaseClass::AddEntity( );
PreRender();
}
//-----------------------------------------------------------------------------
// Bounds computation
//-----------------------------------------------------------------------------
void C_ShieldMobile::GetBounds( Vector& mins, Vector& maxs )
{
m_ShieldEffect.ComputeBounds( mins, maxs );
}
//-----------------------------------------------------------------------------
// Return true if the panel is active
//-----------------------------------------------------------------------------
bool C_ShieldMobile::IsPanelActive( int x, int y )
{
return m_ShieldEffect.IsPanelActive(x, y);
}
//-----------------------------------------------------------------------------
// Gets at the control point data; who knows how it was made?
//-----------------------------------------------------------------------------
void C_ShieldMobile::GetShieldData( Vector const** ppVerts, float* pOpacity, float* pBlend )
{
for ( int i = 0; i < SHIELD_NUM_CONTROL_POINTS; ++i )
{
ppVerts[i] = &m_ShieldEffect.GetControlPoint(i);
if ( m_pVertsActive[i >> 3] & (1 << (i & 0x7)) )
{
pOpacity[i] = m_ShieldEffect.ComputeOpacity( *ppVerts[i], GetAbsOrigin() );
pBlend[i] = 1.0f;
}
else
{
pOpacity[i] = 192.0f;
pBlend[i] = 0.0f;
}
}
}

Some files were not shown because too many files have changed in this diff Show More