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
+120
View File
@@ -0,0 +1,120 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
// c_bot_npc.cpp
#include "cbase.h"
#include "NextBot/C_NextBot.h"
#include "c_bot_npc.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#undef NextBot
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_BotNPC, DT_BotNPC, CBotNPC )
RecvPropEHandle( RECVINFO( m_laserTarget ) ),
RecvPropBool( RECVINFO( m_isNuking ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_BotNPC::C_BotNPC()
{
}
//-----------------------------------------------------------------------------
C_BotNPC::~C_BotNPC()
{
if ( m_laserBeamEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_laserBeamEffect );
m_laserBeamEffect = NULL;
}
if ( m_nukeEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_nukeEffect );
m_nukeEffect = NULL;
}
}
//-----------------------------------------------------------------------------
void C_BotNPC::Spawn( void )
{
BaseClass::Spawn();
m_vecViewOffset = Vector( 0, 0, 180.0f );
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//-----------------------------------------------------------------------------
void C_BotNPC::ClientThink( void )
{
if ( m_laserTarget )
{
if ( !m_laserBeamEffect )
{
m_laserBeamEffect = ParticleProp()->Create( "laser_sight_beam", PATTACH_POINT_FOLLOW, LookupAttachment( "head" ) );
}
if ( m_laserBeamEffect )
{
m_laserBeamEffect->SetSortOrigin( m_laserBeamEffect->GetRenderOrigin() );
m_laserBeamEffect->SetControlPoint( 2, Vector( 0, 255, 0 ) );
m_laserBeamEffect->SetControlPoint( 1, m_laserTarget->WorldSpaceCenter() );
}
}
else
{
// shut off the laser
if ( m_laserBeamEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_laserBeamEffect );
m_laserBeamEffect = NULL;
}
}
if ( m_isNuking )
{
if ( !m_nukeEffect )
{
m_nukeEffect = ParticleProp()->Create( "charge_up", PATTACH_POINT_FOLLOW, LookupAttachment( "head" ) );
}
}
else
{
if ( m_nukeEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_nukeEffect );
m_nukeEffect = NULL;
}
}
}
//-----------------------------------------------------------------------------
// Return the origin for player observers tracking this target
Vector C_BotNPC::GetObserverCamOrigin( void )
{
return EyePosition();
}
//-----------------------------------------------------------------------------
void C_BotNPC::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
if ( event == 7001 )
{
EmitSound( "RobotBoss.Footstep" );
/*
ParticleProp()->Create( "halloween_boss_foot_impact", PATTACH_ABSORIGIN, 0 );
*/
}
}
+42
View File
@@ -0,0 +1,42 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_BOT_NPC_H
#define C_BOT_NPC_H
#include "c_ai_basenpc.h"
//--------------------------------------------------------------------------------------------------------
/**
* The client-side implementation of Bot NPC
*/
class C_BotNPC : public C_NextBotCombatCharacter
{
public:
DECLARE_CLASS( C_BotNPC, C_NextBotCombatCharacter );
DECLARE_CLIENTCLASS();
C_BotNPC();
virtual ~C_BotNPC();
public:
virtual void Spawn( void );
virtual bool IsNextBot() { return true; }
virtual Vector GetObserverCamOrigin( void ); // Return the origin for player observers tracking this target
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void ClientThink();
private:
C_BotNPC( const C_BotNPC & ); // not defined, not accessible
CNetworkHandle( C_BaseEntity, m_laserTarget );
HPARTICLEFFECT m_laserBeamEffect;
CNetworkVar( bool, m_isNuking );
HPARTICLEFFECT m_nukeEffect;
};
#endif // C_BOT_NPC_H
+115
View File
@@ -0,0 +1,115 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
// c_bot_npc_minion.cpp
#include "cbase.h"
#include "NextBot/C_NextBot.h"
#include "c_bot_npc_minion.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#undef NextBot
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_BotNPCMinion, DT_BotNPCMinion, CBotNPCMinion )
RecvPropEHandle( RECVINFO( m_stunTarget ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_BotNPCMinion::C_BotNPCMinion()
{
m_stunEffect = NULL;
m_stunBeamEffect = NULL;
m_scanEffect = NULL;
}
//-----------------------------------------------------------------------------
C_BotNPCMinion::~C_BotNPCMinion()
{
if ( m_stunEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_stunEffect );
m_stunEffect = NULL;
}
if ( m_stunBeamEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_stunBeamEffect );
m_stunBeamEffect = NULL;
}
if ( m_scanEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_scanEffect );
m_scanEffect = NULL;
}
}
//-----------------------------------------------------------------------------
void C_BotNPCMinion::Spawn( void )
{
BaseClass::Spawn();
SetNextClientThink( CLIENT_THINK_ALWAYS );
//m_scanEffect = ParticleProp()->Create( "minion_scan", PATTACH_ABSORIGIN_FOLLOW );
}
//-----------------------------------------------------------------------------
void C_BotNPCMinion::ClientThink( void )
{
if ( m_stunTarget )
{
if ( !m_stunEffect )
{
m_stunEffect = ParticleProp()->Create( "cart_flashinglight", PATTACH_ABSORIGIN_FOLLOW );
}
if ( !m_stunBeamEffect )
{
m_stunBeamEffect = ParticleProp()->Create( "laser_sight_beam", PATTACH_ABSORIGIN_FOLLOW );
}
if ( m_stunBeamEffect )
{
m_stunBeamEffect->SetSortOrigin( m_stunBeamEffect->GetRenderOrigin() );
m_stunBeamEffect->SetControlPoint( 2, Vector( 255, 0, 255 ) );
m_stunBeamEffect->SetControlPoint( 1, m_stunTarget->WorldSpaceCenter() );
}
}
else
{
// shut off the effect
if ( m_stunEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_stunEffect );
m_stunEffect = NULL;
}
if ( m_stunBeamEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_stunBeamEffect );
m_stunBeamEffect = NULL;
}
}
}
//-----------------------------------------------------------------------------
// Return the origin for player observers tracking this target
Vector C_BotNPCMinion::GetObserverCamOrigin( void )
{
return GetAbsOrigin();
}
//-----------------------------------------------------------------------------
void C_BotNPCMinion::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
}
+41
View File
@@ -0,0 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_BOT_NPC_MINION_H
#define C_BOT_NPC_MINION_H
#include "c_ai_basenpc.h"
//--------------------------------------------------------------------------------------------------------
/**
* The client-side implementation of Bot NPC Minion
*/
class C_BotNPCMinion : public C_NextBotCombatCharacter
{
public:
DECLARE_CLASS( C_BotNPCMinion, C_NextBotCombatCharacter );
DECLARE_CLIENTCLASS();
C_BotNPCMinion();
virtual ~C_BotNPCMinion();
public:
virtual void Spawn( void );
virtual bool IsNextBot() { return true; }
virtual Vector GetObserverCamOrigin( void ); // Return the origin for player observers tracking this target
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void ClientThink();
private:
C_BotNPCMinion( const C_BotNPCMinion & ); // not defined, not accessible
CNetworkHandle( C_BaseEntity, m_stunTarget );
HPARTICLEFFECT m_stunEffect;
HPARTICLEFFECT m_stunBeamEffect;
HPARTICLEFFECT m_scanEffect;
};
#endif // C_BOT_NPC_MINION_H
@@ -0,0 +1,77 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#include "cbase.h"
#include "c_tf_bot_hint_engineer_nest.h"
IMPLEMENT_CLIENTCLASS_DT(C_TFBotHintEngineerNest, DT_TFBotHintEngineerNest, CTFBotHintEngineerNest)
RecvPropBool( RECVINFO(m_bHasActiveTeleporter) ),
END_RECV_TABLE()
//------------------------------------------------------------------------------
C_TFBotHintEngineerNest::C_TFBotHintEngineerNest( void )
{
m_bHasActiveTeleporter = false;
m_bHadActiveTeleporter = false;
m_pMvMActiveTeleporter = NULL;
}
C_TFBotHintEngineerNest::~C_TFBotHintEngineerNest()
{
}
void C_TFBotHintEngineerNest::UpdateOnRemove()
{
StopEffect();
BaseClass::UpdateOnRemove();
}
void C_TFBotHintEngineerNest::OnPreDataChanged( DataUpdateType_t type )
{
BaseClass::OnPreDataChanged( type );
m_bHadActiveTeleporter = m_bHasActiveTeleporter;
}
void C_TFBotHintEngineerNest::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
if ( m_bHadActiveTeleporter != m_bHasActiveTeleporter )
{
if ( m_bHasActiveTeleporter )
{
StartEffect();
}
else
{
StopEffect();
}
}
}
void C_TFBotHintEngineerNest::StartEffect()
{
if ( !m_pMvMActiveTeleporter )
{
m_pMvMActiveTeleporter = ParticleProp()->Create( "teleporter_mvm_bot_persist", PATTACH_ABSORIGIN );
}
}
void C_TFBotHintEngineerNest::StopEffect()
{
if ( m_pMvMActiveTeleporter )
{
ParticleProp()->StopEmission( m_pMvMActiveTeleporter );
m_pMvMActiveTeleporter = NULL;
}
}
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#ifndef TF_BOT_HINT_ENGINEER_NEST_H
#define TF_BOT_HINT_ENGINEER_NEST_H
#include "c_baseentity.h"
class C_TFBotHintEngineerNest : public C_BaseEntity
{
DECLARE_CLASS( C_TFBotHintEngineerNest, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_TFBotHintEngineerNest( void );
virtual ~C_TFBotHintEngineerNest();
virtual void UpdateOnRemove() OVERRIDE;
virtual void OnPreDataChanged( DataUpdateType_t type ) OVERRIDE;
virtual void OnDataChanged( DataUpdateType_t type ) OVERRIDE;
private:
bool m_bHadActiveTeleporter;
CNetworkVar( bool, m_bHasActiveTeleporter );
void StartEffect();
void StopEffect();
CNewParticleEffect *m_pMvMActiveTeleporter;
};
#endif // TF_BOT_HINT_ENGINEER_NEST_H
File diff suppressed because it is too large Load Diff
+311
View File
@@ -0,0 +1,311 @@
//========= 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 "particlemgr.h"
#include "particle_prototype.h"
#include "particle_util.h"
#include "c_basecombatcharacter.h"
#include "ihasbuildpoints.h"
#include <vgui/ILocalize.h>
class C_TFPlayer;
// Max Length of ID Strings
#define MAX_ID_STRING 256
extern mstudioevent_t *GetEventIndexForSequence( mstudioseqdesc_t &seqdesc );
DECLARE_AUTO_LIST( IBaseObjectAutoList );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BaseObject : public C_BaseCombatCharacter, public IHasBuildPoints, public ITargetIDProvidesHint, public IBaseObjectAutoList
{
DECLARE_CLASS( C_BaseObject, C_BaseCombatCharacter );
public:
DECLARE_CLIENTCLASS();
C_BaseObject();
~C_BaseObject( void );
virtual void Spawn( void );
virtual bool IsBaseObject( void ) const { return true; }
virtual bool IsAnUpgrade(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 ResetClientsideFrame( void );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
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 const char *GetTargetDescription( void ) const;
virtual const char *GetIDString( void );
virtual bool IsValidIDTarget( void );
virtual void GetTargetIDString( OUT_Z_BYTECAP(iMaxLenInBytes) wchar_t *sIDString, int iMaxLenInBytes, bool bSpectator );
virtual void GetTargetIDDataString( OUT_Z_BYTECAP(iMaxLenInBytes) wchar_t *sDataString, int iMaxLenInBytes );
virtual bool ShouldBeActive( void );
virtual void OnGoActive( void );
virtual void OnGoInactive( void );
virtual void UpdateOnRemove( void );
C_TFPlayer *GetBuilder( void ) { return m_hBuilder; }
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;
virtual void RecalculateIDString( void );
int GetType() const { return m_iObjectType; }
bool IsOwnedByLocalPlayer() const;
C_TFPlayer *GetOwner();
virtual void Simulate();
virtual int DrawModel( int flags );
float GetPercentageConstructed( void ) { return m_flPercentageConstructed; }
bool IsPlacing( void ) const { return m_bPlacing; }
bool IsBuilding( void ) const { return m_bBuilding; }
virtual bool IsUpgrading( void ) const { return false; }
bool IsCarried( void ) const { return m_bCarried; }
float GetReversesBuildingConstructionSpeed( void );
virtual void FinishedBuilding( void ) { return; }
virtual const char* GetStatusName() const;
// Object Previews
void HighlightBuildPoints( int flags );
bool HasSapper( void );
bool IsPlasmaDisabled( void );
virtual void OnStartDisabled( void );
virtual void OnEndDisabled( void );
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
virtual bool ShouldPlayersAvoid( void );
bool MustBeBuiltOnAttachmentPoint( void ) const;
virtual bool IsHostileUpgrade( void ) { return false; }
// For ordering in hud building status
virtual int GetDisplayPriority( void );
virtual const char *GetHudStatusIcon( void );
virtual BuildingHudAlert_t GetBuildingAlertLevel( void );
// Upgrading
virtual int GetUpgradeLevel( void ) { return m_iUpgradeLevel; }
int GetUpgradeMetal( void ) { return m_iUpgradeMetal; }
virtual int GetUpgradeMetalRequired( void ) { return m_iUpgradeMetalRequired; }
virtual void UpgradeLevelChanged() { return; }
int GetHighestUpgradeLevel( void ) { return m_iHighestUpgradeLevel; }
int GetObjectMode( void ) const { return m_iObjectMode; }
// Shadows
virtual ShadowType_t ShadowCastType( void ) OVERRIDE;
// Stealth
virtual float GetInvisibilityLevel( void );
virtual void SetInvisibilityLevel( float flValue );
bool IsEnteringOrExitingFullyInvisible( float flValue ) { return ( ( m_flInvisibilityPercent != 1.f && flValue == 1.f ) || ( m_flInvisibilityPercent == 1.f && flValue != 1.f ) ); }
private:
void StopAnimGeneratedSounds( void );
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.IsValid(); }
void AttachObjectToObject( CBaseEntity *pEntity, int iPoint, Vector &vecOrigin );
CBaseObject *GetParentObject( void );
CBaseEntity *GetParentEntity( void );
void SetBuildPointPassenger( int iPoint, int iPassenger );
// Build points
CUtlVector<BuildPoint_t> m_BuildPoints;
bool IsDisabled( void ) { return m_bDisabled || m_bCarried; }
// Shared placement
bool VerifyCorner( const Vector &vBottomCenter, float xOffset, float yOffset );
virtual bool IsPlacementPosValid( void );
virtual float GetNearbyObjectCheckRadius( void ) { return 30.0; }
virtual void OnPlacementStateChanged( bool bValidPlacement );
bool ServerValidPlacement( void ); // allow server to trump our placement state
bool WasLastPlacementPosValid( void ); // query if we're in a valid place, when we last tried to calculate it
// 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 CBaseObject *GetObjectOfTypeOnMe( int iObjectType );
virtual void RemoveAllObjects( void );
virtual int FindObjectOnBuildPoint( CBaseObject *pObject );
virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
bool IsMiniBuilding() { return m_bMiniBuilding; }
bool IsDisposableBuilding( void ) const { return m_bDisposableBuilding; }
// ITargetIDProvidesHint
public:
virtual void DisplayHintTo( C_BasePlayer *pPlayer );
virtual void GetGlowEffectColor( float *r, float *g, float *b );
bool IsMapPlaced( void ){ return m_bWasMapPlaced; }
protected:
virtual void UpdateDamageEffects( BuildingDamageLevel_t damageLevel ) {} // default is no effects
void UpdateDesiredBuildRotation( float flFrameTime );
bool CalculatePlacementPos( void );
protected:
BuildingDamageLevel_t CalculateDamageLevel( void );
char m_szIDString[ MAX_ID_STRING ];
BuildingDamageLevel_t m_damageLevel;
Vector m_vecBuildOrigin;
Vector m_vecBuildCenterOfMass;
// Upgrading
int m_iUpgradeLevel;
int m_iOldUpgradeLevel;
int m_iUpgradeMetal;
int m_iHighestUpgradeLevel;
int m_iUpgradeMetalRequired;
HPARTICLEFFECT m_hDamageEffects;
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_TFPlayer > m_hOldOwner;
CHandle< C_TFPlayer > 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_bWasPlacing;
bool m_bPlacing;
bool m_bDisabled;
bool m_bOldDisabled;
bool m_bCarried;
bool m_bCarryDeploy;
bool m_bOldCarryDeploy;
bool m_bMiniBuilding;
bool m_bDisposableBuilding;
float m_flPercentageConstructed;
EHANDLE m_hBuiltOnEntity;
int m_iObjectMode;
bool m_bPlasmaDisable;
CNetworkVector( m_vecBuildMaxs );
CNetworkVector( m_vecBuildMins );
CNetworkVar( int, m_iDesiredBuildRotations );
float m_flCurrentBuildRotation;
int m_iLastPlacementPosValid; // -1 - init, 0 - invalid, 1 - valid
CNetworkVar( bool, m_bServerOverridePlacement );
int m_nObjectOldSequence;
// used when calculating the placement position
Vector m_vecBuildForward;
float m_flBuildDistance;
// Stealth
float m_flInvisibilityPercent;
float m_flPrevInvisibilityPercent;
CNetworkVar( bool, m_bWasMapPlaced );
private:
C_BaseObject( const C_BaseObject & ); // not defined, not accessible
};
#endif // C_BASEOBJECT_H
+170
View File
@@ -0,0 +1,170 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Dove entity for the Meet the Medic tease.
//
//=============================================================================//
#include "cbase.h"
#include "tf_gamerules.h"
#include "c_baseanimating.h"
#define ENTITY_FLYING_BIRD_MODEL "models/props_forest/dove.mdl"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EntityFlyingBird : public CBaseAnimating
{
DECLARE_CLASS( C_EntityFlyingBird, CBaseAnimating );
public:
void InitFromServerData( float flyAngle, float flyAngleRate, float flAccelZ, float flSpeed, float flGlideTime );
virtual void Touch( CBaseEntity *pOther );
private:
virtual void ClientThink( void );
void UpdateFlyDirection( void );
private:
Vector m_flyForward;
float m_flyAngle;
float m_flyAngleRate;
float m_flyZ;
float m_accelZ;
float m_speed;
float m_timestamp;
CountdownTimer m_lifetimeTimer;
CountdownTimer m_glideTimer;
};
//-----------------------------------------------------------------------------
// Purpose: Server message that tells us to create a dove
//-----------------------------------------------------------------------------
void __MsgFunc_SpawnFlyingBird( bf_read &msg )
{
Vector vecPos;
msg.ReadBitVec3Coord( vecPos );
float flyAngle = msg.ReadFloat();
float flyAngleRate = msg.ReadFloat();
float flAccelZ = msg.ReadFloat();
float flSpeed = msg.ReadFloat();
float flGlideTime = msg.ReadFloat();
C_EntityFlyingBird *pBird = new C_EntityFlyingBird();
if ( !pBird )
return;
pBird->SetAbsOrigin( vecPos );
pBird->InitFromServerData( flyAngle, flyAngleRate, flAccelZ, flSpeed, flGlideTime );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlyingBird::UpdateFlyDirection( void )
{
Vector forward;
forward.x = cos( m_flyAngle );
forward.y = sin( m_flyAngle );
forward.z = m_flyZ;
forward.NormalizeInPlace();
SetAbsVelocity( forward * m_speed );
QAngle angles;
VectorAngles( forward, angles );
SetAbsAngles( angles );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlyingBird::InitFromServerData( float flyAngle, float flyAngleRate, float flAccelZ, float flSpeed, float flGlideTime )
{
if ( InitializeAsClientEntity( ENTITY_FLYING_BIRD_MODEL, RENDER_GROUP_OPAQUE_ENTITY ) == false )
{
Release();
return;
}
SetMoveType( MOVETYPE_FLY );
SetSolid( SOLID_BBOX );
SetCollisionGroup( COLLISION_GROUP_DEBRIS );
SetSize( -Vector(8,8,0), Vector(8,8,16) );
m_flyAngle = flyAngle;
m_flyAngleRate = flyAngleRate;
m_accelZ = flAccelZ;
m_flyZ = 0.0;
m_speed = flSpeed;
UpdateFlyDirection();
SetSequence( 0 );
SetPlaybackRate( 1.0f );
SetCycle( 0 );
ResetSequenceInfo();
// make sure the bird is removed
m_lifetimeTimer.Start( 10.0f );
m_glideTimer.Start( flGlideTime );
SetNextClientThink( CLIENT_THINK_ALWAYS );
m_timestamp = gpGlobals->curtime;
SetModelScale( 0.1f );
SetModelScale( 1.0f, 0.5f );
}
//-----------------------------------------------------------------------------
// Purpose: Fly away!
//-----------------------------------------------------------------------------
void C_EntityFlyingBird::ClientThink( void )
{
if ( m_lifetimeTimer.IsElapsed() )
{
Release();
return;
}
if ( m_glideTimer.HasStarted() && m_glideTimer.IsElapsed() )
{
SetSequence( 1 );
SetPlaybackRate( 1.0f );
SetCycle( 0 );
ResetSequenceInfo();
m_glideTimer.Invalidate();
}
StudioFrameAdvance();
PhysicsSimulate();
const float deltaT = gpGlobals->curtime - m_timestamp;
m_flyAngle += m_flyAngleRate * deltaT;
m_flyZ += m_accelZ * deltaT;
UpdateFlyDirection();
m_timestamp = gpGlobals->curtime;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlyingBird::Touch( CBaseEntity *pOther )
{
if ( !pOther || !pOther->IsWorld() )
return;
BaseClass::Touch( pOther );
// Die at next think. Not safe to remove ourselves during physics touch.
m_lifetimeTimer.Invalidate();
}
+93
View File
@@ -0,0 +1,93 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#include "cbase.h"
#include "c_entity_currencypack.h"
#include "c_tf_player.h"
IMPLEMENT_CLIENTCLASS_DT( C_CurrencyPack, DT_CurrencyPack, CCurrencyPack )
RecvPropBool( RECVINFO( m_bDistributed ) ),
END_RECV_TABLE()
C_CurrencyPack::C_CurrencyPack()
{
m_bDistributed = false;
m_pGlowEffect = NULL;
m_bShouldGlowForLocalPlayer = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_CurrencyPack::~C_CurrencyPack()
{
DestroyGlowEffect();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_CurrencyPack::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_CurrencyPack::ClientThink()
{
#ifdef STAGING_ONLY
int iSeeCashThroughWall = 0;
C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( pTFPlayer && pTFPlayer->IsAlive() )
{
CALL_ATTRIB_HOOK_INT_ON_OTHER( pTFPlayer, iSeeCashThroughWall, mvm_see_cash_through_wall );
}
bool bShouldGlowForLocalPlayer = iSeeCashThroughWall != 0;
if ( m_bShouldGlowForLocalPlayer != bShouldGlowForLocalPlayer )
{
m_bShouldGlowForLocalPlayer = bShouldGlowForLocalPlayer;
UpdateGlowEffect();
}
#endif // STAGING_ONLY
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_CurrencyPack::UpdateGlowEffect( void )
{
// destroy the existing effect
if ( m_pGlowEffect )
{
DestroyGlowEffect();
}
// create a new effect if we have a cart
if ( m_bShouldGlowForLocalPlayer )
{
Vector color = m_bDistributed ? Vector( 150, 0, 0 ) : Vector( 0, 150, 0 );
m_pGlowEffect = new CGlowObject( this, color, 1.0, true );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_CurrencyPack::DestroyGlowEffect( void )
{
if ( m_pGlowEffect )
{
delete m_pGlowEffect;
m_pGlowEffect = NULL;
}
}
+27
View File
@@ -0,0 +1,27 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_ENTITY_CURRENCYPACK_H
#define C_ENTITY_CURRENCYPACK_H
class C_CurrencyPack : public C_BaseAnimating
{
public:
DECLARE_CLASS( C_CurrencyPack, C_BaseAnimating );
DECLARE_CLIENTCLASS();
C_CurrencyPack();
~C_CurrencyPack();
virtual void OnDataChanged( DataUpdateType_t updateType ) OVERRIDE;
virtual void ClientThink();
private:
void UpdateGlowEffect( void );
void DestroyGlowEffect( void );
CGlowObject *m_pGlowEffect;
bool m_bShouldGlowForLocalPlayer;
bool m_bDistributed;
};
#endif // C_ENTITY_CURRENCYPACK_H
+18
View File
@@ -0,0 +1,18 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "tf_shareddefs.h"
#include "c_func_capture_zone.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_CaptureZone, DT_CaptureZone, CCaptureZone )
RecvPropInt( RECVINFO( m_bDisabled ) ),
END_RECV_TABLE()
IMPLEMENT_AUTO_LIST( ICaptureZoneAutoList );
+33
View File
@@ -0,0 +1,33 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_FUNC_CAPTURE_ZONE_H
#define C_FUNC_CAPTURE_ZONE_H
#ifdef _WIN32
#pragma once
#endif
class C_CaptureZone;
DECLARE_AUTO_LIST( ICaptureZoneAutoList );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_CaptureZone : public C_BaseEntity, public ICaptureZoneAutoList
{
DECLARE_CLASS( C_CaptureZone, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
bool IsDisabled( void ){ return m_bDisabled; }
private:
bool m_bDisabled;
};
#endif // C_FUNC_CAPTURE_ZONE_H
+73
View File
@@ -0,0 +1,73 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "tf_shareddefs.h"
#include "tf_gamerules.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_FuncForceField : public C_BaseEntity
{
DECLARE_CLASS( C_FuncForceField, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
virtual int DrawModel( int flags ) OVERRIDE;
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const OVERRIDE;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncForceField, DT_FuncForceField, CFuncForceField )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_FuncForceField::DrawModel( int flags )
{
// Don't draw for anyone during a team win
if ( TFGameRules()->State_Get() == GR_STATE_TEAM_WIN )
return 1;
return BaseClass::DrawModel( flags );
}
//-----------------------------------------------------------------------------
// Purpose: Enemy players collide with us, except during a team win
//-----------------------------------------------------------------------------
bool C_FuncForceField::ShouldCollide( int collisionGroup, int contentsMask ) const
{
// Force fields are off during a team win
if ( TFGameRules()->State_Get() == GR_STATE_TEAM_WIN )
return false;
if ( GetTeamNumber() == TEAM_UNASSIGNED )
return false;
if ( collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT )
{
switch ( GetTeamNumber() )
{
case TF_TEAM_BLUE:
if ( !( contentsMask & CONTENTS_BLUETEAM ) )
return false;
break;
case TF_TEAM_RED:
if ( !( contentsMask & CONTENTS_REDTEAM ) )
return false;
break;
}
return true;
}
return false;
}
+19
View File
@@ -0,0 +1,19 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// func_passtime_goal - based on func_capture_zone
#include "cbase.h"
#include "c_func_passtime_goal.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_FuncPasstimeGoal, DT_FuncPasstimeGoal, CFuncPasstimeGoal )
RecvPropBool( RECVINFO( m_bTriggerDisabled ) ),
RecvPropInt( RECVINFO( m_iGoalType ) ),
END_RECV_TABLE()
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// func_passtime_goal - based on func_capture_zone
#ifndef C_FUNC_PASSTIME_GOAL_H
#define C_FUNC_PASSTIME_GOAL_H
#ifdef _WIN32
#pragma once
#endif
#include "util_shared.h"
#include "c_baseentity.h"
//-----------------------------------------------------------------------------
class C_FuncPasstimeGoal : public C_BaseEntity, public TAutoList<C_FuncPasstimeGoal>
{
public:
DECLARE_CLASS( C_FuncPasstimeGoal, C_BaseEntity );
DECLARE_CLIENTCLASS();
bool BGoalTriggerDisabled() const { return m_bTriggerDisabled; }
int GetGoalType() const { return m_iGoalType; }
enum GoalType
{
TYPE_HOOP,
TYPE_ENDZONE,
TYPE_TOWER,
};
private:
CNetworkVar( bool, m_bTriggerDisabled );
CNetworkVar( int, m_iGoalType );
};
#endif // C_FUNC_PASSTIME_GOAL_H
+97
View File
@@ -0,0 +1,97 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "tf_shareddefs.h"
#include "tf_gamerules.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_FuncRespawnRoom : public C_BaseEntity
{
DECLARE_CLASS( C_FuncRespawnRoom, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncRespawnRoom, DT_FuncRespawnRoom, CFuncRespawnRoom )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_FuncRespawnRoomVisualizer : public C_BaseEntity
{
DECLARE_CLASS( C_FuncRespawnRoomVisualizer, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
virtual int DrawModel( int flags );
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncRespawnRoomVisualizer, DT_FuncRespawnRoomVisualizer, CFuncRespawnRoomVisualizer )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose: Don't draw for friendly players
//-----------------------------------------------------------------------------
int C_FuncRespawnRoomVisualizer::DrawModel( int flags )
{
// Don't draw for anyone in endround
if ( TFGameRules()->State_Get() == GR_STATE_TEAM_WIN )
{
return 1;
}
// Don't draw for teammates of the visualizer
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( pLocalPlayer && pLocalPlayer->GetTeamNumber() == GetTeamNumber() )
{
return 1;
}
return BaseClass::DrawModel( flags );
}
//-----------------------------------------------------------------------------
// Purpose: Enemy players collide with us, except in endround
//-----------------------------------------------------------------------------
bool C_FuncRespawnRoomVisualizer::ShouldCollide( int collisionGroup, int contentsMask ) const
{
// Respawn rooms are open in win state
if ( TFGameRules()->State_Get() == GR_STATE_TEAM_WIN )
return false;
if ( GetTeamNumber() == TEAM_UNASSIGNED )
return false;
if ( collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT )
{
switch( GetTeamNumber() )
{
case TF_TEAM_BLUE:
if ( !(contentsMask & CONTENTS_BLUETEAM) )
return false;
break;
case TF_TEAM_RED:
if ( !(contentsMask & CONTENTS_REDTEAM) )
return false;
break;
}
return true;
}
return false;
}
+82
View File
@@ -0,0 +1,82 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#include "cbase.h"
#include "c_monster_resource.h"
#include "tf_hud_boss_health.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void RecvProxy_UpdateBossHud( const CRecvProxyData *pData, void *pStruct, void *pOut );
IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_MonsterResource, DT_MonsterResource, CMonsterResource )
RecvPropInt( RECVINFO( m_iBossHealthPercentageByte ), 0, RecvProxy_UpdateBossHud ),
RecvPropInt( RECVINFO( m_iBossStunPercentageByte ), 0, RecvProxy_UpdateBossHud ),
RecvPropInt( RECVINFO( m_iSkillShotCompleteCount ) ),
RecvPropTime( RECVINFO( m_fSkillShotComboEndTime ) ),
RecvPropInt( RECVINFO( m_iBossState ), 0, RecvProxy_UpdateBossHud ),
END_RECV_TABLE()
C_MonsterResource *g_pMonsterResource = NULL;
//-----------------------------------------------------------------------------
// Update the HUD meter when the Boss' data changes
void RecvProxy_UpdateBossHud( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
int *out = (int *)pOut;
*out = pData->m_Value.m_Int;
CHudBossHealthMeter *meter = GET_HUDELEMENT( CHudBossHealthMeter );
if ( meter )
{
meter->Update();
}
}
//-----------------------------------------------------------------------------
C_MonsterResource::C_MonsterResource()
{
m_iBossHealthPercentageByte = 0;
m_iBossStunPercentageByte = 0;
m_iSkillShotCompleteCount = 0;
m_fSkillShotComboEndTime = 0;
m_iBossState = 0;
// do this here because entity is created via network messages from the server entity's creation
Assert( g_pMonsterResource == NULL );
g_pMonsterResource = this;
}
//-----------------------------------------------------------------------------
C_MonsterResource::~C_MonsterResource()
{
Assert( g_pMonsterResource == this );
g_pMonsterResource = NULL;
}
//-----------------------------------------------------------------------------
float C_MonsterResource::GetBossHealthPercentage( void )
{
return (float)m_iBossHealthPercentageByte / 255.0f;
}
//-----------------------------------------------------------------------------
float C_MonsterResource::GetBossStunPercentage( void )
{
return (float)m_iBossStunPercentageByte / 255.0f;
}
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_MONSTER_RESOURCE
#define C_MONSTER_RESOURCE
#ifdef _WIN32
#pragma once
#endif
class C_MonsterResource : public C_BaseEntity
{
DECLARE_CLASS( C_MonsterResource, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_MonsterResource();
virtual ~C_MonsterResource();
float GetBossHealthPercentage( void );
float GetBossStunPercentage( void );
int GetSkillShotCompleteCount( void ){ return m_iSkillShotCompleteCount; }
float GetSkillShotComboEndTime( void ){ return m_fSkillShotComboEndTime; }
int GetBossState() const { return m_iBossState; }
private:
int m_iBossHealthPercentageByte;
int m_iBossStunPercentageByte;
int m_iSkillShotCompleteCount; // the number of consecutive skill shots that have been completed. 0 = don't show combo HUD
float m_fSkillShotComboEndTime; // the time when the current skill shot combo window closes
int m_iBossState;
};
extern C_MonsterResource *g_pMonsterResource;
#endif // C_MONSTER_RESOURCE
+393
View File
@@ -0,0 +1,393 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CObjectSentrygun
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseobject.h"
#include "c_tf_player.h"
#include "vgui/ILocalize.h"
#include "c_obj_dispenser.h"
// NVNT haptics system interface
#include "c_tf_haptics.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: RecvProxy that converts the Team's player UtlVector to entindexes
//-----------------------------------------------------------------------------
void RecvProxy_HealingList( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_ObjectDispenser *pDispenser = (C_ObjectDispenser*)pStruct;
CBaseHandle *pHandle = (CBaseHandle*)(&(pDispenser->m_hHealingTargets[pData->m_iElement]));
RecvProxy_IntToEHandle( pData, pStruct, pHandle );
// update the heal beams
pDispenser->m_bUpdateHealingTargets = true;
}
void RecvProxyArrayLength_HealingArray( void *pStruct, int objectID, int currentArrayLength )
{
C_ObjectDispenser *pDispenser = (C_ObjectDispenser*)pStruct;
if ( pDispenser->m_hHealingTargets.Size() != currentArrayLength )
pDispenser->m_hHealingTargets.SetSize( currentArrayLength );
// update the heal beams
pDispenser->m_bUpdateHealingTargets = true;
}
//-----------------------------------------------------------------------------
// Purpose: Dispenser object
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT(C_ObjectDispenser, DT_ObjectDispenser, CObjectDispenser)
RecvPropInt( RECVINFO( m_iState ) ),
RecvPropInt( RECVINFO( m_iAmmoMetal ) ),
RecvPropInt( RECVINFO( m_iMiniBombCounter ) ),
RecvPropArray2(
RecvProxyArrayLength_HealingArray,
RecvPropInt( "healing_array_element", 0, SIZEOF_IGNORE, 0, RecvProxy_HealingList ),
MAX_PLAYERS,
0,
"healing_array"
)
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectDispenser::C_ObjectDispenser()
{
m_bUpdateHealingTargets = false;
m_bPlayingSound = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectDispenser::~C_ObjectDispenser()
{
StopSound( "Building_Dispenser.Heal" );
// NVNT see if local player is in the list of targets
// temp. fix if dispener is destroyed will stop all healers.
if(m_bPlayingSound)
{
if(tfHaptics.healingDispenserCount>0) {
tfHaptics.healingDispenserCount --;
if(tfHaptics.healingDispenserCount==0 && !tfHaptics.wasBeingHealedMedic)
tfHaptics.isBeingHealed = false;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_ObjectDispenser::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
#ifdef STAGING_ONLY
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
#endif // STAGING_ONLY
if ( m_bUpdateHealingTargets )
{
UpdateEffects();
m_bUpdateHealingTargets = false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectDispenser::ClientThink()
{
BaseClass::ClientThink();
#ifdef STAGING_ONLY
C_TFPlayer *pTFOwner = GetOwner();
if ( pTFOwner && pTFOwner->m_Shared.IsEnteringOrExitingFullyInvisible() )
{
UpdateEffects();
}
#endif // STAGING_ONLY
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectDispenser::SetInvisibilityLevel( float flValue )
{
if ( IsEnteringOrExitingFullyInvisible( flValue ) )
{
UpdateEffects();
}
BaseClass::SetInvisibilityLevel( flValue );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectDispenser::UpdateEffects( void )
{
C_TFPlayer *pOwner = GetOwner();
if ( GetInvisibilityLevel() == 1.f || ( pOwner && pOwner->m_Shared.IsFullyInvisible() ) )
{
StopEffects( true );
return;
}
StopEffects();
// Now add any new targets
for ( int i = 0; i < m_hHealingTargets.Count(); i++ )
{
C_BaseEntity *pTarget = m_hHealingTargets[i].Get();
// Loops through the healing targets, and make sure we have an effect for each of them
if ( pTarget )
{
// don't want to show this effect for stealthed spies
C_TFPlayer *pPlayer = dynamic_cast< C_TFPlayer * >( pTarget );
if ( pPlayer && ( pPlayer->m_Shared.IsStealthed() || pPlayer->m_Shared.InCond( TF_COND_STEALTHED_BLINK ) ) )
continue;
bool bHaveEffect = false;
for ( int targets = 0; targets < m_hHealingTargetEffects.Count(); targets++ )
{
if ( m_hHealingTargetEffects[targets].pTarget == pTarget )
{
bHaveEffect = true;
break;
}
}
if ( bHaveEffect )
continue;
// NVNT if the dispenser has started to heal the local player
// notify the haptics system
if(pTarget==C_BasePlayer::GetLocalPlayer())
{
tfHaptics.healingDispenserCount++;
if(!tfHaptics.wasBeingHealedMedic) {
tfHaptics.isBeingHealed = true;
}
}
const char *pszEffectName;
if ( GetTeamNumber() == TF_TEAM_RED )
{
pszEffectName = "dispenser_heal_red";
}
else
{
pszEffectName = "dispenser_heal_blue";
}
CNewParticleEffect *pEffect;
// if we don't have a model, attach at the origin, otherwise use attachment 'heal_origin'
if ( FBitSet( GetObjectFlags(), OF_DOESNT_HAVE_A_MODEL ) )
{
// offset the origin to player's chest
if ( FBitSet( GetObjectFlags(), OF_PLAYER_DESTRUCTION ) )
{
pEffect = ParticleProp()->Create( pszEffectName, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector( 0, 0, 50 ) );
}
else
{
pEffect = ParticleProp()->Create( pszEffectName, PATTACH_ABSORIGIN_FOLLOW );
}
}
else
{
pEffect = ParticleProp()->Create( pszEffectName, PATTACH_POINT_FOLLOW, "heal_origin" );
}
ParticleProp()->AddControlPoint( pEffect, 1, pTarget, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector(0,0,50) );
int iIndex = m_hHealingTargetEffects.AddToTail();
m_hHealingTargetEffects[iIndex].pTarget = pTarget;
m_hHealingTargetEffects[iIndex].pEffect = pEffect;
// Start the sound over again every time we start a new beam
StopSound( "Building_Dispenser.Heal" );
CLocalPlayerFilter filter;
EmitSound( filter, entindex(), "Building_Dispenser.Heal" );
m_bPlayingSound = true;
}
}
// Stop the sound if we're not healing anyone
if ( m_bPlayingSound && m_hHealingTargets.Count() == 0 )
{
m_bPlayingSound = false;
// stop the sound
StopSound( "Building_Dispenser.Heal" );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectDispenser::StopEffects( bool bRemoveAll /* = false */ )
{
// Find all the targets we've stopped healing
bool bStillHealing[MAX_DISPENSER_HEALING_TARGETS] = { 0 };
for ( int i = 0; i < m_hHealingTargetEffects.Count(); i++ )
{
bStillHealing[i] = false;
// Are we still healing this target?
if ( !bRemoveAll )
{
for ( int target = 0; target < m_hHealingTargets.Count(); target++ )
{
if ( m_hHealingTargets[target] && m_hHealingTargets[target] == m_hHealingTargetEffects[i].pTarget )
{
bStillHealing[i] = true;
break;
}
}
}
}
// Now remove all the dead effects
for ( int i = m_hHealingTargetEffects.Count()-1; i >= 0; i-- )
{
if ( !bStillHealing[i] )
{
// NVNT if the healing target of this dispenser is the local player.
// inform the haptics system interface we are no longer healing.
if(m_hHealingTargetEffects[i].pTarget==C_BasePlayer::GetLocalPlayer())
{
if(tfHaptics.healingDispenserCount>0) {
tfHaptics.healingDispenserCount --;
if(tfHaptics.healingDispenserCount==0 && !tfHaptics.wasBeingHealedMedic)
tfHaptics.isBeingHealed = false;
}
}
ParticleProp()->StopEmission( m_hHealingTargetEffects[i].pEffect );
m_hHealingTargetEffects.Remove(i);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Damage level has changed, update our effects
//-----------------------------------------------------------------------------
void C_ObjectDispenser::UpdateDamageEffects( BuildingDamageLevel_t damageLevel )
{
if ( m_hDamageEffects )
{
m_hDamageEffects->StopEmission( false, false );
m_hDamageEffects = NULL;
}
const char *pszEffect = "";
switch( damageLevel )
{
case BUILDING_DAMAGE_LEVEL_LIGHT:
pszEffect = "dispenserdamage_1";
break;
case BUILDING_DAMAGE_LEVEL_MEDIUM:
pszEffect = "dispenserdamage_2";
break;
case BUILDING_DAMAGE_LEVEL_HEAVY:
pszEffect = "dispenserdamage_3";
break;
case BUILDING_DAMAGE_LEVEL_CRITICAL:
pszEffect = "dispenserdamage_4";
break;
default:
break;
}
if ( Q_strlen(pszEffect) > 0 )
{
m_hDamageEffects = ParticleProp()->Create( pszEffect, PATTACH_ABSORIGIN );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int C_ObjectDispenser::GetMaxMetal( void )
{
return DISPENSER_MAX_METAL_AMMO;
}
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
DECLARE_VGUI_SCREEN_FACTORY( CDispenserControlPanel, "screen_obj_dispenser_blue" );
DECLARE_VGUI_SCREEN_FACTORY( CDispenserControlPanel_Red, "screen_obj_dispenser_red" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CDispenserControlPanel::CDispenserControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CDispenserControlPanel" )
{
m_pAmmoProgress = new RotatingProgressBar( this, "MeterArrow" );
}
//-----------------------------------------------------------------------------
// Deactivates buttons we can't afford
//-----------------------------------------------------------------------------
void CDispenserControlPanel::OnTickActive( C_BaseObject *pObj, C_TFPlayer *pLocalPlayer )
{
BaseClass::OnTickActive( pObj, pLocalPlayer );
Assert( dynamic_cast< C_ObjectDispenser* >( pObj ) );
m_hDispenser = static_cast< C_ObjectDispenser* >( pObj );
float flProgress = m_hDispenser ? m_hDispenser->GetMetalAmmoCount() / (float)m_hDispenser->GetMaxMetal() : 0.f;
m_pAmmoProgress->SetProgress( flProgress );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CDispenserControlPanel::IsVisible( void )
{
if ( m_hDispenser )
{
#ifdef STAGING_ONLY
if ( m_hDispenser->IsMiniBuilding() )
return false;
#endif // STAGING_ONLY
if ( m_hDispenser->GetInvisibilityLevel() == 1.f )
return false;
}
return BaseClass::IsVisible();
}
IMPLEMENT_CLIENTCLASS_DT(C_ObjectCartDispenser, DT_ObjectCartDispenser, CObjectCartDispenser)
END_RECV_TABLE()
+95
View File
@@ -0,0 +1,95 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_OBJ_DISPENSER_H
#define C_OBJ_DISPENSER_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseobject.h"
#include "ObjectControlPanel.h"
#include "vgui_controls/RotatingProgressBar.h"
class C_ObjectDispenser : public C_BaseObject
{
DECLARE_CLASS( C_ObjectDispenser, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectDispenser();
~C_ObjectDispenser();
int GetMetalAmmoCount() { return m_iAmmoMetal; }
CUtlVector< CHandle<C_TFPlayer> > m_hHealingTargets;
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink() OVERRIDE;
virtual void SetInvisibilityLevel( float flValue );
void UpdateEffects( void );
void StopEffects( bool bRemoveAll = false );
virtual void UpdateDamageEffects( BuildingDamageLevel_t damageLevel );
virtual int GetMaxMetal( void );
bool m_bUpdateHealingTargets;
private:
int m_iState;
int m_iAmmoMetal;
int m_iMiniBombCounter;
bool m_bPlayingSound;
struct healingtargeteffects_t
{
C_BaseEntity *pTarget;
CNewParticleEffect *pEffect;
};
CUtlVector<healingtargeteffects_t> m_hHealingTargetEffects;
C_ObjectDispenser( const C_ObjectDispenser & ); // not defined, not accessible
};
class CDispenserControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CDispenserControlPanel, CObjectControlPanel );
public:
CDispenserControlPanel( vgui::Panel *parent, const char *panelName );
protected:
virtual void OnTickActive( C_BaseObject *pObj, C_TFPlayer *pLocalPlayer );
virtual bool IsVisible() OVERRIDE;
private:
vgui::RotatingProgressBar *m_pAmmoProgress;
CHandle< C_ObjectDispenser > m_hDispenser;
};
class CDispenserControlPanel_Red : public CDispenserControlPanel
{
DECLARE_CLASS( CDispenserControlPanel_Red, CDispenserControlPanel );
public:
CDispenserControlPanel_Red( vgui::Panel *parent, const char *panelName ) : CDispenserControlPanel( parent, panelName ) {}
};
class C_ObjectCartDispenser : public C_ObjectDispenser
{
DECLARE_CLASS( C_ObjectCartDispenser, C_ObjectDispenser );
public:
DECLARE_CLIENTCLASS();
};
#endif //C_OBJ_DISPENSER_H
+54
View File
@@ -0,0 +1,54 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "c_obj_sapper.h"
#include "c_tf_player.h"
#include <igameevents.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Start thinking
//-----------------------------------------------------------------------------
void C_ObjectSapper::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
if ( type == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
//-----------------------------------------------------------------------------
// Purpose: Create the sparking effect if we're built and ready
//-----------------------------------------------------------------------------
void C_ObjectSapper::ClientThink( void )
{
IGameEvent *event = gameeventmanager->CreateEvent( "building_info_changed" );
if ( event )
{
event->SetInt( "building_type", OBJ_ATTACHMENT_SAPPER );
event->SetInt( "object_mode", GetObjectMode() );
gameeventmanager->FireEventClientSide( event );
}
}
float C_ObjectSapper::GetReversesBuildingConstructionSpeed( void )
{
float flReverseSpeed = 0.0f;
CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBuilder(), flReverseSpeed, sapper_degenerates_buildings );
return flReverseSpeed;
}
IMPLEMENT_CLIENTCLASS_DT(C_ObjectSapper, DT_ObjectSapper, CObjectSapper)
END_RECV_TABLE()
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_OBJ_SAPPER_H
#define C_OBJ_SAPPER_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_obj_baseupgrade_shared.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_ObjectSapper : public C_BaseObjectUpgrade
{
DECLARE_CLASS( C_ObjectSapper, C_BaseObjectUpgrade );
public:
DECLARE_CLIENTCLASS();
C_ObjectSapper() {}
virtual void ClientThink( void );
virtual void OnDataChanged( DataUpdateType_t type );
virtual bool IsHostileUpgrade( void ) { return true; }
float GetReversesBuildingConstructionSpeed( void );
private:
C_ObjectSapper( const C_ObjectSapper & ); // not defined, not accessible
};
#endif // C_OBJ_SAPPER_H
+761
View File
@@ -0,0 +1,761 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CObjectSentrygun
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_tf_player.h"
#include "vgui_bitmapbutton.h"
#include "vgui/ILocalize.h"
#include "tf_fx_muzzleflash.h"
#include "eventlist.h"
#include "hintsystem.h"
#include <vgui_controls/ProgressBar.h>
#include "igameevents.h"
#include "c_obj_sentrygun.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
static void RecvProxy_BooleanToShieldLevel( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
// convert old boolean "m_bShielded" to uint32 "m_nShieldLevel"
*(uint32*)pOut = ( pData->m_Value.m_Int != 0 ) ? 1 : 0;
}
IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_SentryRocket, DT_TFProjectile_SentryRocket )
BEGIN_NETWORK_TABLE( C_TFProjectile_SentryRocket, DT_TFProjectile_SentryRocket )
END_NETWORK_TABLE()
BEGIN_NETWORK_TABLE_NOBASE( C_ObjectSentrygun, DT_SentrygunLocalData )
RecvPropInt( RECVINFO(m_iKills) ),
RecvPropInt( RECVINFO(m_iAssists) ),
END_NETWORK_TABLE()
IMPLEMENT_CLIENTCLASS_DT(C_ObjectSentrygun, DT_ObjectSentrygun, CObjectSentrygun)
RecvPropInt( RECVINFO(m_iAmmoShells) ),
RecvPropInt( RECVINFO(m_iAmmoRockets) ),
RecvPropInt( RECVINFO(m_iState) ),
RecvPropBool( RECVINFO(m_bPlayerControlled) ),
RecvPropInt( RECVINFO(m_nShieldLevel) ),
RecvPropInt( RECVINFO_NAME(m_nShieldLevel, m_bShielded), 0, RecvProxy_BooleanToShieldLevel ), // for demo compatibility only
RecvPropEHandle( RECVINFO( m_hEnemy ) ),
RecvPropEHandle( RECVINFO( m_hAutoAimTarget ) ),
RecvPropDataTable( "SentrygunLocalData", 0, 0, &REFERENCE_RECV_TABLE( DT_SentrygunLocalData ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectSentrygun::C_ObjectSentrygun()
{
m_iMaxAmmoShells = SENTRYGUN_MAX_SHELLS_1;
m_bPlayerControlled = false;
m_bOldPlayerControlled = false;
m_nShieldLevel = SHIELD_NONE;
m_nOldShieldLevel = SHIELD_NONE;
m_hLaserBeamEffect = NULL;
m_pTempShield = NULL;
m_bNearMiss = false;
m_flNextNearMissCheck = 0.f;
m_iOldModelIndex = 0;
m_bOldCarried = false;
m_bRecreateShield = false;
m_bRecreateLaserBeam = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::UpdateOnRemove( void )
{
DestroyLaserBeam();
DestroyShield();
DestroySiren();
BaseClass::UpdateOnRemove();
}
void C_ObjectSentrygun::GetAmmoCount( int &iShells, int &iMaxShells, int &iRockets, int & iMaxRockets )
{
iShells = m_iAmmoShells;
iMaxShells = m_iMaxAmmoShells;
iRockets = m_iAmmoRockets;
iMaxRockets = SENTRYGUN_MAX_ROCKETS;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::UpgradeLevelChanged()
{
switch( m_iUpgradeLevel )
{
case 1:
{
VectorCopy( SENTRYGUN_EYE_OFFSET_LEVEL_1, m_vecViewOffset );
m_iMaxAmmoShells = SENTRYGUN_MAX_SHELLS_1;
break;
}
case 2:
{
VectorCopy( SENTRYGUN_EYE_OFFSET_LEVEL_2, m_vecViewOffset );
m_iMaxAmmoShells = SENTRYGUN_MAX_SHELLS_2;
break;
}
case 3:
{
VectorCopy( SENTRYGUN_EYE_OFFSET_LEVEL_3, m_vecViewOffset );
m_iMaxAmmoShells = SENTRYGUN_MAX_SHELLS_3;
break;
}
default:
{
Assert( 0 );
break;
}
}
CreateLaserBeam();
// Because the bounding box size changes when upgrading, force the shadow to be reprojected using the new bounds
g_pClientShadowMgr->AddToDirtyShadowList( this, true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_iOldBodygroups = GetBody();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// intercept bodygroup sets from the server
// we aren't clientsideanimating, but we don't want the server setting our
// bodygroup while we are placing
if ( m_iOldBodygroups != GetBody() )
{
if ( IsPlacing() )
{
m_nBody = m_iOldBodygroups;
}
}
if ( GetModelIndex() != m_iOldModelIndex )
{
m_iOldModelIndex = GetModelIndex();
if ( IsMiniBuilding() )
{
CStudioHdr *pStudiohdr = GetModelPtr();
int bodyGroup = FindBodygroupByName( "mini_sentry_light" );
if ( bodyGroup < pStudiohdr->numbodyparts() )
{
mstudiobodyparts_t *pbodypart = pStudiohdr->pBodypart( bodyGroup );
if ( pbodypart->base > 0 )
{
SetBodygroup( bodyGroup, 1 );
}
}
}
}
if ( m_bPlayerControlled != m_bOldPlayerControlled || m_bRecreateLaserBeam )
{
if ( m_bPlayerControlled )
{
CreateLaserBeam();
}
else
{
DestroyLaserBeam();
}
m_bOldPlayerControlled = m_bPlayerControlled;
m_bRecreateLaserBeam = false;
}
if ( m_nShieldLevel != m_nOldShieldLevel || m_bRecreateShield )
{
if ( m_nShieldLevel > 0 )
{
CreateShield();
}
else
{
DestroyShield();
}
m_nOldShieldLevel = m_nShieldLevel;
m_bRecreateShield = false;
}
if ( IsCarried() != m_bOldCarried )
{
m_bOldCarried = IsCarried();
if ( IsCarried() )
{
DestroySiren();
}
}
if ( ShouldBeActive() && !IsDisabled() && IsMiniBuilding() && !m_hSirenEffect )
{
CreateSiren();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::OnGoActive( void )
{
CreateSiren();
BaseClass::OnGoActive();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::OnGoInactive( void )
{
DestroySiren();
BaseClass::OnGoInactive();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::OnStartDisabled( void )
{
DestroySiren();
BaseClass::OnStartDisabled();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::OnEndDisabled( void )
{
CreateSiren();
BaseClass::OnEndDisabled();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::CreateLaserBeam( void )
{
if ( !m_bPlayerControlled )
return;
DestroyLaserBeam();
int iAttachment = LookupAttachment( "laser_origin" );
m_hLaserBeamEffect = ParticleProp()->Create( "laser_sight_beam", PATTACH_POINT_FOLLOW, iAttachment );
if ( m_hLaserBeamEffect )
{
m_hLaserBeamEffect->SetSortOrigin( m_hLaserBeamEffect->GetRenderOrigin() );
}
SetNextClientThink( CLIENT_THINK_ALWAYS );
if ( m_hLaserBeamEffect )
{
if ( GetTeamNumber() == TF_TEAM_BLUE )
{
m_hLaserBeamEffect->SetControlPoint( 2, Vector( 0, 0, 255 ) );
}
else
{
m_hLaserBeamEffect->SetControlPoint( 2, Vector( 255, 0, 0 ) );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::DestroyLaserBeam( void )
{
if ( m_hLaserBeamEffect )
{
SetNextClientThink( CLIENT_THINK_NEVER );
ParticleProp()->StopEmissionAndDestroyImmediately( m_hLaserBeamEffect );
m_hLaserBeamEffect = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::SetDormant( bool bDormant )
{
if ( IsDormant() && !bDormant )
{
// Make sure our shield is where we are. We may have moved since last seen.
if ( m_pTempShield )
{
m_bRecreateShield = true;
m_bRecreateLaserBeam = true;
}
}
BaseClass::SetDormant( bDormant );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::CreateShield( void )
{
DestroyShield();
model_t *pModel = (model_t *) engine->LoadModel( "models/buildables/sentry_shield.mdl" );
m_pTempShield = tempents->SpawnTempModel( pModel, GetAbsOrigin(), GetAbsAngles(), Vector(0, 0, 0), 1, FTENT_NEVERDIE );
if ( m_pTempShield )
{
m_pTempShield->ChangeTeam( GetTeamNumber() );
m_pTempShield->m_nSkin = ( GetTeamNumber() == TF_TEAM_RED ) ? 0 : 1;
//m_pTempShield->m_nRenderFX = kRenderFxDistort;
}
m_hShieldEffect = ParticleProp()->Create( "turret_shield", PATTACH_ABSORIGIN_FOLLOW, 0, Vector( 0,0,30) );
if ( !m_hShieldEffect )
return;
if ( GetTeamNumber() == TF_TEAM_BLUE )
{
m_hShieldEffect->SetControlPoint( 1, Vector(50,150,255) );
}
else
{
m_hShieldEffect->SetControlPoint( 1, Vector(255,50,50) );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::DestroyShield( void )
{
if ( m_pTempShield )
{
m_pTempShield->flags = FTENT_FADEOUT;
m_pTempShield->die = gpGlobals->curtime;
m_pTempShield->fadeSpeed = 1.0f;
m_pTempShield = NULL;
}
if ( m_hShieldEffect )
{
ParticleProp()->StopEmission( m_hShieldEffect );
m_hShieldEffect = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::CreateSiren( void )
{
if ( !IsMiniBuilding() )
return;
if ( IsCarried() )
return;
if ( m_hSirenEffect )
return;
const char* flashlightName = "cart_flashinglight";
if ( GetTeamNumber() == TF_TEAM_RED )
{
flashlightName = "cart_flashinglight_red";
}
m_hSirenEffect = ParticleProp()->Create( flashlightName, PATTACH_POINT_FOLLOW, "siren" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::DestroySiren( void )
{
if ( m_hSirenEffect )
{
ParticleProp()->StopEmission( m_hSirenEffect );
m_hSirenEffect = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::ClientThink( void )
{
if ( m_hLaserBeamEffect && m_hEnemy && GetBuilder() )
{
QAngle vecAngles;
Vector vecMuzzleOrigin;
int iAttachment = 0;
switch ( GetUpgradeLevel() )
{
case 1:
iAttachment = LookupAttachment( "muzzle" );
break;
case 2:
iAttachment = LookupAttachment( "muzzle_l" );
break;
case 3:
iAttachment = LookupAttachment( "rocket_l" );
break;
}
GetAttachment( iAttachment, vecMuzzleOrigin, vecAngles );
Vector vForward;
AngleVectors( vecAngles, &vForward );
Vector vEnd = m_hEnemy->WorldSpaceCenter();
if ( m_hAutoAimTarget )
{
vEnd = m_hAutoAimTarget->GetAbsOrigin() + m_hAutoAimTarget->GetClassEyeHeight()*0.75f;
}
trace_t trace;
CTraceFilterIgnoreTeammatesAndTeamObjects filter( GetBuilder(), COLLISION_GROUP_NONE, GetBuilder()->GetTeamNumber() );
UTIL_TraceLine( vecMuzzleOrigin, vEnd, MASK_SOLID, &filter, &trace );
Vector vecInterpBeamPos;
InterpolateVector( gpGlobals->frametime * 25.f, m_vecLaserBeamPos, trace.endpos, vecInterpBeamPos );
m_hLaserBeamEffect->SetControlPoint( 1, vecInterpBeamPos );
m_vecLaserBeamPos = vecInterpBeamPos;
// Perform a near-miss check.
// This works pretty well as a threat indicator for the arrow, let's try it for our laser.
if ( gpGlobals->curtime > m_flNextNearMissCheck )
{
// CheckNearMiss( vecMuzzleOrigin, m_hEnemy->GetAbsOrigin() );
m_flNextNearMissCheck = gpGlobals->curtime + 0.2f;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::CheckNearMiss( Vector vecStart, Vector vecEnd )
{
// Check against the local player. If the laser sweeps near him, play the near miss sound...
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pLocalPlayer || !pLocalPlayer->IsAlive() )
return;
// Can't hear near miss sounds from friendly guns.
// if ( pLocalPlayer->GetTeamNumber() == GetTeamNumber() )
// return;
Vector vecPlayerPos = pLocalPlayer->GetAbsOrigin();
Vector vecClosestPoint;
float dist;
CalcClosestPointOnLineSegment( vecPlayerPos, vecStart, vecEnd, vecClosestPoint, &dist );
dist = vecPlayerPos.DistTo( vecClosestPoint );
if ( dist > 120 )
{
StopSound( "Building_Sentrygun.ShaftLaserPass" );
return;
}
if ( !m_bNearMiss )
{
// We're good for a near miss!
float soundlen = 0;
EmitSound_t params;
params.m_flSoundTime = 0;
params.m_pSoundName = "Building_Sentrygun.ShaftLaserPass";
params.m_pflSoundDuration = &soundlen;
params.m_flVolume = 1.f - (dist / 120.f);
CSingleUserRecipientFilter localFilter( pLocalPlayer );
EmitSound( localFilter, pLocalPlayer->entindex(), params );
m_bNearMiss = true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::DisplayHintTo( C_BasePlayer *pPlayer )
{
bool bHintPlayed = false;
C_TFPlayer *pTFPlayer = ToTFPlayer(pPlayer);
if ( InSameTeam( pPlayer ) )
{
// We're looking at a friendly object.
if ( pTFPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) )
{
// If the sentrygun can be upgraded, and I can afford it, let me know
if ( GetHealth() == GetMaxHealth() && GetUpgradeLevel() < 3 )
{
if ( pTFPlayer->GetBuildResources() >= SENTRYGUN_UPGRADE_COST )
{
bHintPlayed = pTFPlayer->HintMessage( HINT_ENGINEER_UPGRADE_SENTRYGUN, false, true );
}
else
{
bHintPlayed = pTFPlayer->HintMessage( HINT_ENGINEER_METAL_TO_UPGRADE, false, true );
}
}
}
}
if ( !bHintPlayed )
{
BaseClass::DisplayHintTo( pPlayer );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_ObjectSentrygun::GetHudStatusIcon( void )
{
const char *pszResult;
switch( m_iUpgradeLevel )
{
case 1:
default:
pszResult = "obj_status_sentrygun_1";
break;
case 2:
pszResult = "obj_status_sentrygun_2";
break;
case 3:
pszResult = "obj_status_sentrygun_3";
break;
}
return pszResult;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
BuildingHudAlert_t C_ObjectSentrygun::GetBuildingAlertLevel( void )
{
BuildingHudAlert_t baseAlertLevel = BaseClass::GetBuildingAlertLevel();
// Just warn on low shells.
float flShellPercent = (float)m_iAmmoShells / (float)m_iMaxAmmoShells;
BuildingHudAlert_t alertLevel = BUILDING_HUD_ALERT_NONE;
if ( !IsCarried() )
{
if ( !IsBuilding() && flShellPercent < 0.25 )
{
alertLevel = BUILDING_HUD_ALERT_VERY_LOW_AMMO;
}
else if ( !IsBuilding() && flShellPercent < 0.50 )
{
alertLevel = BUILDING_HUD_ALERT_LOW_AMMO;
}
}
return MAX( baseAlertLevel, alertLevel );
}
//-----------------------------------------------------------------------------
// Purpose: During placement, only use the smaller bbox for shadow calc, don't include the range bodygroup
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType )
{
if ( IsPlacing() )
{
mins = CollisionProp()->OBBMins();
maxs = CollisionProp()->OBBMaxs();
// HACK: The collision prop bounding box doesn't quite cover the blueprint model, so we bloat it a little
Vector bbBloat( 10.0f, 10.0f, 0.0f );
mins -= bbBloat;
maxs += bbBloat;
}
else
{
BaseClass::GetShadowRenderBounds( mins, maxs, shadowType );
}
}
//-----------------------------------------------------------------------------
// Purpose: Re-calc our damage particles when we get a new model
//-----------------------------------------------------------------------------
CStudioHdr *C_ObjectSentrygun::OnNewModel( void )
{
CStudioHdr *hdr = BaseClass::OnNewModel();
UpdateDamageEffects( m_damageLevel );
// Reset Bodygroups
for ( int i = GetNumBodyGroups()-1; i >= 0; i-- )
{
SetBodygroup( i, 0 );
}
m_iPlacementBodygroup = FindBodygroupByName( "sentry1_range" );
m_iPlacementBodygroup_Mini = FindBodygroupByName( "sentry1_range_mini" );
return hdr;
}
//-----------------------------------------------------------------------------
// Purpose: Damage level has changed, update our effects
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::UpdateDamageEffects( BuildingDamageLevel_t damageLevel )
{
if ( m_hDamageEffects )
{
m_hDamageEffects->StopEmission( false, false );
m_hDamageEffects = NULL;
}
const char *pszEffect = "";
switch( damageLevel )
{
case BUILDING_DAMAGE_LEVEL_LIGHT:
pszEffect = "sentrydamage_1";
break;
case BUILDING_DAMAGE_LEVEL_MEDIUM:
pszEffect = "sentrydamage_2";
break;
case BUILDING_DAMAGE_LEVEL_HEAVY:
pszEffect = "sentrydamage_3";
break;
case BUILDING_DAMAGE_LEVEL_CRITICAL:
pszEffect = "sentrydamage_4";
break;
default:
break;
}
if ( Q_strlen(pszEffect) > 0 )
{
switch( m_iUpgradeLevel )
{
case 1:
case 2:
m_hDamageEffects = ParticleProp()->Create( pszEffect, PATTACH_POINT_FOLLOW, "build_point_0" );
break;
case 3:
m_hDamageEffects = ParticleProp()->Create( pszEffect, PATTACH_POINT_FOLLOW, "sentrydamage" );
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: placement state has changed, update the model
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::OnPlacementStateChanged( bool bValidPlacement )
{
if ( bValidPlacement && ( m_iPlacementBodygroup >= 0 ) && ( m_iPlacementBodygroup_Mini >= 0 ) )
{
if ( IsMiniBuilding() )
{
SetBodygroup( m_iPlacementBodygroup, 0 );
SetBodygroup( m_iPlacementBodygroup_Mini, 1 );
}
else
{
SetBodygroup( m_iPlacementBodygroup, 1 );
SetBodygroup( m_iPlacementBodygroup_Mini, 0 );
}
}
else
{
SetBodygroup( m_iPlacementBodygroup, 0 );
SetBodygroup( m_iPlacementBodygroup_Mini, 0 );
}
BaseClass::OnPlacementStateChanged( bValidPlacement );
}
void C_ObjectSentrygun::DebugDamageParticles( void )
{
Msg( "Health %d\n", GetHealth() );
BuildingDamageLevel_t damageLevel = CalculateDamageLevel();
Msg( "Damage Level %d\n", (int)damageLevel );
if ( m_hDamageEffects )
{
Msg( "m_hDamageEffects is valid\n" );
}
else
{
Msg( "m_hDamageEffects is NULL\n" );
}
// print all particles owned by particleprop
ParticleProp()->DebugPrintEffects();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectSentrygun::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed )
{
BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed );
if ( !IsMiniBuilding() )
return;
if ( IsBuilding() || IsPlacing() )
return;
//Vector position;
//for ( int i=0; i<8; ++i )
//{
// matrix3x4_t &transform = GetBoneForWrite( i );
// MatrixGetColumn( transform, 3, position );
// MatrixSetColumn( Vector(0,0,-4) + position, 3, transform );
//}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char* C_ObjectSentrygun::GetStatusName() const
{
if ( IsDisposableBuilding() )
{
return "#TF_Object_Sentry_Disp";
}
return "#TF_Object_Sentry";
}
+150
View File
@@ -0,0 +1,150 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_OBJ_SENTRYGUN_H
#define C_OBJ_SENTRYGUN_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseobject.h"
#include "ObjectControlPanel.h"
#include "c_tf_projectile_rocket.h"
#include "tempent.h"
#include "c_te_legacytempents.h"
#include "c_tf_player.h"
class C_MuzzleFlashModel;
enum
{
SHIELD_NONE = 0,
SHIELD_NORMAL, // 33% damage taken
SHIELD_MAX, // 10% damage taken, no inactive period
};
//-----------------------------------------------------------------------------
// Purpose: Sentry object
//-----------------------------------------------------------------------------
class C_ObjectSentrygun : public C_BaseObject
{
DECLARE_CLASS( C_ObjectSentrygun, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectSentrygun();
virtual void UpdateOnRemove( void );
void GetAmmoCount( int &iShells, int &iMaxShells, int &iRockets, int & iMaxRockets );
virtual BuildingHudAlert_t GetBuildingAlertLevel( void );
virtual const char *GetHudStatusIcon( void );
int GetKills( void ) { return m_iKills; }
int GetAssists( void ) { return m_iAssists; }
virtual void GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType );
virtual CStudioHdr *OnNewModel( void );
virtual void UpdateDamageEffects( BuildingDamageLevel_t damageLevel );
virtual void OnPlacementStateChanged( bool bValidPlacement );
void DebugDamageParticles();
virtual const char* GetStatusName() const;
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual bool IsUpgrading( void ) const { return ( m_iState == SENTRY_STATE_UPGRADING ); }
void CreateLaserBeam( void );
void DestroyLaserBeam( void );
virtual void SetDormant( bool bDormant );
void CreateShield( void );
void DestroyShield( void );
void CreateSiren( void );
void DestroySiren( void );
virtual void OnGoActive( void );
virtual void OnGoInactive( void );
virtual void OnStartDisabled( void );
virtual void OnEndDisabled( void );
virtual void ClientThink( void );
void CheckNearMiss( Vector vecStart, Vector vecEnd );
// ITargetIDProvidesHint
public:
virtual void DisplayHintTo( C_BasePlayer *pPlayer );
virtual void BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
private:
virtual void UpgradeLevelChanged();
private:
int m_iState;
int m_iAmmoShells;
int m_iMaxAmmoShells;
int m_iAmmoRockets;
int m_iKills;
int m_iAssists;
int m_iPlacementBodygroup;
int m_iPlacementBodygroup_Mini;
int m_iOldBodygroups;
bool m_bPlayerControlled;
bool m_bOldPlayerControlled;
uint32 m_nShieldLevel;
uint32 m_nOldShieldLevel;
bool m_bOldCarried;
bool m_bPDQSentry;
int m_iOldModelIndex;
bool m_bNearMiss;
bool m_bRecreateShield;
bool m_bRecreateLaserBeam;
float m_flNextNearMissCheck;
C_LocalTempEntity *m_pTempShield;
HPARTICLEFFECT m_hSirenEffect;
HPARTICLEFFECT m_hShieldEffect;
HPARTICLEFFECT m_hLaserBeamEffect;
CNetworkHandle( CBaseEntity, m_hEnemy );
CNetworkHandle( C_TFPlayer, m_hAutoAimTarget );
Vector m_vecLaserBeamPos;
private:
C_ObjectSentrygun( const C_ObjectSentrygun & ); // not defined, not accessible
};
class C_TFProjectile_SentryRocket : public C_TFProjectile_Rocket
{
DECLARE_CLASS( C_TFProjectile_SentryRocket, C_TFProjectile_Rocket );
public:
DECLARE_CLIENTCLASS();
virtual void CreateRocketTrails( void ) {}
};
#endif //C_OBJ_SENTRYGUN_H
+465
View File
@@ -0,0 +1,465 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CObjectTeleporter
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_baseobject.h"
#include "c_tf_player.h"
#include "vgui/ILocalize.h"
#include "c_obj_teleporter.h"
#include "soundenvelope.h"
#include "vgui/ILocalize.h"
#include "tf_gamerules.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
#define TELEPORTER_MINS Vector( -24, -24, 0)
#define TELEPORTER_MAXS Vector( 24, 24, 12)
//-----------------------------------------------------------------------------
// Purpose: Teleporter object
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT(C_ObjectTeleporter, DT_ObjectTeleporter, CObjectTeleporter)
RecvPropInt( RECVINFO(m_iState) ),
RecvPropTime( RECVINFO(m_flRechargeTime) ),
RecvPropTime( RECVINFO(m_flCurrentRechargeDuration) ),
RecvPropInt( RECVINFO(m_iTimesUsed) ),
RecvPropFloat( RECVINFO(m_flYawToExit) ),
RecvPropBool( RECVINFO(m_bMatchBuilding) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_ObjectTeleporter::C_ObjectTeleporter()
{
m_hChargedEffect = NULL;
m_hDirectionEffect = NULL;
m_hChargedLeftArmEffect = NULL;
m_hChargedRightArmEffect = NULL;
m_iDirectionArrowPoseParam = 0;
m_pSpinSound = NULL;
m_bMatchBuilding = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::UpdateOnRemove( void )
{
StopActiveEffects();
StopChargedEffects();
if ( m_pSpinSound )
{
CSoundEnvelopeController::GetController().SoundDestroy( m_pSpinSound );
}
BaseClass::UpdateOnRemove();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_iOldState = m_iState;
m_bOldMatchBuilding = m_bMatchBuilding;
}
void C_ObjectTeleporter::StartBuildingEffects()
{
StopBuildingEffects();
char szEffect[128];
// arm glow effects
Q_snprintf( szEffect, sizeof(szEffect), "teleporter_arms_circle_%s_blink", ( GetTeamNumber() == TF_TEAM_RED ) ? "red" : "blue" );
Assert( m_hBuildingLeftArmEffect.m_pObject == NULL );
m_hBuildingLeftArmEffect = ParticleProp()->Create( szEffect, PATTACH_POINT_FOLLOW, 1 );
Assert( m_hBuildingRightArmEffect.m_pObject == NULL );
m_hBuildingRightArmEffect = ParticleProp()->Create( szEffect, PATTACH_POINT_FOLLOW, 3 );
}
void C_ObjectTeleporter::StartChargedEffects()
{
StopChargedEffects();
char szEffect[128];
Q_snprintf( szEffect, sizeof(szEffect), "teleporter_%s_charged_level%d",
( GetTeamNumber() == TF_TEAM_RED ) ? "red" : "blue", GetUpgradeLevel() );
Assert( m_hChargedEffect.m_pObject == NULL );
m_hChargedEffect = ParticleProp()->Create( szEffect, PATTACH_ABSORIGIN );
}
void C_ObjectTeleporter::StartActiveEffects()
{
StopActiveEffects();
char szEffect[128];
Q_snprintf( szEffect, sizeof(szEffect), "teleporter_%s_%s_level%d",
( GetTeamNumber() == TF_TEAM_RED ) ? "red" : "blue",
GetObjectMode() == MODE_TELEPORTER_ENTRANCE ? "entrance" : "exit",
GetUpgradeLevel() );
Assert( m_hDirectionEffect.m_pObject == NULL );
m_hDirectionEffect = ParticleProp()->Create( szEffect, PATTACH_ABSORIGIN );
// arm glow effects
Q_snprintf( szEffect, sizeof(szEffect), "teleporter_arms_circle_%s",
( GetTeamNumber() == TF_TEAM_RED ) ? "red" : "blue" );
Assert( m_hChargedLeftArmEffect.m_pObject == NULL );
m_hChargedLeftArmEffect = ParticleProp()->Create( szEffect, PATTACH_POINT_FOLLOW, 1 );
Assert( m_hChargedRightArmEffect.m_pObject == NULL );
m_hChargedRightArmEffect = ParticleProp()->Create( szEffect, PATTACH_POINT_FOLLOW, 3 );
// always reinitializes sound since this only gets called when the sound needs to start or change
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
if ( m_pSpinSound )
{
controller.SoundDestroy( m_pSpinSound );
m_pSpinSound = NULL;
}
char szSound[128];
Q_snprintf( szSound, sizeof(szSound), "Building_Teleporter.SpinLevel%d", GetUpgradeLevel());
CLocalPlayerFilter filter;
m_pSpinSound = controller.SoundCreate( filter, entindex(), szSound );
controller.Play( m_pSpinSound, 1.0, 100 );
}
void C_ObjectTeleporter::StopBuildingEffects()
{
if ( m_hBuildingLeftArmEffect )
{
ParticleProp()->StopEmission( m_hBuildingLeftArmEffect );
m_hBuildingLeftArmEffect = NULL;
}
if ( m_hBuildingRightArmEffect )
{
ParticleProp()->StopEmission( m_hBuildingRightArmEffect );
m_hBuildingRightArmEffect = NULL;
}
}
void C_ObjectTeleporter::StopChargedEffects()
{
if ( m_hChargedEffect )
{
ParticleProp()->StopEmission( m_hChargedEffect );
m_hChargedEffect = NULL;
}
}
void C_ObjectTeleporter::StopActiveEffects()
{
if ( m_hDirectionEffect )
{
ParticleProp()->StopEmission( m_hDirectionEffect );
m_hDirectionEffect = NULL;
}
if ( m_hChargedLeftArmEffect )
{
ParticleProp()->StopEmission( m_hChargedLeftArmEffect );
m_hChargedLeftArmEffect = NULL;
}
if ( m_hChargedRightArmEffect )
{
ParticleProp()->StopEmission( m_hChargedRightArmEffect );
m_hChargedRightArmEffect = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::SetInvisibilityLevel( float flValue )
{
if ( IsEnteringOrExitingFullyInvisible( flValue ) )
{
UpdateTeleporterEffects();
}
BaseClass::SetInvisibilityLevel( flValue );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::UpdateTeleporterEffects( void )
{
#ifdef STAGING_ONLY
C_TFPlayer *pTFOwner = GetOwner();
if ( ( pTFOwner && pTFOwner->m_Shared.IsEnteringOrExitingFullyInvisible() ) || GetInvisibilityLevel() == 1.f )
{
StopActiveEffects();
StopBuildingEffects();
StopChargedEffects();
return;
}
#endif // STAGING_ONLY
if ( m_bMatchBuilding )
{
StartBuildingEffects();
}
else
{
StopBuildingEffects();
}
// In MVM, teleporter from invaders act as spawn point. Always play active effect
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
{
if ( m_iState != TELEPORTER_STATE_BUILDING && GetTeamNumber() == TF_TEAM_PVE_INVADERS )
{
StartChargedEffects();
StartActiveEffects();
return;
}
}
if ( m_iState == TELEPORTER_STATE_READY )
{
StartChargedEffects();
}
else
{
StopChargedEffects();
}
if ( m_iState > TELEPORTER_STATE_IDLE && m_iOldState <= TELEPORTER_STATE_IDLE )
{
StartActiveEffects();
}
else if ( ( m_iState <= TELEPORTER_STATE_IDLE || m_iState == TELEPORTER_STATE_UPGRADING ) && m_iOldState > TELEPORTER_STATE_IDLE )
{
StopActiveEffects();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( m_bOldMatchBuilding != m_bMatchBuilding )
{
m_bOldMatchBuilding = m_bMatchBuilding;
UpdateTeleporterEffects();
}
if ( m_iOldState != m_iState )
{
UpdateTeleporterEffects();
m_iOldState = m_iState;
}
// update the pitch based on our playback rate
if ( m_pSpinSound )
{
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
controller.SoundChangePitch( m_pSpinSound, GetPlaybackRate() * 100.0f, 0.1 );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float C_ObjectTeleporter::GetChargeTime( void )
{
float flTime = m_flRechargeTime - gpGlobals->curtime;
if ( flTime < 0 )
return 0;
return flTime;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_ObjectTeleporter::GetTimesUsed( void )
{
return m_iTimesUsed;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStudioHdr *C_ObjectTeleporter::OnNewModel( void )
{
CStudioHdr *hdr = BaseClass::OnNewModel();
m_iDirectionArrowPoseParam = LookupPoseParameter( "direction" );
SetNextClientThink( CLIENT_THINK_ALWAYS );
return hdr;
}
//-----------------------------------------------------------------------------
// Purpose: Update the direction arrow
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::ClientThink( void )
{
if ( m_iState >= TELEPORTER_STATE_READY )
{
SetPoseParameter( m_iDirectionArrowPoseParam, m_flYawToExit);
}
#ifdef STAGING_ONLY
C_TFPlayer *pTFOwner = GetOwner();
if ( pTFOwner && pTFOwner->m_Shared.IsEnteringOrExitingFullyInvisible() )
{
UpdateTeleporterEffects();
}
#endif // STAGING_ONLY
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::GetTargetIDDataString( OUT_Z_BYTECAP(iMaxLenInBytes) wchar_t *sDataString, int iMaxLenInBytes )
{
Assert( iMaxLenInBytes >= sizeof(sDataString[0]) );
wchar_t wzBaseString[MAX_ID_STRING];
BaseClass::GetTargetIDDataString( wzBaseString, sizeof( wzBaseString ) );
sDataString[0] = '\0';
if ( m_iState == TELEPORTER_STATE_RECHARGING && gpGlobals->curtime < m_flRechargeTime )
{
float flPercent = clamp( ( m_flRechargeTime - gpGlobals->curtime ) / m_flCurrentRechargeDuration, 0.0f, 1.0f );
wchar_t wszRecharging[ 32 ];
_snwprintf( wszRecharging, ARRAYSIZE(wszRecharging) - 1, L"%.0f", 100 - (flPercent * 100) );
wszRecharging[ ARRAYSIZE(wszRecharging)-1 ] = '\0';
const char *printFormatString = "#TF_playerid_object_recharging";
g_pVGuiLocalize->ConstructString( sDataString, iMaxLenInBytes, g_pVGuiLocalize->Find(printFormatString),
1,
wszRecharging );
}
else if ( m_iState == TELEPORTER_STATE_IDLE )
{
g_pVGuiLocalize->ConstructString( sDataString, iMaxLenInBytes, g_pVGuiLocalize->Find("#TF_playerid_teleporter_nomatch" ), 0 );
}
// Concatenate the base level string
V_wcsncat( sDataString, L" ", iMaxLenInBytes / sizeof( wchar_t ) );
V_wcsncat( sDataString, wzBaseString, iMaxLenInBytes / sizeof( wchar_t ) );
}
//-----------------------------------------------------------------------------
// Purpose: Damage level has changed, update our effects
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::UpdateDamageEffects( BuildingDamageLevel_t damageLevel )
{
if ( m_hDamageEffects )
{
m_hDamageEffects->StopEmission( false, false );
m_hDamageEffects = NULL;
}
const char *pszEffect = "";
switch( damageLevel )
{
case BUILDING_DAMAGE_LEVEL_LIGHT:
pszEffect = "tpdamage_1";
break;
case BUILDING_DAMAGE_LEVEL_MEDIUM:
pszEffect = "tpdamage_2";
break;
case BUILDING_DAMAGE_LEVEL_HEAVY:
pszEffect = "tpdamage_3";
break;
case BUILDING_DAMAGE_LEVEL_CRITICAL:
pszEffect = "tpdamage_4";
break;
default:
break;
}
if ( Q_strlen(pszEffect) > 0 )
{
m_hDamageEffects = ParticleProp()->Create( pszEffect, PATTACH_ABSORIGIN );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool C_ObjectTeleporter::IsPlacementPosValid( void )
{
bool bResult = BaseClass::IsPlacementPosValid();
if ( !bResult )
{
return false;
}
// m_vecBuildOrigin is the proposed build origin
// start above the teleporter position
Vector vecTestPos = m_vecBuildOrigin;
vecTestPos.z += TELEPORTER_MAXS.z;
// make sure we can fit a player on top in this pos
trace_t tr;
UTIL_TraceHull( vecTestPos, vecTestPos, VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID | CONTENTS_PLAYERCLIP, this, COLLISION_GROUP_PLAYER_MOVEMENT, &tr );
return ( tr.fraction >= 1.0 );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::UpgradeLevelChanged( void )
{
StopActiveEffects();
StopChargedEffects();
if ( m_iState >= TELEPORTER_STATE_READY && m_iState != TELEPORTER_STATE_UPGRADING )
{
StartActiveEffects();
if ( m_iState != TELEPORTER_STATE_RECHARGING )
{
StartChargedEffects();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_ObjectTeleporter::OnGoInactive( void )
{
StopActiveEffects();
StopBuildingEffects();
StopChargedEffects();
BaseClass::OnGoInactive();
}
+94
View File
@@ -0,0 +1,94 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_OBJ_TELEPORTER_H
#define C_OBJ_TELEPORTER_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseobject.h"
#include "ObjectControlPanel.h"
class C_ObjectTeleporter : public C_BaseObject
{
DECLARE_CLASS( C_ObjectTeleporter, C_BaseObject );
public:
DECLARE_CLIENTCLASS();
C_ObjectTeleporter();
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void GetTargetIDDataString( OUT_Z_BYTECAP(iMaxLenInBytes) wchar_t *sDataString, int iMaxLenInBytes );
virtual void ClientThink( void );
virtual void UpdateOnRemove();
virtual CStudioHdr *OnNewModel( void );
virtual bool IsPlacementPosValid( void );
float GetChargeTime( void );
float GetCurrentRechargeDuration( void ) { return m_flCurrentRechargeDuration; }
int GetState( void ) { return m_iState; }
int GetTimesUsed( void );
void StartChargedEffects( void );
void StopChargedEffects( void );
void StartActiveEffects( void );
void StopActiveEffects( void );
void StartBuildingEffects( void );
void StopBuildingEffects( void );
virtual void SetInvisibilityLevel( float flValue );
void UpdateTeleporterEffects( void );
virtual void UpdateDamageEffects( BuildingDamageLevel_t damageLevel );
virtual int GetUpgradeLevel( void ) { return m_iUpgradeLevel; }
int GetUpgradeMetal( void ) { return m_iUpgradeMetal; }
//virtual int GetUpgradeMetalRequired( void ) { return GetObjectInfo( GetType() )->m_UpgradeCost; }
virtual void UpgradeLevelChanged( void );
virtual void OnGoInactive( void ) OVERRIDE;
private:
int m_iState;
int m_iOldState;
float m_flRechargeTime;
float m_flCurrentRechargeDuration;
int m_iTimesUsed;
float m_flYawToExit;
bool m_bMatchBuilding;
bool m_bOldMatchBuilding;
int m_iDirectionArrowPoseParam;
HPARTICLEFFECT m_hChargedEffect;
HPARTICLEFFECT m_hDirectionEffect;
HPARTICLEFFECT m_hChargedLeftArmEffect;
HPARTICLEFFECT m_hChargedRightArmEffect;
HPARTICLEFFECT m_hBuildingLeftArmEffect;
HPARTICLEFFECT m_hBuildingRightArmEffect;
CSoundPatch *m_pSpinSound;
private:
C_ObjectTeleporter( const C_ObjectTeleporter & ); // not defined, not accessible
};
#endif //C_OBJ_TELEPORTER_H
+137
View File
@@ -0,0 +1,137 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A clientside, visual only model that's attached to players
//
//=============================================================================
#include "cbase.h"
#include "c_playerattachedmodel.h"
// Todo: Turn these all into parameters
#define PAM_ANIMATE_TIME 0.075
#define PAM_ROTATE_TIME 0.075
#define PAM_SCALE_SPEED 7
#define PAM_MAX_SCALE 3
#define PAM_SPIN_SPEED 360
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_PlayerAttachedModel *C_PlayerAttachedModel::Create( const char *pszModelName, C_BaseEntity *pParent, int iAttachment, Vector vecOffset, float flLifetime, int iFlags )
{
C_PlayerAttachedModel *pFlash = new C_PlayerAttachedModel;
if ( !pFlash )
return NULL;
if ( !pFlash->Initialize( pszModelName, pParent, iAttachment, vecOffset, flLifetime, iFlags ) )
return NULL;
return pFlash;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_PlayerAttachedModel::Initialize( const char *pszModelName, C_BaseEntity *pParent, int iAttachment, Vector vecOffset, float flLifetime, int iFlags )
{
AddEffects( EF_NORECEIVESHADOW | EF_NOSHADOW );
if ( InitializeAsClientEntity( pszModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
{
Release();
return false;
}
SetParent( pParent, iAttachment );
SetLocalOrigin( vecOffset );
SetLocalAngles( vec3_angle );
AddSolidFlags( FSOLID_NOT_SOLID );
SetLifetime( flLifetime );
SetNextClientThink( CLIENT_THINK_ALWAYS );
SetCycle( 0 );
m_iFlags = iFlags;
m_flScale = 0;
if ( m_iFlags & PAM_ROTATE_RANDOMLY )
{
m_flRotateAt = gpGlobals->curtime + PAM_ANIMATE_TIME;
}
if ( m_iFlags & PAM_ANIMATE_RANDOMLY )
{
m_flAnimateAt = gpGlobals->curtime + PAM_ROTATE_TIME;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_PlayerAttachedModel::SetLifetime( float flLifetime )
{
if ( flLifetime == PAM_PERMANENT )
{
m_flExpiresAt = PAM_PERMANENT;
}
else
{
// Expire when the lifetime is up
m_flExpiresAt = gpGlobals->curtime + flLifetime;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_PlayerAttachedModel::ClientThink( void )
{
if ( !GetMoveParent() || (m_flExpiresAt != PAM_PERMANENT && gpGlobals->curtime > m_flExpiresAt) )
{
Release();
return;
}
if ( m_iFlags & PAM_ANIMATE_RANDOMLY && gpGlobals->curtime > m_flAnimateAt )
{
float flDelta = RandomFloat(0.2,0.4) * (RandomInt(0,1) == 1 ? 1 : -1);
float flCycle = clamp( GetCycle() + flDelta, 0.f, 1.f );
SetCycle( flCycle );
m_flAnimateAt = gpGlobals->curtime + PAM_ANIMATE_TIME;
}
if ( m_iFlags & PAM_ROTATE_RANDOMLY && gpGlobals->curtime > m_flRotateAt )
{
SetLocalAngles( QAngle(0,0,RandomFloat(0,360)) );
m_flRotateAt = gpGlobals->curtime + PAM_ROTATE_TIME;
}
if ( m_iFlags & PAM_SPIN_Z )
{
float flAng = GetAbsAngles().y + (gpGlobals->frametime * PAM_SPIN_SPEED);
SetLocalAngles( QAngle(0,flAng,0) );
}
if ( m_iFlags & PAM_SCALEUP )
{
m_flScale = MIN( m_flScale + (gpGlobals->frametime * PAM_SCALE_SPEED), PAM_MAX_SCALE );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_PlayerAttachedModel::ApplyBoneMatrixTransform( matrix3x4_t& transform )
{
BaseClass::ApplyBoneMatrixTransform( transform );
if ( !(m_iFlags & PAM_SCALEUP) )
return;
VectorScale( transform[0], m_flScale, transform[0] );
VectorScale( transform[1], m_flScale, transform[1] );
VectorScale( transform[2], m_flScale, transform[2] );
}
+43
View File
@@ -0,0 +1,43 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_PLAYERATTACHEDMODEL_H
#define C_PLAYERATTACHEDMODEL_H
#ifdef _WIN32
#pragma once
#endif
#define PAM_PERMANENT -1
// Flags
#define PAM_SPIN_Z (1<<0)
#define PAM_ROTATE_RANDOMLY (1<<1)
#define PAM_SCALEUP (1<<2)
#define PAM_ANIMATE_RANDOMLY (1<<3)
//-----------------------------------------------------------------------------
// Purpose: A clientside, visual only model that's attached to players
//-----------------------------------------------------------------------------
class C_PlayerAttachedModel : public C_BaseAnimating
{
DECLARE_CLASS( C_PlayerAttachedModel, C_BaseAnimating );
public:
static C_PlayerAttachedModel *Create( const char *pszModelName, C_BaseEntity *pParent, int iAttachment, Vector vecOffset, float flLifetime = 0.2, int iFlags = 0 );
bool Initialize( const char *pszModelName, C_BaseEntity *pParent, int iAttachment, Vector vecOffset, float flLifetime, int iFlags );
void SetLifetime( float flLifetime );
void ClientThink( void );
void ApplyBoneMatrixTransform( matrix3x4_t& transform );
private:
float m_flExpiresAt;
int m_iFlags;
float m_flRotateAt;
float m_flAnimateAt;
float m_flScale;
};
#endif // C_PLAYERATTACHEDMODEL_H
+164
View File
@@ -0,0 +1,164 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A clientside, visual only model that's positioned relative to players
//
//=============================================================================
#include "cbase.h"
#include "c_playerrelativemodel.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_PlayerRelativeModel *C_PlayerRelativeModel::Create( const char *pszModelName, C_BaseEntity *pParent, Vector vecOffset, QAngle angleOffset, float flAnimSpeed, float flLifetime, int iFlags )
{
C_PlayerRelativeModel *pFlash = new C_PlayerRelativeModel;
if ( !pFlash )
return NULL;
if ( !pFlash->Initialize( pszModelName, pParent, vecOffset, angleOffset, flAnimSpeed, flLifetime, iFlags ) )
return NULL;
return pFlash;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_PlayerRelativeModel::Initialize( const char *pszModelName, C_BaseEntity *pParent, Vector vecOffset, QAngle angleOffset, float flAnimSpeed, float flLifetime, int iFlags )
{
AddEffects( EF_NORECEIVESHADOW | EF_NOSHADOW );
if ( InitializeAsClientEntity( pszModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
{
Release();
return false;
}
m_vecOffsetPos = vecOffset;
m_angleOffset = angleOffset;
SetParent( pParent, 0 );
SetLocalOrigin( vec3_origin );
SetLocalAngles( vec3_angle );
AddSolidFlags( FSOLID_NOT_SOLID );
SetLifetime( flLifetime );
SetNextClientThink( CLIENT_THINK_ALWAYS );
SetCycle( 0 );
m_qOffsetRotation = vec3_angle;
m_flAnimSpeed = flAnimSpeed;
m_iFlags = iFlags;
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_PlayerRelativeModel::SetLifetime( float flLifetime )
{
if ( flLifetime == PRM_PERMANENT )
{
m_flExpiresAt = PRM_PERMANENT;
}
else
{
// Expire when the lifetime is up
m_flExpiresAt = gpGlobals->curtime + flLifetime;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_PlayerRelativeModel::ClientThink( void )
{
if ( !GetMoveParent() || (m_flExpiresAt != PRM_PERMANENT && gpGlobals->curtime > m_flExpiresAt) )
{
Release();
return;
}
// Animate
C_BaseEntity *pParent = GetMoveParent();
Vector out(0, 0, 0);
if ( m_iFlags & PRM_SPIN_Z )
{
m_qOffsetRotation += QAngle(0, gpGlobals->frametime * m_flAnimSpeed, 0);
VectorRotate( m_vecOffsetPos, m_qOffsetRotation, out );
}
SetAbsOrigin( pParent->GetAbsOrigin() + out );
SetAbsAngles( m_qOffsetRotation + m_angleOffset );
}
//-----------------------------------------------------------------------------
// C_MerasmusBombEffect
//-----------------------------------------------------------------------------
C_MerasmusBombEffect *C_MerasmusBombEffect::Create( const char *pszModelName, C_TFPlayer *pParent, Vector vecOffset, QAngle angleOffset, float flAnimSpeed, float flLifetime, int iFlags )
{
C_MerasmusBombEffect *pFlash = new C_MerasmusBombEffect;
if ( !pFlash )
return NULL;
if ( !pFlash->Initialize( pszModelName, pParent, vecOffset, angleOffset, flAnimSpeed, flLifetime, iFlags ) )
return NULL;
return pFlash;
}
//-----------------------------------------------------------------------------
bool C_MerasmusBombEffect::Initialize( const char *pszModelName, C_TFPlayer *pParent, Vector vecOffset, QAngle angleOffset, float flAnimSpeed, float flLifetime, int iFlags )
{
if ( !BaseClass::Initialize(pszModelName, pParent, vecOffset, angleOffset, flAnimSpeed, flLifetime, iFlags ) )
return false;
// Create a particle effect
const char *pszEffectName = "bombonomicon_spell_trail";
if ( m_pBombonomiconBeam )
{
m_pBombonomiconBeam->StopEmission();
m_pBombonomiconBeam = NULL;
}
if ( m_pBombonomiconEffect )
{
m_pBombonomiconEffect->StopEmission();
m_pBombonomiconEffect = NULL;
}
m_pBombonomiconBeam = ParticleProp()->Create( pszEffectName, PATTACH_ABSORIGIN_FOLLOW, INVALID_PARTICLE_ATTACHMENT, Vector(0,0,-10) );
if ( m_pBombonomiconBeam )
{
ParticleProp()->AddControlPoint( m_pBombonomiconBeam, 1, pParent, PATTACH_POINT_FOLLOW, "head", Vector(0,0,0) );
}
return true;
}
//-----------------------------------------------------------------------------
void C_MerasmusBombEffect::ClientThink( void )
{
if ( !GetMoveParent() || (m_flExpiresAt != PRM_PERMANENT && gpGlobals->curtime > m_flExpiresAt) )
{
if ( m_pBombonomiconBeam )
{
m_pBombonomiconBeam->StopEmission();
m_pBombonomiconBeam = NULL;
}
if ( m_pBombonomiconEffect )
{
m_pBombonomiconEffect->StopEmission();
m_pBombonomiconEffect = NULL;
}
}
BaseClass::ClientThink();
}
+64
View File
@@ -0,0 +1,64 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_PLAYERRELATIVEMODEL_H
#define C_PLAYERRELATIVEMODEL_H
#ifdef _WIN32
#pragma once
#endif
#include "c_tf_player.h"
#define PRM_PERMANENT -1
//
// Flags
#define PRM_SPIN_Z (1<<0)
//-----------------------------------------------------------------------------
// Purpose: A clientside, visual only model that's positioned relative to players
//-----------------------------------------------------------------------------
class C_PlayerRelativeModel : public C_BaseAnimating
{
DECLARE_CLASS( C_PlayerRelativeModel, C_BaseAnimating );
public:
static C_PlayerRelativeModel *Create( const char *pszModelName, C_BaseEntity *pParent, Vector vecOffset, QAngle angleOffset, float flAnimSpeed, float flLifetime = 0.2, int iFlags = 0 );
bool Initialize( const char *pszModelName, C_BaseEntity *pParent, Vector vecOffset, QAngle angleOffset, float flAnimSpeed, float flLifetime, int iFlags );
void SetLifetime( float flLifetime );
void ClientThink( void );
protected:
float m_flExpiresAt;
int m_iFlags;
private:
float m_flRotateAt;
float m_flAnimateAt;
float m_flScale;
Vector m_vecOffsetPos;
QAngle m_angleOffset;
QAngle m_qOffsetRotation;
float m_flAnimSpeed;
};
//-----------------------------------------------------------------------------
// Purpose: A clientside, visual only model that's positioned relative to players
//-----------------------------------------------------------------------------
class C_MerasmusBombEffect : public C_PlayerRelativeModel
{
DECLARE_CLASS( C_MerasmusBombEffect, C_PlayerRelativeModel );
public:
static C_MerasmusBombEffect *Create( const char *pszModelName, C_TFPlayer *pParent, Vector vecOffset, QAngle angleOffset, float flAnimSpeed, float flLifetime = 0.2, int iFlags = 0 );
bool Initialize( const char *pszModelName, C_TFPlayer *pParent, Vector vecOffset, QAngle angleOffset, float flAnimSpeed, float flLifetime, int iFlags );
void ClientThink( void );
private:
CNewParticleEffect *m_pBombonomiconBeam;
CNewParticleEffect *m_pBombonomiconEffect;
};
#endif // C_PLAYERRELATIVEMODEL_H
+145
View File
@@ -0,0 +1,145 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "c_tf_ammo_pack.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef _DEBUG
static ConVar tf_debug_weapontrail( "tf_debug_weapontrail", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
#endif // _DEBUG
// Network table.
IMPLEMENT_CLIENTCLASS_DT( C_TFAmmoPack, DT_AmmoPack, CTFAmmoPack )
RecvPropVector( RECVINFO( m_vecInitialVelocity ) ),
RecvPropFloat( RECVINFO_NAME( m_angNetworkAngles[0], m_angRotation[0] ) ),
RecvPropFloat( RECVINFO_NAME( m_angNetworkAngles[1], m_angRotation[1] ) ),
RecvPropFloat( RECVINFO_NAME( m_angNetworkAngles[2], m_angRotation[2] ) ),
END_RECV_TABLE()
C_TFAmmoPack::C_TFAmmoPack( void )
{
m_nWorldModelIndex = 0;
}
C_TFAmmoPack::~C_TFAmmoPack( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
// Output : int
//-----------------------------------------------------------------------------
int C_TFAmmoPack::DrawModel( int flags )
{
#ifdef _DEBUG
// Debug!
if ( tf_debug_weapontrail.GetBool() )
{
Msg( "Ammo Pack:: Position: (%f %f %f), Velocity (%f %f %f)\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, GetAbsVelocity().x, GetAbsVelocity().y, GetAbsVelocity().z );
if ( debugoverlay )
{
debugoverlay->AddBoxOverlay( GetAbsOrigin(), Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), QAngle( 0, 0, 0 ), 255, 255, 0, 32, 5.0 );
}
}
#endif // _DEBUG
return BaseClass::DrawModel( flags );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_TFAmmoPack::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
#ifdef _DEBUG
// Debug!
if ( tf_debug_weapontrail.GetBool() )
{
Msg( "AbsOrigin (%f %f %f), LocalOrigin(%f %f %f)\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, GetLocalOrigin().x, GetLocalOrigin().y, GetLocalOrigin().z );
}
#endif // _DEBUG
if ( updateType == DATA_UPDATE_CREATED )
{
#ifdef _DEBUG
// Debug!
if ( tf_debug_weapontrail.GetBool() )
{
Msg( "Origin (%f %f %f)\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z );
}
#endif // _DEBUG
float flChangeTime = GetLastChangeTime( LATCH_SIMULATION_VAR );
Vector vecCurOrigin = GetLocalOrigin();
// Now stick our initial velocity into the interpolation history
CInterpolatedVar< Vector > &interpolator = GetOriginInterpolator();
interpolator.ClearHistory();
interpolator.AddToHead( flChangeTime - 0.15f, &vecCurOrigin, false );
m_nWorldModelIndex = m_nModelIndex;
}
}
int C_TFAmmoPack::GetWorldModelIndex( void )
{
if ( m_nWorldModelIndex == 0 )
return m_nModelIndex;
if ( GameRules() )
{
const char *pBaseName = modelinfo->GetModelName( modelinfo->GetModel( m_nWorldModelIndex ) );
const char *pTranslatedName = GameRules()->TranslateEffectForVisionFilter( "weapons", pBaseName );
if ( pTranslatedName != pBaseName )
{
return modelinfo->GetModelIndex( pTranslatedName );
}
}
return m_nWorldModelIndex;
}
void C_TFAmmoPack::ValidateModelIndex( void )
{
m_nModelIndex = GetWorldModelIndex();
BaseClass::ValidateModelIndex();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : currentTime -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_TFAmmoPack::Interpolate( float currentTime )
{
return BaseClass::Interpolate( currentTime );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pPlayer -
//-----------------------------------------------------------------------------
void C_TFAmmoPack::DisplayHintTo( C_BasePlayer *pPlayer )
{
C_TFPlayer *pTFPlayer = ToTFPlayer(pPlayer);
if ( pTFPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) )
{
pTFPlayer->HintMessage( HINT_ENGINEER_PICKUP_METAL );
}
else
{
pTFPlayer->HintMessage( HINT_PICKUP_AMMO );
}
}
+49
View File
@@ -0,0 +1,49 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_TF_AMMO_PACK_H
#define C_TF_AMMO_PACK_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseanimating.h"
#include "engine/ivdebugoverlay.h"
#include "c_tf_player.h"
#include "engine/IEngineSound.h"
#include "soundenvelope.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class C_TFAmmoPack : public C_BaseAnimating, public ITargetIDProvidesHint
{
DECLARE_CLASS( C_TFAmmoPack, C_BaseAnimating );
public:
DECLARE_CLIENTCLASS();
C_TFAmmoPack( void );
~C_TFAmmoPack( void );
virtual int DrawModel( int flags );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual int GetWorldModelIndex( void );
virtual void ValidateModelIndex( void );
virtual bool Interpolate( float currentTime );
// ITargetIDProvidesHint
public:
virtual void DisplayHintTo( C_BasePlayer *pPlayer );
private:
Vector m_vecInitialVelocity;
short m_nWorldModelIndex;
};
#endif // C_TF_AMMO_PACK_H
+98
View File
@@ -0,0 +1,98 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "c_tf_buff_banner.h"
#include "c_tf_player.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_NETWORKCLASS_ALIASED( TFBuffBanner, DT_TFBuffBanner )
BEGIN_NETWORK_TABLE( C_TFBuffBanner, DT_TFBuffBanner )
END_NETWORK_TABLE()
C_TFBuffBanner::C_TFBuffBanner()
{
m_flDetachTime = 0.f;
m_iBuffType = 0;
}
// -----------------------------------------------------------------------------
// Purpose:
// -----------------------------------------------------------------------------
void CTFBuffBanner::NotifyBoneAttached( C_BaseAnimating* attachTarget )
{
if ( m_hBuffItem )
{
if ( attachTarget != m_hBuffItem->GetOwner() )
{
// We are being moved to a corpse. Let our associated buff item know.
m_hBuffItem->SetBanner( NULL );
}
else
{
float flDuration = 10.f; // 10 is default
CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( attachTarget, flDuration, mod_buff_duration );
m_flDetachTime = gpGlobals->curtime + flDuration;
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
BaseClass::NotifyBoneAttached( attachTarget );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFBuffBanner::ClientThink( void )
{
BaseClass::ClientThink();
// DO THIS AFTER BASECLASS::CLIENTTHINK
if ( !m_pAttachedTo || !m_hBuffItem )
{
if ( m_hBuffItem )
{
m_hBuffItem->SetBanner( NULL );
}
Release();
return;
}
// Parachute's never expire
if ( m_iBuffType == EParachute )
{
m_flDetachTime = gpGlobals->curtime + 10.0f;
}
// Normal Banners
if ( m_pAttachedTo )
{
if ( gpGlobals->curtime > m_flDetachTime || !m_hBuffItem )
{
// Destroy us automatically after a period of time.
if ( m_hBuffItem )
{
m_hBuffItem->SetBanner( NULL );
}
Release();
}
else if ( m_pAttachedTo->IsEffectActive( EF_NODRAW ) && !IsEffectActive( EF_NODRAW ) )
{
AddEffects( EF_NODRAW );
UpdateVisibility();
}
else if ( !m_pAttachedTo->IsEffectActive( EF_NODRAW ) && IsEffectActive( EF_NODRAW ) && (m_pAttachedTo != C_BasePlayer::GetLocalPlayer()) )
{
RemoveEffects( EF_NODRAW );
UpdateVisibility();
}
}
}
+47
View File
@@ -0,0 +1,47 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_TF_BUFF_BANNER_H
#define C_TF_BUFF_BANNER_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_weapon_buff_item.h"
#define CTFBuffBanner C_TFBuffBanner
class C_TFBuffItem;
//-----------------------------------------------------------------------------
// Purpose: These need some base class derived from base animating that handles stuff like clientthink.
//-----------------------------------------------------------------------------
class C_TFBuffBanner : public CBaseAnimating
{
DECLARE_CLASS( C_TFBuffBanner, CBaseAnimating );
public:
DECLARE_NETWORKCLASS();
C_TFBuffBanner();
~C_TFBuffBanner() {}
void SetBuffItem( C_TFBuffItem* newBuffItem ) { m_hBuffItem = newBuffItem; }
virtual void NotifyBoneAttached( C_BaseAnimating* attachTarget );
virtual void ClientThink( void );
void SetBuffType( int iBuffType ) { m_iBuffType = iBuffType; }
private:
float m_flDetachTime;
int m_iBuffType;
CHandle<C_TFBuffItem> m_hBuffItem;
};
#endif // C_TF_BUFF_BANNER_H
+109
View File
@@ -0,0 +1,109 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: TF Death Calling card version based off the stickybolt code.
//=============================================================================//
#include "cbase.h"
#include "c_basetempentity.h"
#include "fx.h"
#include "decals.h"
#include "iefx.h"
#include "engine/IEngineSound.h"
#include "materialsystem/imaterialvar.h"
#include "IEffects.h"
#include "engine/IEngineTrace.h"
#include "vphysics/constraints.h"
#include "engine/ivmodelinfo.h"
#include "tempent.h"
#include "c_te_legacytempents.h"
#include "engine/ivdebugoverlay.h"
#include "c_te_effect_dispatch.h"
#include "c_tf_player.h"
#include "GameEventListener.h"
#include "tf_shareddefs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern IPhysicsSurfaceProps *physprops;
IPhysicsObject *GetWorldPhysObject( void );
extern CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel, const Vector &position,
const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, int nSkin, const breakablepropparams_t &params );
//-----------------------------------------------------------------------------
// Purpose: Creates a "Calling Card" prop at the victim's location
//-----------------------------------------------------------------------------
void CreateDeathCallingCard(
const Vector &vecOrigin,
const QAngle &vAngle,
const int iVictimIndex,
const int iShooterIndex,
const int iCallingCardIndex
) {
if ( iCallingCardIndex < 1 || iCallingCardIndex > TF_CALLING_CARD_MODEL_COUNT )
{
Warning( "Attempted to Call CreateDeathCallingCard With invalid index %d", iCallingCardIndex );
return;
}
const char* pszModelName = g_pszDeathCallingCardModels[iCallingCardIndex];
CTFPlayer *pVictim = ToTFPlayer( UTIL_PlayerByIndex( iVictimIndex ) );
if ( !pVictim )
return;
breakablepropparams_t breakParams( vecOrigin, vAngle, vec3_origin, vec3_origin );
breakParams.impactEnergyScale = 1.0f;
breakmodel_t breakModel;
Q_strncpy( breakModel.modelName, pszModelName, sizeof(breakModel.modelName) );
breakModel.health = 1;
breakModel.fadeTime = RandomFloat(7,10);
breakModel.fadeMinDist = 0.0f;
breakModel.fadeMaxDist = 0.0f;
breakModel.burstScale = 1.0f;
breakModel.collisionGroup = COLLISION_GROUP_DEBRIS;
breakModel.isRagdoll = false;
breakModel.isMotionDisabled = false;
breakModel.placementName[0] = 0;
breakModel.placementIsBone = false;
breakModel.offset = Vector( 0, 0, 50 );
CBaseEntity * pBreakModel = BreakModelCreateSingle(
pVictim,
&breakModel,
pVictim->GetAbsOrigin() + Vector( 0, 0, 50 ),
QAngle(0, vAngle.y, 0 ),
vec3_origin,
vec3_origin,
0,
breakParams
);
// Scale down the tombstones a bit
if ( pBreakModel )
{
CBaseAnimating *pAnim = dynamic_cast < CBaseAnimating * > ( pBreakModel );
if ( pAnim )
{
pAnim->SetModelScale( 0.9f );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void DeathCallingCard( const CEffectData &data )
{
CreateDeathCallingCard(
data.m_vOrigin,
data.m_vAngles,
data.m_nAttachmentIndex, // Victim
data.m_nHitBox, // iShooter
data.m_fFlags // Calling card Index
);
}
DECLARE_CLIENT_EFFECT( "TFDeathCallingCard", DeathCallingCard );
+388
View File
@@ -0,0 +1,388 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_tf_freeaccount.h"
#include "gcsdk/sharedobjectcache.h"
#include "tf_gcmessages.h"
#include "econ_game_account_client.h"
#include "tf_item_inventory.h"
#include "tf_player_info.h"
#include <vgui/ILocalize.h>
#include "confirm_dialog.h"
#include "econ/econ_notifications.h"
#include "select_player_dialog.h"
#include "gc_clientsystem.h"
//-----------------------------------------------------------------------------
class CSelectMostHelpfulFriendDialog : public CSelectPlayerDialog
{
public:
CSelectMostHelpfulFriendDialog( vgui::Panel *parent )
: CSelectPlayerDialog( parent )
, m_iNumFriends( 0 )
, m_bRefreshing( false )
{
}
virtual void UpdatePlayerList()
{
CSelectPlayerDialog::UpdatePlayerList();
vgui::Label *pLabelEmpty = dynamic_cast<vgui::Label*>( m_pStatePanels[m_iCurrentState]->FindChildByName("EmptyPlayerListLabel") );
vgui::Label *pLabelQuery = dynamic_cast<vgui::Label*>( m_pStatePanels[m_iCurrentState]->FindChildByName("QueryLabel") );
vgui::Label *pLabelRetrieving = dynamic_cast<vgui::Label*>( m_pStatePanels[m_iCurrentState]->FindChildByName("RetrievingPlayerListLabel") );
if ( pLabelEmpty )
{
pLabelEmpty->SetVisible( m_bRefreshing == false && pLabelEmpty->IsVisible() );
}
if ( pLabelQuery )
{
pLabelQuery->SetVisible( m_bRefreshing == false && pLabelQuery->IsVisible() );
}
if ( pLabelRetrieving )
{
pLabelRetrieving->SetVisible( m_bRefreshing );
}
}
virtual void Reset()
{
CSelectPlayerDialog::Reset();
m_iNumFriends = 0;
if ( m_bRefreshing == false )
{
RequestFriendsFromGC();
}
}
virtual void SetupSelectFriends()
{
m_PlayerInfoList.Purge();
if ( steamapicontext && steamapicontext->SteamFriends() )
{
// Get our game info so we can use that to test if our friends are connected to the same game as us
FriendGameInfo_t myGameInfo;
CSteamID mySteamID = steamapicontext->SteamUser()->GetSteamID();
steamapicontext->SteamFriends()->GetFriendGamePlayed( mySteamID, &myGameInfo );
int iFriends = steamapicontext->SteamFriends()->GetFriendCount( k_EFriendFlagImmediate );
if ( m_iNumFriends != iFriends )
{
RequestFriendsFromGC();
}
else
{
m_PlayerInfoList = m_FriendsWhoOwnTF2;
}
}
UpdatePlayerList();
}
virtual void OnSelectPlayer( const CSteamID &steamID )
{
GCSDK::CProtoBufMsg<CMsgTFFreeTrialChooseMostHelpfulFriend> msg( k_EMsgGCFreeTrial_ChooseMostHelpfulFriend );
msg.Body().set_account_id_friend( steamID.GetAccountID() );
GCClientSystem()->BSendMessage( msg );
}
void OnTF2FriendsReceived( GCSDK::CProtoBufMsg<CMsgTFRequestTF2FriendsResponse> &msg )
{
// populate the list of friends who own TF2
m_bRefreshing = false;
m_FriendsWhoOwnTF2.Purge();
for ( int i = 0; i < msg.Body().account_ids_size(); ++i )
{
uint32 unAccountID = msg.Body().account_ids( i );
FOR_EACH_VEC( m_EntireFriendsList, j )
{
partner_info_t &info = m_EntireFriendsList[j];
if ( info.m_steamID.GetAccountID() == unAccountID )
{
int idx = m_FriendsWhoOwnTF2.AddToTail();
partner_info_t &infoCopy = m_FriendsWhoOwnTF2[idx];
infoCopy = info;
break;
}
}
}
// update UI
if ( m_iCurrentState == SPDS_SELECTING_FROM_FRIENDS )
{
m_PlayerInfoList = m_FriendsWhoOwnTF2;
UpdatePlayerList();
}
}
protected:
virtual const char *GetResFile() { return "resource/ui/SelectMostHelpfulFriendDialog.res"; }
void RequestFriendsFromGC()
{
// send a message to the GC requesting that it validate which friends own TF2
m_bRefreshing = true;
m_EntireFriendsList.Purge();
m_FriendsWhoOwnTF2.Purge();
if ( steamapicontext && steamapicontext->SteamFriends() )
{
// Get our game info so we can use that to test if our friends are connected to the same game as us
FriendGameInfo_t myGameInfo;
CSteamID mySteamID = steamapicontext->SteamUser()->GetSteamID();
steamapicontext->SteamFriends()->GetFriendGamePlayed( mySteamID, &myGameInfo );
m_iNumFriends = steamapicontext->SteamFriends()->GetFriendCount( k_EFriendFlagImmediate );
if ( m_iNumFriends > 0 )
{
GCSDK::CProtoBufMsg<CMsgTFRequestTF2Friends> msg( k_EMsgGCRequestTF2Friends );
for ( int i = 0; i < m_iNumFriends; i++ )
{
CSteamID friendSteamID = steamapicontext->SteamFriends()->GetFriendByIndex( i, k_EFriendFlagImmediate );
const char *pszName = steamapicontext->SteamFriends()->GetFriendPersonaName( friendSteamID );
int idx = m_EntireFriendsList.AddToTail();
partner_info_t &info = m_EntireFriendsList[idx];
info.m_steamID = friendSteamID;
info.m_name = pszName;
msg.Body().add_account_ids( friendSteamID.GetAccountID() );
}
GCClientSystem()->BSendMessage( msg );
}
else
{
m_bRefreshing = false;
}
}
}
// data
bool m_bRefreshing;
int m_iNumFriends;
CUtlVector<partner_info_t> m_EntireFriendsList;
CUtlVector<partner_info_t> m_FriendsWhoOwnTF2;
};
static vgui::DHANDLE<CSelectMostHelpfulFriendDialog> g_hSelectMostHelpfulFriendDialog;
/**
* Notification that the player should choose their most helpful friend.
*/
class CSelectHelpfulFriendNotification : public CEconNotification
{
public:
CSelectHelpfulFriendNotification() {}
virtual void Accept()
{
OpenSelectMostHelpfulFriendDialog( NULL );
MarkForDeletion();
}
virtual void Decline()
{
MarkForDeletion();
}
virtual EType NotificationType() { return eType_AcceptDecline; }
void Trigger()
{
OpenSelectMostHelpfulFriendDialog( NULL );
MarkForDeletion();
}
static bool RemoveOtherNotifications( CEconNotification *pNotification )
{
return dynamic_cast< CSelectHelpfulFriendNotification* >( pNotification ) != NULL;
}
};
class CWasThankedBySomeoneNotification : public CEconNotification
{
public:
CWasThankedBySomeoneNotification( const CSteamID& steamID )
{
SetText( "#TF_Trial_Alert_ThankedBySomeone" );
SetLifetime( 30.0f );
{
extern void GetPlayerNameBySteamID( const CSteamID &steamID, OUT_Z_CAP(maxLenInChars) char *pDestBuffer, int maxLenInChars );
wchar_t wszPlayerName[ MAX_PLAYER_NAME_LENGTH ];
char szPlayerName[ MAX_PLAYER_NAME_LENGTH ];
GetPlayerNameBySteamID( steamID, szPlayerName, sizeof( szPlayerName ) );
g_pVGuiLocalize->ConvertANSIToUnicode( szPlayerName, wszPlayerName, sizeof( wszPlayerName ) );
AddStringToken( "thanker", wszPlayerName );
}
}
static bool RemoveOtherNotifications( CEconNotification *pNotification )
{
return dynamic_cast< CWasThankedBySomeoneNotification* >( pNotification ) != NULL;
}
};
#ifdef _DEBUG
CON_COMMAND( cl_free_trial_select_friend, "Bring up dialog to select most helpful friend" )
{
OpenSelectMostHelpfulFriendDialog( NULL );
}
CON_COMMAND( cl_thanks_test, "Tests the thanked ui notification." )
{
if ( steamapicontext == NULL || steamapicontext->SteamUser() == NULL )
return;
CSteamID steamID = steamapicontext->SteamUser()->GetSteamID();
NotificationQueue_Add( new CWasThankedBySomeoneNotification( steamID ) );
}
#endif
class CGCRequestTF2FriendsResponse : public GCSDK::CGCClientJob
{
public:
CGCRequestTF2FriendsResponse( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
{
GCSDK::CProtoBufMsg<CMsgTFRequestTF2FriendsResponse> msg( pNetPacket );
if ( g_hSelectMostHelpfulFriendDialog.Get() )
{
g_hSelectMostHelpfulFriendDialog->OnTF2FriendsReceived( msg );
}
return true;
}
};
GC_REG_JOB( GCSDK::CGCClient, CGCRequestTF2FriendsResponse, "CGCRequestTF2FriendsResponse", k_EMsgGCRequestTF2FriendsResponse, GCSDK::k_EServerTypeGCClient );
class CGCThankedBySomeone : public GCSDK::CGCClientJob
{
public:
CGCThankedBySomeone( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
{
GCSDK::CProtoBufMsg<CMsgTFThankedBySomeone> msg( pNetPacket );
NotificationQueue_Add( new CWasThankedBySomeoneNotification( CSteamID( msg.Body().thanker_steam_id() ) ) );
return true;
}
};
GC_REG_JOB( GCSDK::CGCClient, CGCThankedBySomeone, "CGCThankedBySomeone", k_EMsgGCFreeTrial_ThankedBySomeone, GCSDK::k_EServerTypeGCClient );
class CGCThankedSomeone : public GCSDK::CGCClientJob
{
public:
CGCThankedSomeone( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
{
ShowMessageBox( "#TF_Trial_ThankSuccess_Title", "#TF_Trial_ThankSuccess_Text", "#GameUI_OK" );
return true;
}
};
GC_REG_JOB( GCSDK::CGCClient, CGCThankedSomeone, "CGCThankedSomeone", k_EMsgGCFreeTrial_ThankedSomeone, GCSDK::k_EServerTypeGCClient );
class CGCFreeTrialConvertedToPremium : public GCSDK::CGCClientJob
{
public:
CGCFreeTrialConvertedToPremium( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
{
ShowMessageBox( "#TF_Trial_Converted_Title", "#TF_Trial_Converted_Text", "#GameUI_OK" );
return true;
}
};
GC_REG_JOB( GCSDK::CGCClient, CGCFreeTrialConvertedToPremium, "CGCFreeTrialConvertedToPremium", k_EMsgGCFreeTrial_ConvertedToPremium, GCSDK::k_EServerTypeGCClient );
//-----------------------------------------------------------------------------
// External API
#if _DEBUG
ConVar tf_forcetrialaccount( "tf_forcetrialaccount", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
#endif
#ifdef STAGING_ONLY
ConVar tf_thank_a_friend_enabled( "tf_thank_a_friend_enabled", "1", FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
#endif // STAGING_ONLY
bool IsFreeTrialAccount()
{
#if _DEBUG
if ( tf_forcetrialaccount.GetBool() )
return true;
#endif
if ( InventoryManager() && TFInventoryManager()->GetLocalTFInventory() && TFInventoryManager()->GetLocalTFInventory()->GetSOC() )
{
CEconGameAccountClient *pGameAccountClient = TFInventoryManager()->GetLocalTFInventory()->GetSOC()->GetSingleton<CEconGameAccountClient>();
if ( pGameAccountClient )
return pGameAccountClient->Obj().trial_account();
}
return false;
}
bool NeedsToChooseMostHelpfulFriend()
{
#ifdef STAGING_ONLY
if ( tf_thank_a_friend_enabled.GetBool() )
#endif // STAGING_ONLY
{
if ( InventoryManager() && TFInventoryManager()->GetLocalTFInventory() && TFInventoryManager()->GetLocalTFInventory()->GetSOC() )
{
CEconGameAccountClient *pGameAccountClient = TFInventoryManager()->GetLocalTFInventory()->GetSOC()->GetSingleton<CEconGameAccountClient>();
if ( pGameAccountClient )
{
return !pGameAccountClient->Obj().trial_account()
&& pGameAccountClient->Obj().need_to_choose_most_helpful_friend();
}
}
}
return false;
}
void NotifyNeedsToChooseMostHelpfulFriend()
{
// remove duplicates
NotificationQueue_Remove( &CSelectHelpfulFriendNotification::RemoveOtherNotifications );
// add new notification
CSelectHelpfulFriendNotification *pNotification = new CSelectHelpfulFriendNotification();
pNotification->SetText( "#TF_Trial_Alert_SelectFriend" );
pNotification->SetLifetime( 120.0f );
NotificationQueue_Add( pNotification );
}
CSelectPlayerDialog *OpenSelectMostHelpfulFriendDialog( vgui::Panel *pParent )
{
if (!g_hSelectMostHelpfulFriendDialog.Get())
{
g_hSelectMostHelpfulFriendDialog = vgui::SETUP_PANEL( new CSelectMostHelpfulFriendDialog( pParent ) );
}
g_hSelectMostHelpfulFriendDialog->InvalidateLayout( false, true );
g_hSelectMostHelpfulFriendDialog->Reset();
g_hSelectMostHelpfulFriendDialog->SetVisible( true );
g_hSelectMostHelpfulFriendDialog->MakePopup();
g_hSelectMostHelpfulFriendDialog->MoveToFront();
g_hSelectMostHelpfulFriendDialog->SetKeyBoardInputEnabled(true);
g_hSelectMostHelpfulFriendDialog->SetMouseInputEnabled(true);
TFModalStack()->PushModal( g_hSelectMostHelpfulFriendDialog );
return g_hSelectMostHelpfulFriendDialog;
}
+42
View File
@@ -0,0 +1,42 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface for the client to general GC API
//
// $NoKeywords: $
//=============================================================================
#ifndef C_TF_FREEACCOUNT_H
#define C_TF_FREEACCOUNT_H
#ifdef _WIN32
#pragma once
#endif
namespace vgui
{
class Panel;
};
class CSelectPlayerDialog;
/**
* @return true if the local player is using a free trial account, false otherwise
*/
bool IsFreeTrialAccount();
/**
* @return true if the local player needs to choose their most helpful friend, false otherwse
*/
bool NeedsToChooseMostHelpfulFriend();
/**
* Adds an alert that the player needs to choose their most helpful friend
*/
void NotifyNeedsToChooseMostHelpfulFriend();
/**
* Opens the dialog where the user can specify the friend that helped them the most
* @param pParent
* @return CSelectPlayerDialog
*/
CSelectPlayerDialog *OpenSelectMostHelpfulFriendDialog( vgui::Panel *pParent );
#endif // C_TF_FREEACCOUNT_H
+55
View File
@@ -0,0 +1,55 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "tf_fx_shared.h"
#include "c_basetempentity.h"
#include "tier0/vprof.h"
#include <cliententitylist.h>
class C_TEFireBullets : public C_BaseTempEntity
{
public:
DECLARE_CLASS( C_TEFireBullets, C_BaseTempEntity );
DECLARE_CLIENTCLASS();
virtual void PostDataUpdate( DataUpdateType_t updateType );
public:
int m_iPlayer;
Vector m_vecOrigin;
QAngle m_vecAngles;
int m_iWeaponID;
int m_iMode;
int m_iSeed;
float m_flSpread;
bool m_bCritical;
};
IMPLEMENT_CLIENTCLASS_EVENT( C_TEFireBullets, DT_TEFireBullets, CTEFireBullets );
BEGIN_RECV_TABLE_NOBASE( C_TEFireBullets, DT_TEFireBullets )
RecvPropVector( RECVINFO( m_vecOrigin ) ),
RecvPropFloat( RECVINFO( m_vecAngles[0] ) ),
RecvPropFloat( RECVINFO( m_vecAngles[1] ) ),
RecvPropInt( RECVINFO( m_iWeaponID ) ),
RecvPropInt( RECVINFO( m_iMode ) ),
RecvPropInt( RECVINFO( m_iSeed ) ),
RecvPropInt( RECVINFO( m_iPlayer ) ),
RecvPropFloat( RECVINFO( m_flSpread ) ),
RecvPropInt( RECVINFO( m_bCritical ) ),
END_RECV_TABLE()
void C_TEFireBullets::PostDataUpdate( DataUpdateType_t updateType )
{
VPROF( "C_TEFireBullets::PostDataUpdate" );
// Create the effect.
m_vecAngles.z = 0;
FX_FireBullets( NULL, m_iPlayer+1, m_vecOrigin, m_vecAngles, m_iWeaponID, m_iMode, m_iSeed, m_flSpread, -1, m_bCritical );
}
+13
View File
@@ -0,0 +1,13 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_TF_FX_H
#define C_TF_FX_H
#ifdef _WIN32
#pragma once
#endif
// See comments in tf_fx.h
const int kInvalidEHandleExplosion = MAX_EDICTS - 1;
const int kInvalidEHandleParticleEffect = MAX_EDICTS - 1;
#endif
File diff suppressed because it is too large Load Diff
+344
View File
@@ -0,0 +1,344 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_TF_GAMESTATS_H
#define C_TF_GAMESTATS_H
#ifdef _WIN32
#pragma once
#endif
#include "gamestats.h"
#include "tf_gamestats_shared.h"
#include "GameEventListener.h"
#include "c_tf_player.h"
#include "econ_store.h"
#include "store/store_panel.h"
class CTFPlayer;
struct TF_Gamestats_ClientSession_t
{
public:
TF_Gamestats_ClientSession_t();
private:
TF_Gamestats_ClientSession_t( const TF_Gamestats_ClientSession_t &stats ) {}
public:
void Reset();
struct SessionSummary_t
{
int iClassesPlayed;
int iMapsPlayed;
int iRoundsPlayed;
int iFavoriteClass;
int iFavoriteWeapon;
char szFavoriteMap[64];
int iKills;
int iDeaths;
int iSuicides;
int iAssists;
int iBuildingsBuilt;
int iBuildingsUpgraded;
int iBuildingsDestroyed;
int iHeadshots;
int iDominations;
int iRevenges;
int iInvulns;
int iTeleports;
int iDamageDone;
int iHealingDone;
int iCrits;
int iBackstabs;
int iAchievementsEarned;
};
SessionSummary_t m_Summary;
RTime32 m_SessionStart;
RTime32 m_FirstConnect;
int m_iMapsPlayed;
int m_iRoundsPlayed;
CBitVecT< CFixedBitVecBase<32> > m_ClassesPlayed;
};
struct TF_Gamestats_WeaponInfo_t
{
TF_Gamestats_WeaponInfo_t();
int weaponID;
int critsFired;
int shotsFired;
int shotsHit;
int shotsMissed;
int avgDamage;
int totalDamage;
int critHits;
float lastUpdateTime;
};
struct TF_Gamestats_AchievementEvent_t
{
TF_Gamestats_AchievementEvent_t( int in_achievementNum, const char* in_achievementID );
int eventTime;
int achievementNum;
const char* achievementID;
};
// Item event baseclass.
class TF_Gamestats_ItemEvent
{
public:
TF_Gamestats_ItemEvent( int in_eventNum, CEconItemView* in_item );
int eventNum;
int eventTime;
const char* eventID;
item_definition_index_t itemDefIndex;
itemid_t itemID;
const char* itemName;
char itemNameBuf[512];
bool bUseNameBuf;
const char* GetItemName()
{
if ( bUseNameBuf )
return itemNameBuf;
else
return itemName;
}
};
// Mann Co Catalog Usage Tracking
class TF_Gamestats_CatalogEvent : public TF_Gamestats_ItemEvent
{
public:
TF_Gamestats_CatalogEvent( int in_eventNum, CEconItemView* in_item, const char* in_filter );
const char* catalogFilter;
};
// Crafting System Usage Tracking
class TF_Gamestats_CraftingEvent : public TF_Gamestats_ItemEvent
{
public:
TF_Gamestats_CraftingEvent( int in_eventNum, CEconItemView* in_item, int in_numAttempts, int in_recipe );
int numAttempts;
int recipeFound;
};
// Store Usage Tracking
class TF_Gamestats_StoreEvent : public TF_Gamestats_ItemEvent
{
public:
TF_Gamestats_StoreEvent( int in_eventNum, CEconItemView* in_item,
const char* in_panelName, int in_classId, const cart_item_t* in_cartItem,
int in_checkoutAttempts, const char* in_storeError, int in_totalPrice, int in_currencyCode );
int classId;
int cartQuantity;
int cartItemCost;
int currencyCode;
int checkoutAttempt;
const char* storeError;
const char* panelName;
};
// General client-subjective item transaction tracking.
class TF_Gamestats_ItemTransactionEvent : public TF_Gamestats_ItemEvent
{
public:
TF_Gamestats_ItemTransactionEvent( int in_eventNum, CEconItemView* in_item, const char* in_reason, int in_quality );
const char* reason;
int itemQuality;
};
// Trade Usage Tracking
class TF_Gamestats_TradeEvent : public TF_Gamestats_ItemEvent
{
public:
TF_Gamestats_TradeEvent( int eventID, CEconItemView* item, bool localPlayerIsPartyA,
uint64 steamIDPartyA, uint64 steamIDPartyB, int iTradeRequests, int iTradeAttempts );
TF_Gamestats_TradeEvent( int eventID, uint64 steamIDRequested, int iTradeRequests, int iTradeAttempts );
TF_Gamestats_TradeEvent( int eventID, int iTradeRequests, const char* reason, int iTradeAttempts );
bool localPlayerPartyMatters;
bool localPlayerIsPartyA;
uint64 steamIDPartyA;
uint64 steamIDPartyB;
uint64 steamIDRequested;
int tradeRequests;
int tradeAttempts;
const char* reason;
};
// Matchmaking stats
struct TF_Gamestats_QuickPlay_t
{
// Status code for the search as a whole
enum eResult
{
k_Result_InternalError = -1,
k_Result_UserCancel = 10,
k_Result_NoServersFound = 20,
k_Result_NoServersMetCrtieria = 30,
//k_Result_NeverHeardBackFromGC = 40,
//k_Result_ReceivedZeroGCScores = 50,
k_Result_FinalPingFailed = 60,
k_Result_TriedToConnect = 100,
};
// Status codes for the servers
enum eServerStatus
{
k_Server_Invalid = -1, // we have a bug if this gets reported
k_Server_Ineligible = 10,
k_Server_Eligible = 20,
k_Server_RequestedScore = 30,
k_Server_Scored = 40,
k_Server_Pinged = 50,
k_Server_PingTimedOut = 60,
k_Server_PingIneligible = 70,
k_Server_Connected = 100,
};
TF_Gamestats_QuickPlay_t()
{
m_fUserHoursPlayed = -1.0f;
m_sUserGameMode;
m_fSearchTime = -1.0;
m_eResultCode = k_Result_UserCancel;
m_iExperimentGroup = 0;
}
float m_fUserHoursPlayed;
CUtlString m_sUserGameMode;
float m_fSearchTime;
eResult m_eResultCode;
int m_iExperimentGroup; // TF2ScoringNumbers_t::ExperimentGroup_t
struct Server_t
{
uint32 m_ip;
uint16 m_port;
bool m_bRegistered;
bool m_bValve;
bool m_bSecure;
bool m_bMapIsNewUserFriendly;
bool m_bMapIsQuickPlayOK;
int m_nPlayers;
int m_nMaxPlayers;
CUtlString m_sMapName;
CUtlString m_sTags;
int m_iPing;
float m_fScoreClient;
float m_fScoreServer;
float m_fScoreGC;
eServerStatus m_eStatus;
};
CUtlVector<Server_t> m_vecServers;
};
//=============================================================================
//
// TF Game Stats Class
//
class C_CTFGameStats : public CBaseGameStats, public CGameEventListener, public CAutoGameSystem
{
public:
// Constructor/Destructor.
C_CTFGameStats( void );
~C_CTFGameStats( void );
virtual void Clear( void );
virtual bool UseOldFormat() { return false; }
virtual bool AddDataForSend( KeyValues *pKV, StatSendType_t sendType );
virtual bool Init();
virtual void Shutdown();
void ResetRoundStats();
void ClientDisconnect( int iReason );
// Events.
virtual void Event_LevelInit( void );
virtual void Event_LevelShutdown( float flElapsed );
virtual void Event_RoundActive();
virtual void Event_RoundEnd( int winningTeam, float roundTime, int fullRound );
virtual void Event_PlayerChangeClass( int userid, int classid );
virtual void Event_AchievementProgress( int achievementID, const char* achievementName );
virtual void Event_PlayerHurt( IGameEvent* event /*player_hurt*/ );
virtual void Event_PlayerFiredWeapon( C_TFPlayer *pPlayer, bool bCritical );
virtual void Event_Catalog( int eventID, const char* filter=NULL, CEconItemView* item=NULL );
virtual void Event_Crafting( int eventID, CEconItemView* item=NULL, int numAttempts=0, int recipeFound=0 );
virtual void Event_Store( int eventID, CEconItemView* item=NULL, const char* panelName=NULL,
int classId=0, const cart_item_t* in_cartItem=NULL, int in_checkoutAttempts=0, const char* storeError=NULL, int in_totalPrice=0, int in_currencyCode=0 );
virtual void Event_ItemTransaction( int eventID, CEconItemView* item, const char* pszReason=NULL, int iQuality=0 );
virtual void Event_Trading( int eventID, CEconItemView* item=NULL, bool localPlayerIsPartyA=false,
uint64 steamIDPartyA=0, uint64 steamIDPartyB=0, int iTradeRequests=0, int iTradeAttempts=0 );
virtual void Event_Trading( int eventID, uint64 steamIDRequested=0, int iTradeRequests=0, int iTradeAttempts=0 );
virtual void Event_Trading( int eventID, int iTradeRequests=0, const char* reason=NULL, int iTradeAttempts=0 );
virtual void Event_Trading( TF_Gamestats_TradeEvent& event );
virtual void FireGameEvent( IGameEvent * event );
void SW_GameStats_WriteClientSessionSummary();
void SW_GameStats_WriteClientWeapons();
void SW_GameStats_WriteClientRound( int winningTeam, int fullRound, int endReason );
void SW_GameStats_WriteClientMap();
void SetExperimentValue( uint64 experimentValue ) { m_ulExperimentValue = experimentValue; }
static void ImmediateWriteInterfaceEvent( const char *pszEventType, const char *pszEventDesc );
/*
void SW_GameStats_WriteClientAchievements();
void SW_GameStats_WriteClientCatalogEvents();
void SW_GameStats_WriteClientCraftingEvents();
void SW_GameStats_WriteClientStoreEvents();
void SW_GameStats_WriteClientItemTransactionEvents();
void SW_GameStats_WriteClientTradeEvents();
*/
void QuickplayResults( const TF_Gamestats_QuickPlay_t &info );
private:
char m_szCountryCode[64];
char m_szAudioLanguage[64];
char m_szTextLanguage[64];
TF_Gamestats_ClientSession_t m_currentSession;
TF_Gamestats_RoundStats_t m_currentRound;
TF_Gamestats_LevelStats_t m_currentMap;
CUtlVector<TF_Gamestats_AchievementEvent_t> m_vecAchievementEvents;
CUtlMap<int, TF_Gamestats_WeaponInfo_t> m_mapWeaponInfo;
CUtlVector<TF_Gamestats_CatalogEvent> m_vecCatalogEvents;
CUtlVector<TF_Gamestats_CraftingEvent> m_vecCraftingEvents;
CUtlVector<TF_Gamestats_StoreEvent> m_vecStoreEvents;
CUtlVector<TF_Gamestats_ItemTransactionEvent> m_vecItemTransactionEvents;
CUtlVector<TF_Gamestats_TradeEvent> m_vecTradeEvents;
uint64 m_ulExperimentValue;
bool m_bRoundActive;
bool m_bIsDisconnecting;
};
extern C_CTFGameStats C_CTF_GameStats;
#endif // C_TF_GAMESTATS_H
+89
View File
@@ -0,0 +1,89 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
class C_TFGlow : public C_BaseEntity
{
public:
DECLARE_CLASS( C_TFGlow, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_TFGlow();
virtual ~C_TFGlow();
virtual void PostDataUpdate( DataUpdateType_t updateType ) OVERRIDE;
private:
void CreateGlow();
CGlowObject *pGlow;
CNetworkVar( int, m_iMode );
CNetworkVar( color32, m_glowColor );
CNetworkVar( bool, m_bDisabled );
CNetworkHandle( CBaseEntity, m_hTarget );
};
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_TFGlow, DT_TFGlow, CTFGlow )
RecvPropInt(RECVINFO( m_iMode ) ),
RecvPropInt( RECVINFO( m_glowColor ), 0, RecvProxy_IntToColor32 ),
RecvPropBool( RECVINFO( m_bDisabled ) ),
RecvPropEHandle( RECVINFO( m_hTarget ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_TFGlow::C_TFGlow()
{
}
//-----------------------------------------------------------------------------
C_TFGlow::~C_TFGlow()
{
delete pGlow;
}
//-----------------------------------------------------------------------------
void C_TFGlow::CreateGlow()
{
if ( pGlow )
{
delete pGlow;
pGlow = nullptr;
}
if ( m_bDisabled || !m_hTarget )
{
return;
}
Vector cvec;
color32 c = m_glowColor.Get();
cvec[0] = c.r * (1.0f/255.0f);
cvec[1] = c.g * (1.0f/255.0f);
cvec[2] = c.b * (1.0f/255.0f);
float a = c.a * (1.0f/255.0f);
int iMode = m_iMode.Get();
bool bDrawWhenOccluded = ( iMode == 0 ) || ( iMode == 1 );
bool bDrawWhenVisible = ( iMode == 0 ) || ( iMode == 2 );
Assert( bDrawWhenOccluded || bDrawWhenVisible );
pGlow = new CGlowObject( m_hTarget, cvec, a, bDrawWhenOccluded, bDrawWhenVisible );
}
//-----------------------------------------------------------------------------
void C_TFGlow::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
// this could avoid recreating the glow object on every update, but it
// wouldn't be noticeably more efficient and it would add a ton of code here.
CreateGlow();
}
+416
View File
@@ -0,0 +1,416 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "c_tf_player.h"
#include "collisionutils.h"
#include "econ_item_inventory.h"
#include "iclientmode.h"
#include "tf_gcmessages.h"
#include "tf_gamerules.h"
#include "econ_notifications.h"
#include "rtime.h"
#include "achievementmgr.h"
#include "baseachievement.h"
#include "achievements_tf.h"
#include "gc_clientsystem.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
EHalloweenMap GetHalloweenMap()
{
if ( FStrEq( engine->GetLevelName(), "maps/cp_manor_event.bsp" ) )
return kHalloweenMap_MannManor;
if ( FStrEq( engine->GetLevelName(), "maps/koth_viaduct_event.bsp" ) )
return kHalloweenMap_Viaduct;
if ( FStrEq( engine->GetLevelName(), "maps/koth_lakeside_event.bsp" ) )
return kHalloweenMap_Lakeside;
if ( FStrEq( engine->GetLevelName(), "maps/plr_hightower_event.bsp" ) )
return kHalloweenMap_Hightower;
return kHalloweenMapCount;
}
//-----------------------------------------------------------------------------
// Created when the GC decides to give out an item.
// A player must intersect the item to claim it.
//-----------------------------------------------------------------------------
#define HALLOWEEN_ITEM_TIME_TO_READY 10.0f
class C_HalloweenItemPickup : public CBaseAnimating
{
DECLARE_CLASS( C_HalloweenItemPickup, CBaseAnimating );
public:
C_HalloweenItemPickup()
: m_bReadyForPickup( false )
, m_bClaimed( false )
, m_flTimeToReady( 0.0f )
{
AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
}
virtual ~C_HalloweenItemPickup()
{
}
bool Initialize()
{
const char *pszModelName = "models/props_halloween/halloween_gift.mdl";
SetModelName( AllocPooledString( pszModelName ) );
if ( InitializeAsClientEntity( STRING(GetModelName()), RENDER_GROUP_OPAQUE_ENTITY ) == false )
return false;
const model_t *mod = GetModel();
if ( mod )
{
Vector mins, maxs;
modelinfo->GetModelBounds( mod, mins, maxs );
SetCollisionBounds( mins, maxs );
}
Spawn();
// initialize as translucent
float alpha = 0.0f;
SetRenderMode( kRenderTransTexture );
SetRenderColorA( alpha * 256 );
m_flTimeToReady = gpGlobals->realtime + HALLOWEEN_ITEM_TIME_TO_READY;
UpdatePartitionListEntry();
SetBlocksLOS( false ); // this should be a small object
// Set up shadows; do it here so that objects can change shadowcasting state
CreateShadow();
UpdateVisibility();
SetNextClientThink( CLIENT_THINK_ALWAYS );
return true;
}
virtual void Spawn()
{
Precache();
BaseClass::Spawn();
SetSolid( SOLID_NONE );
AddSolidFlags( FSOLID_NOT_SOLID );
SetMoveType( MOVETYPE_NONE );
}
virtual void ClientThink()
{
if ( m_bReadyForPickup )
{
ClientThink_Active();
return;
}
float flTimeDelta = m_flTimeToReady - gpGlobals->realtime;
if ( flTimeDelta < 0 )
{
m_bReadyForPickup = true;
ParticleProp()->Create( "halloween_pickup_active", PATTACH_ABSORIGIN_FOLLOW );
SetRenderMode( kRenderNormal );
}
else
{
float alpha = 0.75f * ( ( HALLOWEEN_ITEM_TIME_TO_READY - flTimeDelta ) / HALLOWEEN_ITEM_TIME_TO_READY );
SetRenderColorA( alpha * 256 );
}
}
void ClientThink_Active( void )
{
Vector vWorldMins = WorldAlignMins();
Vector vWorldMaxs = WorldAlignMaxs();
Vector vBoxMin1 = GetAbsOrigin() + vWorldMins;
Vector vBoxMax1 = GetAbsOrigin() + vWorldMaxs;
float flBestDistance2 = 0.0f;
CSteamID bestSteamID;
bool bBestHasNoclip = false;
#define CLIENT_HALLOWEEN_LOGIC_ENABLE_LOCAL_PLAYER_ONLY 1
#if !CLIENT_HALLOWEEN_LOGIC_ENABLE_LOCAL_PLAYER_ONLY
for( int iPlayerIndex = 1 ; iPlayerIndex <= MAX_PLAYERS; iPlayerIndex++ )
{
C_TFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerIndex ) );
#else
do
{
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
#endif
CSteamID steamID;
if ( pPlayer == NULL || pPlayer->IsBot() == true || pPlayer->GetSteamID( &steamID ) == false ||
( pPlayer->GetTeamNumber() != TF_TEAM_RED && pPlayer->GetTeamNumber() != TF_TEAM_BLUE ) ||
pPlayer->IsAlive() == false ||
pPlayer->GetObserverMode() != OBS_MODE_NONE )
{
continue;
}
Vector vPlayerMins = pPlayer->GetAbsOrigin() + pPlayer->WorldAlignMins();
Vector vPlayerMaxs = pPlayer->GetAbsOrigin() + pPlayer->WorldAlignMaxs();
bool bIntersecting = IsBoxIntersectingBox( vBoxMin1, vBoxMax1, vPlayerMins, vPlayerMaxs );
float flDistance2 = ( pPlayer->GetAbsOrigin(), GetAbsOrigin() ).LengthSqr();
if ( bIntersecting && ( bestSteamID.GetAccountID() == 0 || flDistance2 < flBestDistance2 ) )
{
bestSteamID = steamID;
bBestHasNoclip = pPlayer->GetMoveType() == MOVETYPE_NOCLIP;
flBestDistance2 = flDistance2;
}
}
#if CLIENT_HALLOWEEN_LOGIC_ENABLE_LOCAL_PLAYER_ONLY
while ( false );
#endif
if ( bestSteamID.GetAccountID() != 0 )
{
GCSDK::CProtoBufMsg<CMsgGC_Halloween_GrantItem> msg( k_EMsgGC_Halloween_GrantItem );
msg.Body().set_recipient_account_id( bestSteamID.GetAccountID() );
msg.Body().set_level_id( GetHalloweenMap() );
msg.Body().set_flagged( bBestHasNoclip );
GCClientSystem()->BSendMessage( msg );
OnClaimed( true );
return;
}
SetNextClientThink( gpGlobals->curtime + 0.33f );
}
void OnClaimed( bool bPlayAudio )
{
if ( m_bClaimed )
return;
m_bClaimed = true;
// stop thinking and remove sparkle...
ParticleProp()->StopParticlesNamed( "halloween_pickup_active", true );
SetNextClientThink( CLIENT_THINK_NEVER );
// throw up bday confetti
DispatchParticleEffect( "halloween_gift_pickup", GetAbsOrigin(), vec3_angle );
if ( bPlayAudio )
{
C_BaseEntity::EmitSound( "Game.HappyBirthday" );
}
SetRenderMode( kRenderNone );
UpdateVisibility();
}
bool m_bReadyForPickup;
bool m_bClaimed;
float m_flTimeToReady;
};
LINK_ENTITY_TO_CLASS( tf_halloween_item_pickup, C_HalloweenItemPickup );
PRECACHE_REGISTER( tf_halloween_item_pickup );
static EHANDLE gHalloweenPickup;
#ifdef _DEBUG
CON_COMMAND( cl_halloween_test_cheating, "Test cheating the halloween pickup" )
{
GCSDK::CProtoBufMsg< CMsgGC_Halloween_GrantItem > msg( k_EMsgGC_Halloween_GrantItem );
msg.Body().set_recipient_account_id( steamapicontext->SteamUser()->GetSteamID().GetAccountID() );
GCClientSystem()->BSendMessage( msg );
}
CON_COMMAND( cl_halloween_test_spawn_pickup, "Test spawning the pickup item" )
{
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( pLocalPlayer == NULL )
return;
// Now create the pickup item
C_HalloweenItemPickup *pEntity = new C_HalloweenItemPickup();
if ( !pEntity )
return;
Vector vecTargetPoint;
trace_t tr;
Vector forward;
pLocalPlayer->EyeVectors( &forward );
UTIL_TraceLine( pLocalPlayer->EyePosition(),
pLocalPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_NPCSOLID,
pLocalPlayer, COLLISION_GROUP_NONE, &tr );
if ( tr.fraction != 1.0 )
{
vecTargetPoint = tr.endpos;
}
pEntity->SetAbsOrigin( vecTargetPoint );
if ( !pEntity->Initialize() )
{
pEntity->Release();
}
else
{
if ( gHalloweenPickup.Get() )
gHalloweenPickup->Release();
gHalloweenPickup = pEntity;
}
}
#endif
//-----------------------------------------------------------------------------
// GC has decided to drop a Halloween item
//-----------------------------------------------------------------------------
//class CGCHalloween_ReservedItem : public GCSDK::CGCClientJob
//{
//public:
// CGCHalloween_ReservedItem( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
//
// virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
// {
// GCSDK::CProtoBufMsg<CMsgGC_Halloween_ReservedItem> msg( pNetPacket );
//
// // Figure out which level we're on so we know how to handle notifications, etc.
// EHalloweenMap eMap = GetHalloweenMap();
// if ( eMap == kHalloweenMapCount )
// return true;
//
// // Sanity-check the message contents from the GC.
// if ( msg.Body().x_size() != msg.Body().y_size() || msg.Body().y_size() != msg.Body().z_size() )
// return true;
//
// if ( msg.Body().x_size() <= eMap )
// return true;
//
// // Don't spawn gifts during startup.
// if ( TFGameRules() == NULL
// || TFGameRules()->State_Get() != GR_STATE_RND_RUNNING
// || TFGameRules()->InSetup()
// || TFGameRules()->IsInWaitingForPlayers()
// || TFGameRules()->ArePlayersInHell() ) // Dont spawn gifts if players are in 2013 Hell
// return true;
//
// C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
// if ( pLocalPlayer == NULL )
// return true;
//
// // If we don't already know about this gift pickup, create one.
// if ( gHalloweenPickup.Get() == NULL )
// {
// // Now create the pickup item
// C_HalloweenItemPickup *pEntity = new C_HalloweenItemPickup();
// if ( !pEntity )
// return true;
//
// Vector position( msg.Body().x( eMap ), msg.Body().y( eMap ), msg.Body().z( eMap ) );
// pEntity->SetAbsOrigin( position );
// if ( !pEntity->Initialize() )
// {
// pEntity->Release();
// }
// else
// {
// gHalloweenPickup = pEntity;
// }
// }
//
// // Regardless of whether we created a new gift or whether this was a new notification about an old gift,
// // display a UI notification for the user.
// CEconNotification *pNotification = new CEconNotification();
// pNotification->SetText( "#TF_HalloweenItem_Reserved" );
// pNotification->SetLifetime( 15.0f );
// pNotification->SetSoundFilename( "ui/halloween_loot_spawn.wav" );
// NotificationQueue_Add( pNotification );
//
// return true;
// }
//};
//GC_REG_JOB( GCSDK::CGCClient, CGCHalloween_ReservedItem, "CGCHalloween_ReservedItem", k_EMsgGC_Halloween_ReservedItem, GCSDK::k_EServerTypeGCClient );
//-----------------------------------------------------------------------------
// GC gave out the Halloween item to a player
//-----------------------------------------------------------------------------
//class CGCHalloween_GrantedItemResponse : public GCSDK::CGCClientJob
//{
//public:
// CGCHalloween_GrantedItemResponse( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
//
// virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
// {
// GCSDK::CProtoBufMsg<CMsgGC_Halloween_GrantItemResponse> msg( pNetPacket );
//
// // which Steam universe are we in?
// EUniverse eUniverse = steamapicontext && steamapicontext->SteamUtils()
// ? steamapicontext->SteamUtils()->GetConnectedUniverse()
// : k_EUniverseInvalid;
//
// CSteamID steamIDRecipient( msg.Body().recipient_account_id(), eUniverse, k_EAccountTypeIndividual );
// bool bIsValidRecipient = steamIDRecipient.IsValid();
//
// if ( gHalloweenPickup.Get() != NULL )
// {
// assert_cast<C_HalloweenItemPickup *>( gHalloweenPickup.Get() )->OnClaimed( bIsValidRecipient );
// gHalloweenPickup->Release();
// gHalloweenPickup = NULL;
// }
//
// // don't do any work if we're not on a Halloween map
// EHalloweenMap eMap = GetHalloweenMap();
// if ( eMap == kHalloweenMapCount )
// return true;
//
// // add alert
// const char* pPlayerName = InventoryManager()->PersonaName_Get( steamIDRecipient.GetAccountID() );
// wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH] = L"";
// if ( pPlayerName != NULL && FStrEq( pPlayerName, "" ) == false )
// {
// g_pVGuiLocalize->ConvertANSIToUnicode( pPlayerName, wszPlayerName, sizeof(wszPlayerName) );
// }
// CEconNotification *pNotification = new CEconNotification();
// pNotification->SetLifetime( 15.0f );
//
// if ( bIsValidRecipient )
// {
// pNotification->SetText( "#TF_HalloweenItem_Granted" );
// pNotification->AddStringToken( "recipient", wszPlayerName );
// pNotification->SetSteamID( steamIDRecipient );
// pNotification->SetSoundFilename( "ui/halloween_loot_found.wav" );
// }
// else
// {
// pNotification->SetText( "#TF_HalloweenItem_GrantPickupFail" );
// // pNotification->SetSoundFilename( "coach/coach_student_died.wav" );
// }
//
// NotificationQueue_Add( pNotification );
//
// // is this the local player? award the achievement...
// if ( steamapicontext && steamapicontext->SteamUser() )
// {
// CSteamID localSteamID = steamapicontext->SteamUser()->GetSteamID();
// if ( steamIDRecipient == localSteamID )
// {
// g_AchievementMgrTF.OnAchievementEvent( ACHIEVEMENT_TF_HALLOWEEN_COLLECT_GOODY_BAG );
// }
// }
//
// return true;
// }
//};
//GC_REG_JOB( GCSDK::CGCClient, CGCHalloween_GrantedItemResponse, "CGCHalloween_GrantedItemResponse", k_EMsgGC_Halloween_GrantItemResponse, GCSDK::k_EServerTypeGCClient );
//-----------------------------------------------------------------------------
void CL_Halloween_LevelShutdown()
{
gHalloweenPickup = NULL;
}
+185
View File
@@ -0,0 +1,185 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
// NVNT haptic manager for tf2
#include "cbase.h"
#include "c_tf_haptics.h"
#include "c_tf_player.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// for full cloak effect
extern ConVar tf_teammate_max_invis;
C_TFHaptics::C_TFHaptics()
{
memset(this, 0, sizeof(C_TFHaptics));
}
void C_TFHaptics::Revert() {
if ( haptics )
{
if(wasBeingHealed)
{
haptics->ProcessHapticEvent(2,"Game","being_healed_stop");
}
if(wasHealing)
{
haptics->ProcessHapticEvent(2,"Game","healing_stop");
}
if(wasUber)
{
haptics->ProcessHapticEvent(2, "Game", "uber_stop");
}
if(wasFullyCloaked)
{
haptics->ProcessHapticEvent(2, "Game", "cloak_full_stop");
}
if(wasCloaked)
{
haptics->ProcessHapticEvent(2, "Game", "cloak_stop");
}
if(wasBurning)
{
haptics->ProcessHapticEvent(2, "Game", "burning_stop");
}
}
memset(this, 0, sizeof(C_TFHaptics));
if ( haptics )
{
haptics->LocalPlayerReset();
haptics->SetNavigationClass("on_foot");
}
}
void C_TFHaptics::HapticsThink(C_TFPlayer *player)
{
if ( !haptics )
return;
Assert(player!=C_TFPlayer::GetLocalPlayer());
{// being healed check
C_TFPlayer *pHealer = NULL;
float uberCharge = 0.0f;
player->GetHealer(&pHealer,&uberCharge);
if(pHealer)
{
if(!wasBeingHealedMedic && !healingDispenserCount)
isBeingHealed = true;
}
else
{
if(wasBeingHealedMedic && !healingDispenserCount)
isBeingHealed = false;
}
wasBeingHealedMedic = pHealer!=NULL;
if(isBeingHealed&&!wasBeingHealed&&haptics)
haptics->ProcessHapticEvent(2,"Game","being_healed_start");
else if(!isBeingHealed&&wasBeingHealed&&haptics)
haptics->ProcessHapticEvent(2,"Game","being_healed_stop");
wasBeingHealed = isBeingHealed;
}
{// healing check
C_BaseEntity *pHealTarget = player->MedicGetHealTarget();
if(pHealTarget)
{
if(!wasHealing&&haptics)
haptics->ProcessHapticEvent(2,"Game","healing_start");
}
else
{
if(wasHealing&&haptics)
haptics->ProcessHapticEvent(2,"Game","healing_stop");
}
wasHealing = pHealTarget!=NULL;
}
//uber
if(player->m_Shared.InCond( TF_COND_INVULNERABLE ) && !player->m_Shared.InCond( TF_COND_INVULNERABLE_WEARINGOFF ) )
{
if(!wasUber&&haptics)
{
haptics->ProcessHapticEvent(2, "Game", "uber_start");
}
}else{
if(wasUber&&haptics)
{
haptics->ProcessHapticEvent(2, "Game", "uber_stop");
}
}
//burning
if(player->m_Shared.InCond( TF_COND_BURNING ) )
{
if(!wasBurning&&haptics)
{
haptics->ProcessHapticEvent(2, "Game", "burning_start");
wasBurning = true;
}
}else{
if(wasBurning)
{
haptics->ProcessHapticEvent(2, "Game", "burning_stop");
wasBurning = false;
}
}
//cloak
// note: theres some weird stuff going on here.
float cloakLevel = player->GetPercentInvisible();
if(readyForCloak)
{
if(cloakLevel>0.0f)
{
if(!wasCloaked)
{
haptics->ProcessHapticEvent(2, "Game", "cloak_start");
wasCloaked = true;
}
if(!wasFullyCloaked)
{
if(cloakLevel >= tf_teammate_max_invis.GetFloat())
{
haptics->ProcessHapticEvent(2, "Game", "cloak_full_start");
wasFullyCloaked = true;
}
}
else
{
if(cloakLevel < tf_teammate_max_invis.GetFloat())
{
haptics->ProcessHapticEvent(2, "Game", "cloak_full_stop");
wasFullyCloaked = false;
}
}
}else{
if(wasFullyCloaked)
{
haptics->ProcessHapticEvent(2, "Game", "cloak_full_stop");
wasFullyCloaked = false;
}
if(wasCloaked)
{
haptics->ProcessHapticEvent(2, "Game", "cloak_stop");
wasCloaked = false;
}
}
}else{
if(skippedFirstCloak)
{
if(cloakLevel==0.0f)
readyForCloak = true;
}else{
if(cloakLevel!=0.0f)
{
skippedFirstCloak = true;
}
}
}
}
class C_TFHapticsInternal : public C_TFHaptics
{
public:
C_TFHapticsInternal() : C_TFHaptics() {};
};
static C_TFHapticsInternal tfInternalHaptics;
C_TFHaptics &tfHaptics = *((C_TFHaptics*)&tfInternalHaptics);
+34
View File
@@ -0,0 +1,34 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
// NVNT haptics for Team Fortress 2
#ifndef C_TF_HAPTICS_H
#define C_TF_HAPTICS_H
class C_TFPlayer;
#include "haptics/haptic_utils.h"
class C_TFHaptics {
protected:
C_TFHaptics();
public:
bool wasCloaked : 1;
bool wasFullyCloaked : 1;
bool wasUber : 1;
bool wasBurning :1;
bool wasHealing : 1;
bool isBeingHealed : 1;
bool wasBeingHealed : 1;
bool wasBeingHealedMedic : 1;
bool wasBeingTeleported :1;
bool skippedFirstCloak:1;
bool readyForCloak:1;
unsigned int healingDispenserCount:16;//short
void Revert();
// should only be local player!
void HapticsThink(C_TFPlayer *player);
};
extern C_TFHaptics &tfHaptics;
#endif // C_TF_HAPTICS_H
@@ -0,0 +1,9 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#include "cbase.h"
#include "c_tf_mvm_boss_progress_user.h"
IMPLEMENT_AUTO_LIST( ITFMvMBossProgressUserAutoList );
@@ -0,0 +1,18 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#ifndef C_TF_MVM_BOSS_HEALTH_USER_H
#define C_TF_MVM_BOSS_HEALTH_USER_H
DECLARE_AUTO_LIST( ITFMvMBossProgressUserAutoList );
class C_TFMvMBossProgressUser : public ITFMvMBossProgressUserAutoList
{
public:
virtual const char* GetBossProgressImageName() const { return NULL; }
virtual float GetBossStatusProgress() const { return 0.f; }
};
#endif // C_TF_MVM_BOSS_HEALTH_USER_H
+237
View File
@@ -0,0 +1,237 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "tf_notification.h"
#include "c_tf_notification.h"
#include "tf_gc_client.h"
#include "econ/econ_notifications.h"
///
/// Support message notification dialog
///
class CTFSupportNotificationDialog : public CTFMessageBoxDialog
{
DECLARE_CLASS_SIMPLE( CTFSupportNotificationDialog, CTFMessageBoxDialog );
public:
CTFSupportNotificationDialog( int iNotificationID, const char *pszSupportMessage )
: CTFMessageBoxDialog( NULL, pszSupportMessage, NULL, NULL, NULL )
, m_iNotificationID( iNotificationID )
, m_pConfirmDialog( NULL )
{
SetDialogVariable( "text", GetText() );
}
void CleanupConfirmDialog()
{
if ( m_pConfirmDialog )
{
m_pConfirmDialog->SetVisible( false );
m_pConfirmDialog->MarkForDeletion();
m_pConfirmDialog = NULL;
}
}
virtual ~CTFSupportNotificationDialog() {
CleanupConfirmDialog();
}
void ConfirmDialogCallback( bool bConfirmed )
{
CleanupConfirmDialog();
if ( bConfirmed )
{
// User acknowledged the message, tell the notification it can go away now
CClientNotification *pNotification = dynamic_cast< CClientNotification * >( NotificationQueue_Get( m_iNotificationID ) );
if ( pNotification )
{
pNotification->OnDialogAcknowledged();
}
BaseClass::OnCommand( "confirm" );
}
}
static void StaticConfirmDialogCallback( bool bConfirmed, void *pContext )
{
static_cast< CTFSupportNotificationDialog * >( pContext )->ConfirmDialogCallback( bConfirmed );
}
virtual void OnCommand( const char *command ) OVERRIDE
{
if ( FStrEq( "acknowledge", command ) )
{
// Confirm this, it's going away forever!
CleanupConfirmDialog();
m_pConfirmDialog = ShowConfirmDialog( "#DeleteConfirmDefault",
"#TF_Support_Message_Confirm_Acknowledge_Text",
"#TF_Support_Message_Acknowledge", "#Cancel",
&StaticConfirmDialogCallback );
m_pConfirmDialog->SetContext( this );
return;
}
else if ( FStrEq( "show_later", command ) )
{
// User selected "show this later" -- leave notification as is and close.
CleanupConfirmDialog();
BaseClass::OnCommand( "confirm" );
return;
}
BaseClass::OnCommand( command );
}
virtual const char *GetResFile() OVERRIDE
{
return "Resource/UI/SupportNotificationDialog.res";
}
private:
// Associated notification to clear
int m_iNotificationID;
CTFGenericConfirmDialog *m_pConfirmDialog;
};
///
/// The notification class
///
CClientNotification::CClientNotification()
{
m_pText = NULL;
m_flExpireTime = CRTime::RTime32TimeCur();
m_ulNotificationID = 0;
m_unAccountID = 0;
m_bSupportMessage = false;
}
CClientNotification::~CClientNotification()
{}
void CClientNotification::Update( const CTFNotification* notification )
{
// Custom type handling. For now only support message does anything special.
m_bSupportMessage = false;
switch ( notification->Obj().type() )
{
case CMsgGCNotification_NotificationType_NOTIFICATION_REPORTED_PLAYER_BANNED:
case CMsgGCNotification_NotificationType_NOTIFICATION_CUSTOM_STRING:
case CMsgGCNotification_NotificationType_NOTIFICATION_MM_BAN_DUE_TO_EXCESSIVE_REPORTS:
case CMsgGCNotification_NotificationType_NOTIFICATION_REPORTED_PLAYER_WAS_BANNED:
// All identical.
//
// Really, the other types could be used to avoid having to send a localization string down? Otherwise
// they're all just redundant with CUSTOM_STRING for now.
break;
case CMsgGCNotification_NotificationType_NOTIFICATION_SUPPORT_MESSAGE:
m_bSupportMessage = true;
break;
default:
Assert( !"Unhandled enum value" );
}
m_pText = NULL;
m_strText = notification->Obj().notification_string().c_str();
if ( m_bSupportMessage )
{
// Use generic notification, save actual notification contents for dialog
m_pText = "#TF_Support_Message_Notification";
}
else
{
// Just use our message
m_pText = m_strText.Get();
}
// 0 -> does not expire
RTime32 rtExpire = notification->Obj().expiration_time();
m_flExpireTime = rtExpire > 0 ? (float)rtExpire : FLT_MAX;
m_ulNotificationID = notification->Obj().notification_id();
m_unAccountID = notification->Obj().account_id();
}
void CClientNotification::GCAcknowledge() {
GTFGCClientSystem()->AcknowledgeNotification( m_unAccountID, m_ulNotificationID );
}
void CClientNotification::Deleted()
{
if ( m_bSupportMessage )
{
AssertMsg( !m_bSupportMessage,
"Support messages should only be able to be triggered, not deleted" );
return;
}
GCAcknowledge();
}
void CClientNotification::Expired()
{
// No action, we don't want de-sync'd client clock to acknowledge these incorrectly, GC will expire them on its end.
}
CClientNotification::EType CClientNotification::NotificationType()
{
// Support messages are "must trigger" type -- no delete action, user must click "view"
if ( m_bSupportMessage )
{
return eType_MustTrigger;
}
return eType_Basic;
}
bool CClientNotification::BHighPriority()
{
return m_bSupportMessage;
}
void CClientNotification::Trigger()
{
if ( !m_bSupportMessage )
{
AssertMsg( m_bSupportMessage,
"Don't expect to be trigger-able when not in support message mode" );
return;
}
CTFSupportNotificationDialog *pDialog = vgui::SETUP_PANEL( new CTFSupportNotificationDialog( GetID(), m_strText.Get() ) );
pDialog->Show();
}
void CClientNotification::OnDialogAcknowledged()
{
if ( !m_bSupportMessage )
{
AssertMsg( m_bSupportMessage,
"Don't expect to be getting callbacks from the support message dialog when not in support message mode" );
return;
}
GCAcknowledge();
MarkForDeletion();
}
//-----------------------------------------------------------------------------
// CAutobalanceVolunteerNotification
//-----------------------------------------------------------------------------
void CAutobalanceVolunteerNotification::SendResponse( bool bResponse )
{
KeyValues *kv = new KeyValues( "AutoBalanceVolunteerReply" );
kv->SetBool( "response", bResponse );
engine->ServerCmdKeyValues( kv );
MarkForDeletion();
}
+72
View File
@@ -0,0 +1,72 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface for the client to acknowledge/view notifications sent from the GC
//
// $NoKeywords: $
//=============================================================================
#ifndef C_TF_NOTIFICATIONS_H
#define C_TF_NOTIFICATIONS_H
#ifdef _WIN32
#pragma once
#endif
#include "econ/econ_notifications.h"
#include "tf_notification.h"
class CClientNotification : public CEconNotification
{
friend class CTFSupportNotificationDialog;
public:
CClientNotification();
virtual ~CClientNotification() OVERRIDE;
virtual EType NotificationType() OVERRIDE;
virtual void Deleted() OVERRIDE;
virtual void Expired() OVERRIDE;
virtual void Trigger() OVERRIDE;
virtual bool BHighPriority() OVERRIDE;
// Should show up on the main menu only -- these go away on dismissal
virtual bool BShowInGameElements() const OVERRIDE { return false; }
void Update( const CTFNotification* notification );
uint64 NotificationID() const { return m_ulNotificationID; }
private:
void OnDialogAcknowledged();
void GCAcknowledge();
uint64 m_ulNotificationID;
uint32 m_unAccountID;
// m_pText sometimes points to a static string we don't own, so this guy owns any text that we do.
CUtlString m_strText;
// Is this a support message? If so, the user must trigger the notification to view the message in a pop-up before they can dismiss.
bool m_bSupportMessage;
};
class CAutobalanceVolunteerNotification : public CEconNotification
{
public:
CAutobalanceVolunteerNotification() : CEconNotification() {}
virtual ~CAutobalanceVolunteerNotification() OVERRIDE {}
virtual bool BShowInGameElements() const OVERRIDE { return true; }
virtual EType NotificationType() OVERRIDE { return eType_AcceptDecline; }
virtual void Accept() OVERRIDE { SendResponse( true ); }
virtual void Decline() OVERRIDE { SendResponse( false ); }
virtual void Expired() OVERRIDE { Decline(); }
static bool IsNotificationType( CEconNotification *pNotification ) { return dynamic_cast<CAutobalanceVolunteerNotification *>( pNotification ) != NULL; }
private:
void SendResponse( bool bResponse );
};
#endif // C_TF_NOTIFICATIONS_H
+237
View File
@@ -0,0 +1,237 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Entity that propagates objective data
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "clientmode_tf.h"
#include "c_tf_objective_resource.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_TFObjectiveResource, DT_TFObjectiveResource, CTFObjectiveResource)
RecvPropInt( RECVINFO(m_nMannVsMachineMaxWaveCount) ),
RecvPropInt( RECVINFO(m_nMannVsMachineWaveCount) ),
RecvPropInt( RECVINFO(m_nMannVsMachineWaveEnemyCount) ),
RecvPropInt( RECVINFO(m_nMvMWorldMoney) ),
RecvPropFloat( RECVINFO( m_flMannVsMachineNextWaveTime ) ),
RecvPropBool( RECVINFO( m_bMannVsMachineBetweenWaves ) ),
RecvPropInt( RECVINFO(m_nFlagCarrierUpgradeLevel) ),
RecvPropFloat( RECVINFO( m_flMvMBaseBombUpgradeTime ) ),
RecvPropFloat( RECVINFO( m_flMvMNextBombUpgradeTime ) ),
RecvPropString( RECVINFO( m_iszMvMPopfileName ) ),
RecvPropInt( RECVINFO(m_iChallengeIndex) ),
RecvPropInt( RECVINFO(m_nMvMEventPopfileType) ),
RecvPropArray3( RECVINFO_ARRAY( m_nMannVsMachineWaveClassCounts ), RecvPropInt( RECVINFO( m_nMannVsMachineWaveClassCounts[0] ) ) ),
RecvPropArray( RecvPropString( RECVINFO( m_iszMannVsMachineWaveClassNames[0]) ), m_iszMannVsMachineWaveClassNames ),
RecvPropArray3( RECVINFO_ARRAY( m_nMannVsMachineWaveClassFlags ), RecvPropInt( RECVINFO( m_nMannVsMachineWaveClassFlags[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_nMannVsMachineWaveClassCounts2 ), RecvPropInt( RECVINFO( m_nMannVsMachineWaveClassCounts2[0] ) ) ),
RecvPropArray( RecvPropString( RECVINFO( m_iszMannVsMachineWaveClassNames2[0]) ), m_iszMannVsMachineWaveClassNames2 ),
RecvPropArray3( RECVINFO_ARRAY( m_nMannVsMachineWaveClassFlags2 ), RecvPropInt( RECVINFO( m_nMannVsMachineWaveClassFlags2[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_bMannVsMachineWaveClassActive ), RecvPropBool( RECVINFO( m_bMannVsMachineWaveClassActive[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_bMannVsMachineWaveClassActive2 ), RecvPropBool( RECVINFO( m_bMannVsMachineWaveClassActive2[0] ) ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFObjectiveResource::C_TFObjectiveResource()
{
PrecacheMaterial( "sprites/obj_icons/icon_obj_cap_blu" );
PrecacheMaterial( "sprites/obj_icons/icon_obj_cap_blu_up" );
PrecacheMaterial( "sprites/obj_icons/icon_obj_cap_red" );
PrecacheMaterial( "sprites/obj_icons/icon_obj_cap_red_up" );
PrecacheMaterial( "VGUI/flagtime_empty" );
PrecacheMaterial( "VGUI/flagtime_full" );
m_nMannVsMachineMaxWaveCount = 0;
m_nMannVsMachineWaveCount = 0;
m_nMannVsMachineWaveEnemyCount = 0;
m_nMvMWorldMoney = 0;
m_flMannVsMachineNextWaveTime = 0;
m_bMannVsMachineBetweenWaves = false;
m_nFlagCarrierUpgradeLevel = 0;
m_iChallengeIndex = -1;
m_nMvMEventPopfileType = MVM_EVENT_POPFILE_NONE;
memset( m_nMannVsMachineWaveClassCounts, 0, sizeof( m_nMannVsMachineWaveClassCounts ) );
memset( m_nMannVsMachineWaveClassCounts2, 0, sizeof( m_nMannVsMachineWaveClassCounts2 ) );
memset( m_nMannVsMachineWaveClassFlags, MVM_CLASS_FLAG_NONE, sizeof( m_nMannVsMachineWaveClassFlags ) );
memset( m_nMannVsMachineWaveClassFlags2, MVM_CLASS_FLAG_NONE, sizeof( m_nMannVsMachineWaveClassFlags2 ) );
memset( m_bMannVsMachineWaveClassActive, 0, sizeof( m_bMannVsMachineWaveClassActive ) );
memset( m_bMannVsMachineWaveClassActive2, 0, sizeof( m_bMannVsMachineWaveClassActive2 ) );
int i = 0;
for ( i = 0 ; i < ARRAYSIZE( m_iszMannVsMachineWaveClassNames ) ; ++i )
{
m_iszMannVsMachineWaveClassNames[ i ][ 0 ] = '\0';
}
for ( i = 0 ; i < ARRAYSIZE( m_iszMannVsMachineWaveClassNames2 ) ; ++i )
{
m_iszMannVsMachineWaveClassNames2[ i ][ 0 ] = '\0';
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFObjectiveResource::~C_TFObjectiveResource()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_TFObjectiveResource::GetGameSpecificCPCappingSwipe( int index_, int iCappingTeam )
{
Assert( index_ < m_iNumControlPoints );
Assert( iCappingTeam != TEAM_UNASSIGNED );
if ( iCappingTeam == TF_TEAM_RED )
return "sprites/obj_icons/icon_obj_cap_red";
return "sprites/obj_icons/icon_obj_cap_blu";
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_TFObjectiveResource::GetGameSpecificCPBarFG( int index_, int iOwningTeam )
{
Assert( index_ < m_iNumControlPoints );
if ( iOwningTeam == TF_TEAM_RED )
return "progress_bar_red";
if ( iOwningTeam == TF_TEAM_BLUE )
return "progress_bar_blu";
return "progress_bar";
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_TFObjectiveResource::GetGameSpecificCPBarBG( int index_, int iCappingTeam )
{
Assert( index_ < m_iNumControlPoints );
Assert( iCappingTeam != TEAM_UNASSIGNED );
if ( iCappingTeam == TF_TEAM_RED )
return "progress_bar_red";
return "progress_bar_blu";
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFObjectiveResource::SetCappingTeam( int index_, int team )
{
//Display warning that someone is capping our point.
//Only do this at the start of a cap and if WE own the point.
//Also don't warn on a point that will do a "Last Point cap" warning.
if ( GetNumControlPoints() > 0 && GetCapWarningLevel( index_ ) == CP_WARN_NORMAL && GetCPCapPercentage( index_ ) == 0.0f && team != TEAM_UNASSIGNED )
{
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( pLocalPlayer )
{
if ( pLocalPlayer->GetTeamNumber() != team )
{
CLocalPlayerFilter filter;
if ( GetOwningTeam( index_ ) != TEAM_UNASSIGNED )
{
C_BaseEntity::EmitSound( filter, -1, "Announcer.ControlPointContested" );
}
else
{
C_BaseEntity::EmitSound( filter, -1, "Announcer.ControlPointContested_Neutral" );
}
}
}
}
BaseClass::SetCappingTeam( index_, team );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TFObjectiveResource::GetMannVsMachineWaveClassCount( int nIndex )
{
if ( nIndex < ARRAYSIZE( m_nMannVsMachineWaveClassCounts ) )
{
return m_nMannVsMachineWaveClassCounts[ nIndex ];
}
nIndex -= ARRAYSIZE( m_nMannVsMachineWaveClassCounts );
if ( nIndex < ARRAYSIZE( m_nMannVsMachineWaveClassCounts2 ) )
{
return m_nMannVsMachineWaveClassCounts2[ nIndex ];
}
return 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_TFObjectiveResource::GetMannVsMachineWaveClassName( int nIndex )
{
if ( nIndex < ARRAYSIZE( m_iszMannVsMachineWaveClassNames ) )
{
return m_iszMannVsMachineWaveClassNames[ nIndex ];
}
nIndex -= ARRAYSIZE( m_iszMannVsMachineWaveClassNames );
if ( nIndex < ARRAYSIZE( m_iszMannVsMachineWaveClassNames2 ) )
{
return m_iszMannVsMachineWaveClassNames2[ nIndex ];
}
return "";
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
unsigned int C_TFObjectiveResource::GetMannVsMachineWaveClassFlags( int nIndex )
{
if ( nIndex < ARRAYSIZE( m_nMannVsMachineWaveClassFlags ) )
{
return m_nMannVsMachineWaveClassFlags[ nIndex ];
}
nIndex -= ARRAYSIZE( m_nMannVsMachineWaveClassFlags );
if ( nIndex < ARRAYSIZE( m_nMannVsMachineWaveClassFlags2 ) )
{
return m_nMannVsMachineWaveClassFlags2[ nIndex ];
}
return 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_TFObjectiveResource::GetMannVsMachineWaveClassActive( int nIndex )
{
if ( nIndex < ARRAYSIZE( m_bMannVsMachineWaveClassActive ) )
{
return m_bMannVsMachineWaveClassActive[ nIndex ];
}
nIndex -= ARRAYSIZE( m_bMannVsMachineWaveClassActive );
if ( nIndex < ARRAYSIZE( m_bMannVsMachineWaveClassActive2 ) )
{
return m_bMannVsMachineWaveClassActive2[ nIndex ];
}
return 0;
}
+87
View File
@@ -0,0 +1,87 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Entity that propagates general data needed by clients for every player.
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_TF_OBJECTIVE_RESOURCE_H
#define C_TF_OBJECTIVE_RESOURCE_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_shareddefs.h"
#include "const.h"
#include "c_baseentity.h"
#include <igameresources.h>
#include "c_team_objectiveresource.h"
class C_TFObjectiveResource : public C_BaseTeamObjectiveResource
{
DECLARE_CLASS( C_TFObjectiveResource, C_BaseTeamObjectiveResource );
public:
DECLARE_CLIENTCLASS();
C_TFObjectiveResource();
virtual ~C_TFObjectiveResource();
const char *GetGameSpecificCPCappingSwipe( int index, int iCappingTeam );
const char *GetGameSpecificCPBarFG( int index, int iOwningTeam );
const char *GetGameSpecificCPBarBG( int index, int iCappingTeam );
void SetCappingTeam( int index, int team );
int GetMannVsMachineMaxWaveCount( void ) { return m_nMannVsMachineMaxWaveCount; }
int GetMannVsMachineWaveCount( void ) { return m_nMannVsMachineWaveCount; }
int GetMannVsMachineWaveEnemyCount( void ) { return m_nMannVsMachineWaveEnemyCount; }
int GetMvMInWorldMoney( void ) { return m_nMvMWorldMoney; }
float GetMannVsMachineNextWaveTime( void ) { return m_flMannVsMachineNextWaveTime; }
bool GetMannVsMachineIsBetweenWaves( void ) { return m_bMannVsMachineBetweenWaves; }
int GetMannVsMachineWaveClassCount( int nIndex );
const char *GetMannVsMachineWaveClassName( int nIndex );
unsigned int GetMannVsMachineWaveClassFlags( int nIndex );
bool GetMannVsMachineWaveClassActive( int nIndex );
int GetFlagCarrierUpgradeLevel( void ) { return m_nFlagCarrierUpgradeLevel; }
float GetBaseMvMBombUpgradeTime( void ) { return m_flMvMBaseBombUpgradeTime; }
float GetNextMvMBombUpgradeTime( void ) { return m_flMvMNextBombUpgradeTime; }
int GetMvMChallengeIndex ( void ) { return m_iChallengeIndex; }
char * GetMvMPopFileName ( void ) { return m_iszMvMPopfileName; }
int GetMvMEventPopfileType( void ) { return m_nMvMEventPopfileType; }
private:
int m_nMannVsMachineMaxWaveCount;
int m_nMannVsMachineWaveCount;
int m_nMannVsMachineWaveEnemyCount;
int m_nMvMWorldMoney;
float m_flMannVsMachineNextWaveTime;
bool m_bMannVsMachineBetweenWaves;
int m_nFlagCarrierUpgradeLevel;
float m_flMvMBaseBombUpgradeTime;
float m_flMvMNextBombUpgradeTime;
int m_nMvMEventPopfileType;
int m_nMannVsMachineWaveClassCounts[ MVM_CLASS_TYPES_PER_WAVE_MAX ];
int m_nMannVsMachineWaveClassCounts2[ MVM_CLASS_TYPES_PER_WAVE_MAX ];
char m_iszMannVsMachineWaveClassNames[ MVM_CLASS_TYPES_PER_WAVE_MAX ][ 64 ];
char m_iszMannVsMachineWaveClassNames2[ MVM_CLASS_TYPES_PER_WAVE_MAX ][ 64 ];
int m_iChallengeIndex;
char m_iszMvMPopfileName[ MAX_PATH ];
unsigned int m_nMannVsMachineWaveClassFlags[ MVM_CLASS_TYPES_PER_WAVE_MAX ];
unsigned int m_nMannVsMachineWaveClassFlags2[ MVM_CLASS_TYPES_PER_WAVE_MAX ];
bool m_bMannVsMachineWaveClassActive[ MVM_CLASS_TYPES_PER_WAVE_MAX ];
bool m_bMannVsMachineWaveClassActive2[ MVM_CLASS_TYPES_PER_WAVE_MAX ];
};
inline C_TFObjectiveResource *TFObjectiveResource()
{
return static_cast<C_TFObjectiveResource*>(g_pObjectiveResource);
}
#endif // C_TF_OBJECTIVE_RESOURCE_H
+99
View File
@@ -0,0 +1,99 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_tf_passtime_ball.h"
#include "passtime_convars.h"
#include "tf_shareddefs.h"
#include "c_tf_player.h"
#include "c_playerresource.h"
#include "c_tf_player.h"
#include "tf_gamerules.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_PasstimeBall, DT_PasstimeBall, CPasstimeBall )
RecvPropInt(RECVINFO(m_iCollisionCount)),
RecvPropEHandle(RECVINFO(m_hHomingTarget)),
RecvPropEHandle(RECVINFO(m_hCarrier)),
RecvPropEHandle(RECVINFO(m_hPrevCarrier)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
LINK_ENTITY_TO_CLASS( passtime_ball, C_PasstimeBall );
PRECACHE_REGISTER( passtime_ball );
C_TFPlayer *C_PasstimeBall::GetCarrier() { return m_hCarrier.Get(); }
C_TFPlayer *C_PasstimeBall::GetPrevCarrier() { return m_hPrevCarrier.Get(); }
//-----------------------------------------------------------------------------
C_PasstimeBall::C_PasstimeBall()
{
UseClientSideAnimation();
m_fDrawTime = 0.0f;
}
//-----------------------------------------------------------------------------
C_PasstimeBall::~C_PasstimeBall()
{
}
//-----------------------------------------------------------------------------
unsigned int C_PasstimeBall::PhysicsSolidMaskForEntity() const
{
return MASK_PLAYERSOLID; // must match server
}
//-----------------------------------------------------------------------------
bool C_PasstimeBall::ShouldCollide( int collisionGroup, int contentsMask ) const
{
// note: returning false for COLLISION_GROUP_PLAYER_MOVEMENT means the ball won't
// stop player movement. the only real visible effect when this function doesn't
// return false for COLLISION_GROUP_PLAYER_MOVEMENT is that the ball is unable
// to impart physics forces on the ball when the ball is blocked, since the player
// will set velocity to zero due to being "stuck" on the ball, even though the
// ball won't actually prevent the player from moving through it.
return (collisionGroup != COLLISION_GROUP_PLAYER_MOVEMENT);
// && (contentsMask & MASK_SHOT_HULL);
//return BaseClass::ShouldCollide( collisionGroup, contentsMask );
}
//-----------------------------------------------------------------------------
void C_PasstimeBall::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
return;
}
if ( TFGameRules()->IsPasstimeMode() )
{
bool bIsVisible = !(GetEffects() & EF_NODRAW);
if ( bIsVisible && !m_bWasVisible )
{
float nextValidTime = gpGlobals->curtime + 0.1f;
m_fDrawTime = nextValidTime;
}
m_bWasVisible = bIsVisible;
}
}
//-----------------------------------------------------------------------------
int C_PasstimeBall::DrawModel( int flags )
{
if( gpGlobals->curtime < m_fDrawTime )
{
return 0;
}
return BaseClass::DrawModel( flags );
}
+52
View File
@@ -0,0 +1,52 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_TF_PASSTIME_BALL_H
#define C_TF_PASSTIME_BALL_H
#ifdef _WIN32
#pragma once
#endif
#include "predictable_entity.h"
#include "util_shared.h"
#include "c_baseanimating.h"
#include "../shared/SpriteTrail.h"
class C_TFPlayer;
//-----------------------------------------------------------------------------
class C_PasstimeBall : public C_BaseAnimating
{
public:
DECLARE_CLASS( C_PasstimeBall, C_BaseAnimating );
DECLARE_NETWORKCLASS();
C_PasstimeBall();
virtual ~C_PasstimeBall();
virtual void OnDataChanged( DataUpdateType_t updateType ) OVERRIDE;
virtual int DrawModel( int flags ) OVERRIDE;
virtual unsigned int PhysicsSolidMaskForEntity() const OVERRIDE;
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const OVERRIDE;
virtual void AddDecal( const Vector& rayStart, const Vector& rayEnd,
const Vector& decalCenter, int hitbox, int decalIndex, bool doTrace,
trace_t& tr, int maxLODToDecal ) OVERRIDE { }// no decals ever
int GetCollisionCount() const { return m_iCollisionCount; }
C_TFPlayer *GetHomingTarget() const { return m_hHomingTarget; }
C_TFPlayer *GetCarrier();
C_TFPlayer *GetPrevCarrier();
private:
bool m_bWasVisible;
float m_fDrawTime;
CNetworkVar( int, m_iCollisionCount );
CNetworkHandle( C_TFPlayer, m_hHomingTarget );
CNetworkHandle( C_TFPlayer, m_hCarrier );
CNetworkHandle( C_TFPlayer, m_hPrevCarrier );
};
#endif // C_TF_PASSTIME_BALL_H
+263
View File
@@ -0,0 +1,263 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "tempent.h"
#include "c_tf_passtime_logic.h"
#include "tf_hud_passtime_reticle.h"
#include "passtime_convars.h"
#include "passtime_game_events.h"
#include "tf_shareddefs.h"
#include "tf_classdata.h"
#include "c_tf_player.h"
#include "c_func_passtime_goal.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void C_TFPasstimeLogic::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
m_pBallReticle = new C_PasstimeBallReticle();
m_pPassReticle = new C_PasstimePassReticle();
for( auto *pGoal : C_FuncPasstimeGoal::GetAutoList() )
{
m_pGoalReticles.AddToTail( new C_PasstimeGoalReticle(
static_cast<C_FuncPasstimeGoal*>( pGoal ) ) );
}
}
}
//-----------------------------------------------------------------------------
C_TFPasstimeLogic* g_pPasstimeLogic;
extern ConVar hud_fastswitch;
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_TFPasstimeLogic, DT_TFPasstimeLogic, CTFPasstimeLogic )
RecvPropEHandle( RECVINFO( m_hBall ) ),
RecvPropArray( RecvPropVector( RECVINFO( m_trackPoints[0] ) ), m_trackPoints ),
RecvPropInt( RECVINFO( m_iNumSections ) ),
RecvPropInt( RECVINFO( m_iCurrentSection ) ),
RecvPropFloat( RECVINFO( m_flMaxPassRange ) ),
RecvPropInt( RECVINFO( m_iBallPower ), 8 ),
RecvPropFloat( RECVINFO( m_flPackSpeed ) ),
RecvPropArray3( RECVINFO_ARRAY( m_bPlayerIsPackMember ), RecvPropInt( RECVINFO( m_bPlayerIsPackMember[0] ) ) ),
END_RECV_TABLE()
LINK_ENTITY_TO_CLASS( passtime_logic, C_TFPasstimeLogic );
//-----------------------------------------------------------------------------
C_TFPasstimeLogic::C_TFPasstimeLogic()
{
m_pBallReticle = nullptr;
m_pPassReticle = nullptr;
memset( m_apPackBeams, 0, sizeof( m_apPackBeams ) );
memset( m_bPlayerIsPackMember, 0, sizeof( m_bPlayerIsPackMember ) );
for( int i = 0; i < m_trackPoints.Count(); ++i )
{
m_trackPoints.GetForModify(i).Zero();
}
g_pPasstimeLogic = this;
}
//-----------------------------------------------------------------------------
C_TFPasstimeLogic::~C_TFPasstimeLogic()
{
delete m_pBallReticle;
m_pGoalReticles.PurgeAndDeleteElements();
delete m_pPassReticle;
// Don't set g_pPasstimeLogic to null here because sometimes this destructor
// happens after the contructor of the new object
// FIXME: what's the right way to do this?
}
//-----------------------------------------------------------------------------
void C_TFPasstimeLogic::Spawn()
{
}
//-----------------------------------------------------------------------------
void C_TFPasstimeLogic::ClientThink()
{
BaseClass::ClientThink();
SetNextClientThink( CLIENT_THINK_ALWAYS );
m_pBallReticle->OnClientThink();
for ( auto *pGoal : m_pGoalReticles )
{
pGoal->OnClientThink();
}
m_pPassReticle->OnClientThink();
UpdateBeams();
}
//-----------------------------------------------------------------------------
void C_TFPasstimeLogic::DestroyBeams( C_PasstimeBall *pBall )
{
for ( CNewParticleEffect *pBeam : m_apPackBeams )
{
if ( pBeam )
{
pBall->ParticleProp()->StopEmission( pBeam );
}
}
memset( m_apPackBeams, 0, sizeof( m_apPackBeams ) );
}
//-----------------------------------------------------------------------------
void C_TFPasstimeLogic::DestroyBeam( int i, C_PasstimeBall *pBall )
{
CNewParticleEffect *pBeam = m_apPackBeams[i];
if ( pBeam )
{
pBall->ParticleProp()->StopEmissionAndDestroyImmediately( pBeam );
m_apPackBeams[i] = nullptr;
}
}
//-----------------------------------------------------------------------------
void C_TFPasstimeLogic::UpdateBeams()
{
C_PasstimeBall *pBall = GetBall();
if ( !pBall )
{
return;
}
C_TFPlayer *pCarrier = pBall->GetCarrier();
if ( !pCarrier )
{
DestroyBeams( pBall );
return;
}
const char *pEffectName = "passtime_beam";
CParticleProperty *pParticles = pBall->ParticleProp();
for ( int i = 1; i <= MAX_PLAYERS; ++i )
{
if ( !m_bPlayerIsPackMember[i] )
{
DestroyBeam( i, pBall );
continue;
}
CTFPlayer *pPlayer = (CTFPlayer*) UTIL_PlayerByIndex( i );
if ( !pPlayer || ( pPlayer == pCarrier ) || !pPlayer->IsAlive() )
{
DestroyBeam( i, pBall );
continue;
}
if ( !m_apPackBeams[i] )
{
CNewParticleEffect *pBeam = pParticles->Create( pEffectName, PATTACH_ABSORIGIN_FOLLOW );
pParticles->AddControlPoint( pBeam, 1, pPlayer, PATTACH_ABSORIGIN_FOLLOW, 0, Vector(0,0,16) );
m_apPackBeams[i] = pBeam;
}
}
}
//-----------------------------------------------------------------------------
void C_TFPasstimeLogic::GetTrackPoints( Vector (&points)[16] )
{
memcpy( points, m_trackPoints.Base(), sizeof(points) );
}
//-----------------------------------------------------------------------------
bool C_TFPasstimeLogic::GetImportantEntities( C_PasstimeBall **ppBall, C_TFPlayer **ppCarrier, C_TFPlayer **ppHomingTarget ) const
{
C_PasstimeBall *pBall = GetBall();
if ( !pBall )
{
return false;
}
if ( ppBall )
{
*ppBall = pBall;
}
if ( ppCarrier )
{
*ppCarrier = pBall->GetCarrier();
}
if ( ppHomingTarget )
{
*ppHomingTarget = ToTFPlayer( pBall->GetHomingTarget() );
}
return true;
}
//-----------------------------------------------------------------------------
bool C_TFPasstimeLogic::GetBallReticleTarget( C_BaseEntity **ppEnt, bool *bHomingActive ) const
{
Assert( ppEnt );
if ( !ppEnt )
{
return false;
}
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pLocalPlayer )
{
return false;
}
C_PasstimeBall *pBall = 0;
C_TFPlayer *pCarrier = 0, *pHomingTarget = 0;
if ( !GetImportantEntities( &pBall, &pCarrier, &pHomingTarget ) )
{
return false;
}
C_BaseEntity *pEnt = pCarrier ? pCarrier : (C_BaseEntity*)pBall;
if ( !pEnt
|| (pEnt == pLocalPlayer)
|| (pEnt->GetEffects() & EF_NODRAW)
|| ((pEnt->GetTeamNumber() != TEAM_UNASSIGNED)
&& (pEnt->GetTeamNumber() != pLocalPlayer->GetTeamNumber()))
|| (pLocalPlayer->IsObserver() && (GetSpectatorMode() != OBS_MODE_ROAMING) && (GetSpectatorTarget() == pEnt->index)) )
{
return false;
}
*ppEnt = pEnt;
if ( bHomingActive )
{
*bHomingActive = pHomingTarget != 0;
}
return true;
}
//-----------------------------------------------------------------------------
bool C_TFPasstimeLogic::BCanPlayerPickUpBall( C_TFPlayer *pPlayer ) const
{
return pPlayer
&& pPlayer->IsAllowedToPickUpFlag()
&& pPlayer->IsAlive() // NOTE: it's possible to be alive and dead at the same time
&& !pPlayer->m_Shared.InCond( TF_COND_INVULNERABLE )
&& !pPlayer->m_Shared.InCond( TF_COND_PHASE )
&& !pPlayer->m_Shared.InCond( TF_COND_INVULNERABLE_WEARINGOFF )
&& !pPlayer->m_Shared.InCond( TF_COND_SELECTED_TO_TELEPORT )
&& !pPlayer->m_Shared.InCond( TF_COND_STEALTHED_BLINK )
&& !pPlayer->m_Shared.InCond( TF_COND_TAUNTING )
&& !pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE )
&& !pPlayer->m_Shared.IsControlStunned()
&& !pPlayer->m_Shared.IsStealthed()
&& !pPlayer->m_Shared.IsCarryingObject();
}
+70
View File
@@ -0,0 +1,70 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_TF_PASSTIME_LOGIC_H
#define C_TF_PASSTIME_LOGIC_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "c_tf_passtime_ball.h"
#include "utlvector.h"
//-----------------------------------------------------------------------------
class C_LocalTempEntity;
class C_TFPlayer;
class C_PasstimeReticle;
class C_TFPasstimeLogic : public C_BaseEntity
{
public:
DECLARE_CLASS( C_TFPasstimeLogic, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_TFPasstimeLogic();
virtual ~C_TFPasstimeLogic();
virtual void Spawn() OVERRIDE;
virtual void ClientThink() OVERRIDE;
virtual void PostDataUpdate( DataUpdateType_t updateType ) OVERRIDE;
C_PasstimeBall *GetBall() const { return m_hBall.Get(); }
void GetTrackPoints( Vector (&points)[16] );
int GetNumSections() const { return m_iNumSections; }
int GetCurrentSection() const { return m_iCurrentSection; }
bool GetBallReticleTarget( C_BaseEntity **ppEnt, bool *bHomingActive ) const;
bool BCanPlayerPickUpBall( C_TFPlayer *pPlayer ) const;
float GetMaxPassRange() const { return m_flMaxPassRange; }
int GetBallPower() const { return m_iBallPower; }
private:
bool GetImportantEntities( C_PasstimeBall **ppBall, C_TFPlayer **ppCarrier, C_TFPlayer **ppHomingTarget ) const;
void DestroyBeam( int i, C_PasstimeBall *pBall );
void DestroyBeams( C_PasstimeBall *pBall );
void UpdateBeams();
C_PasstimeReticle *m_pBallReticle;
CUtlVector<C_PasstimeReticle*> m_pGoalReticles;
C_PasstimeReticle *m_pPassReticle;
CNewParticleEffect *m_apPackBeams[MAX_PLAYERS + 1];
bool m_bPlayerIsPackMember[MAX_PLAYERS + 1];
CNetworkHandle( C_PasstimeBall, m_hBall );
CNetworkArray( Vector, m_trackPoints, 16 );
CNetworkVar( int, m_iNumSections );
CNetworkVar( int, m_iCurrentSection );
CNetworkVar( float, m_flMaxPassRange );
CNetworkVar( int, m_iBallPower );
CNetworkVar( float, m_flPackSpeed );
};
//-----------------------------------------------------------------------------
extern C_TFPasstimeLogic* g_pPasstimeLogic;
#endif // C_TF_PASSTIME_LOGIC_H
File diff suppressed because it is too large Load Diff
+996
View File
@@ -0,0 +1,996 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_TF_PLAYER_H
#define C_TF_PLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_playeranimstate.h"
#include "c_baseplayer.h"
#include "tf_shareddefs.h"
#include "baseparticleentity.h"
#include "tf_player_shared.h"
#include "c_tf_playerclass.h"
#include "tf_item.h"
#include "props_shared.h"
#include "hintsystem.h"
#include "c_playerattachedmodel.h"
#include "c_playerrelativemodel.h"
#include "iinput.h"
#include "ihasattributes.h"
#include "GameEventListener.h"
#include "tf_item_inventory.h"
#include "c_tf_mvm_boss_progress_user.h"
#include "c_te_legacytempents.h"
class C_MuzzleFlashModel;
class C_BaseObject;
class C_TFRagdoll;
class C_TFWearable;
class C_CaptureZone;
class C_MerasmusBombEffect;
class CTFReviveDialog;
class C_TFDroppedWeapon;
class C_PasstimePlayerReticle;
class C_PasstimeAskForBallReticle;
extern ConVar tf_medigun_autoheal;
extern ConVar cl_autorezoom;
extern ConVar cl_autoreload;
enum EBonusEffectFilter_t
{
kEffectFilter_AttackerOnly,
kEffectFilter_AttackerTeam,
kEffectFilter_VictimOnly,
kEffectFilter_VictimTeam,
kEffectFilter_AttackerAndVictimOnly,
kEffectFilter_BothTeams,
};
struct BonusEffect_t
{
BonusEffect_t( const char* pszSoundName, const char* pszParticleName, EBonusEffectFilter_t eParticleFilter, EBonusEffectFilter_t eSoundFilter, bool bPlaySoundInAttackersEars )
: m_pszSoundName( pszSoundName )
, m_pszParticleName( pszParticleName )
, m_eParticleFilter( eParticleFilter )
, m_eSoundFilter( eSoundFilter )
, m_bPlaySoundInAttackersEars( bPlaySoundInAttackersEars )
{}
const char* m_pszSoundName;
const char* m_pszParticleName;
EBonusEffectFilter_t m_eParticleFilter;
EBonusEffectFilter_t m_eSoundFilter;
bool m_bPlaySoundInAttackersEars;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_TFPlayer : public C_BasePlayer, public IHasAttributes, public IInventoryUpdateListener, public C_TFMvMBossProgressUser
{
public:
DECLARE_CLASS( C_TFPlayer, C_BasePlayer );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
C_TFPlayer();
~C_TFPlayer();
virtual void Spawn();
static C_TFPlayer* GetLocalTFPlayer();
virtual void UpdateOnRemove( void );
virtual const QAngle& GetRenderAngles();
virtual void UpdateClientSideAnimation();
virtual void SetDormant( bool bDormant );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ProcessMuzzleFlashEvent();
virtual void ValidateModelIndex( void );
void Touch( CBaseEntity *pOther );
virtual Vector GetObserverCamOrigin( void );
virtual int DrawModel( int flags );
virtual void ApplyBoneMatrixTransform( matrix3x4_t& transform );
virtual void BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
virtual bool CreateMove( float flInputSampleTime, CUserCmd *pCmd ) OVERRIDE;
void CreateVehicleMove( float flInputSampleTime, CUserCmd *pCmd );
virtual bool IsAllowedToSwitchWeapons( void );
void StopViewModelParticles( C_BaseEntity *pParticleEnt );
virtual void ClientThink();
// Deal with recording
virtual void GetToolRecordingState( KeyValues *msg );
CTFWeaponBase *GetActiveTFWeapon( void ) const;
bool IsActiveTFWeapon( CEconItemDefinition *weaponHandle ) const;
bool IsActiveTFWeapon( const CSchemaItemDefHandle &weaponHandle ) const;
virtual void Simulate( void );
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ) OVERRIDE;
virtual void UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) OVERRIDE;
CNewParticleEffect *SpawnHalloweenSpellFootsteps( ParticleAttachment_t eParticleAttachment, int iHalloweenFootstepType );
void FireBullet( CTFWeaponBase *pWpn, const FireBulletsInfo_t &info, bool bDoEffects, int nDamageType, int nCustomDamageType = TF_DMG_CUSTOM_NONE );
void ImpactWaterTrace( trace_t &trace, const Vector &vecStart );
bool CanAttack( int iCanAttackFlags = 0 );
const C_TFPlayerClass *GetPlayerClass( void ) const { return &m_PlayerClass; }
C_TFPlayerClass *GetPlayerClass( void ) { return &m_PlayerClass; }
bool IsPlayerClass( int iClass ) const;
virtual int GetMaxHealth( void ) const;
int GetMaxHealthForBuffing() const;
virtual int GetRenderTeamNumber( void );
bool IsWeaponLowered( void );
void AvoidPlayers( CUserCmd *pCmd );
bool IsABot( void );
// Get the ID target entity index. The ID target is the player that is behind our crosshairs, used to
// display the player's name.
void UpdateIDTarget();
int GetIDTarget() const;
void SetForcedIDTarget( int iTarget );
void SetAnimation( PLAYER_ANIM playerAnim );
virtual float GetMinFOV() const;
virtual const QAngle& EyeAngles();
bool ShouldDrawSpyAsDisguised();
virtual int GetBody( void );
int GetBuildResources( void );
// MATTTODO: object selection if necessary
void SetSelectedObject( C_BaseObject *pObject ) {}
void GetTeamColor( Color &color );
bool InSameDisguisedTeam( CBaseEntity *pEnt );
virtual void ComputeFxBlend( void );
// Taunts/VCDs
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, C_BaseEntity *pTarget );
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
virtual void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov );
bool StartGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
bool StopGestureSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
void TurnOnTauntCam( void );
void TurnOnTauntCam_Finish( void );
void TurnOffTauntCam( void );
void TurnOffTauntCam_Finish( void );
bool IsTaunting( void ) const { return m_Shared.InCond( TF_COND_TAUNTING ); }
virtual void InitPhonemeMappings();
// Gibs.
void InitPlayerGibs( void );
void CheckAndUpdateGibType( void );
void CreatePlayerGibs( const Vector &vecOrigin, const Vector &vecVelocity, float flImpactScale, bool bBurning, bool bWearableGibs=false, bool bOnlyHead=false, bool bDisguiseGibs=false );
void DropPartyHat( breakablepropparams_t &breakParams, Vector &vecBreakVelocity );
void DropWearable( C_TFWearable *pItem, const breakablepropparams_t &params );
int GetObjectCount( void );
C_BaseObject *GetObject( int index );
C_BaseObject *GetObjectOfType( int iObjectType, int iObjectMode=0 ) const;
int GetNumObjects( int iObjectType, int iObjectMode=0 );
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
float GetPercentInvisible( void );
float GetEffectiveInvisibilityLevel( void ); // takes viewer into account
virtual bool IsTransparent( void ) OVERRIDE { return GetPercentInvisible() > 0.f; }
virtual void AddDecal( const Vector& rayStart, const Vector& rayEnd,
const Vector& decalCenter, int hitbox, int decalIndex, bool doTrace, trace_t& tr, int maxLODToDecal = ADDDECAL_TO_ALL_LODS );
virtual void CalcDeathCamView(Vector& eyeOrigin, QAngle& eyeAngles, float& fov);
virtual Vector GetChaseCamViewOffset( CBaseEntity *target );
virtual Vector GetDeathViewPosition();
void ClientPlayerRespawn( void );
virtual bool ShouldDraw();
virtual int GetVisionFilterFlags( bool bWeaponsCheck = false );
virtual void CalculateVisionUsingCurrentFlags( void );
void CreateSaveMeEffect( MedicCallerType nType = CALLER_TYPE_NORMAL );
void StopSaveMeEffect( bool bForceRemoveInstantly = false );
void CreateTauntWithMeEffect();
void StopTauntWithMeEffect();
void CreateKart();
void RemoveKart();
C_BaseAnimating *GetKart() const { return m_pKart; }
void CreateKartEffect( const char *pszEffectName );
void StopKartEffect();
void UpdateKartSounds();
void StartKartBrakeEffect();
void StopKartBrakeEffect();
CNetworkVar( int, m_iKartState );
bool IsAllowedToTaunt( void );
virtual bool IsOverridingViewmodel( void );
virtual int DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags );
void SetHealer( C_TFPlayer *pHealer, float flChargeLevel );
void SetWasHealedByLocalPlayer( bool bState ) { m_bWasHealedByLocalPlayer = bState; }
void GetHealer( C_TFPlayer **pHealer, float *flChargeLevel ) { *pHealer = m_hHealer; *flChargeLevel = m_flHealerChargeLevel; }
bool GetWasHealedByLocalPlayer() { return m_bWasHealedByLocalPlayer; }
float MedicGetChargeLevel( CTFWeaponBase **pRetMedigun = NULL );
bool MedicIsReleasingCharge( void );
CBaseEntity *MedicGetHealTarget( void );
void StartBurningSound( void );
void StopBurningSound( void );
void StopBlastJumpLoopSound( int iUserID );
void UpdateSpyStateChange( void );
void UpdateRecentlyTeleportedEffect( void );
void UpdateOverhealEffect( void );
void UpdatedMarkedForDeathEffect( bool bFroceStop = false );
void CreateOverhealEffect( int iTeam );
void UpdateRuneIcon( bool bForceStop = false );
bool CanShowClassMenu( void );
bool CanShowTeamMenu( void );
void InitializePoseParams( void );
void UpdateLookAt( void );
bool IsEnemyPlayer( void );
void ShowNemesisIcon( bool bShow );
void ShowDuelingIcon( bool bShow );
void ShowIconForIT( bool bShow );
#ifdef STAGING_ONLY
void UpdateTranqMark( bool bShow, bool bForceStop = false );
void UpdateSpyClassStealParticle( bool bShow );
#endif // STAGING_ONLY
void ShowBirthdayEffect( bool bShow );
CUtlVector<EHANDLE> *GetSpawnedGibs( void ) { return &m_hSpawnedGibs; }
bool HasBombinomiconEffectOnDeath( void );
Vector GetClassEyeHeight( void );
void ForceUpdateObjectHudState( void );
bool GetMedigunAutoHeal( void ){ return tf_medigun_autoheal.GetBool(); }
bool ShouldAutoRezoom( void ){ return cl_autorezoom.GetBool(); }
bool ShouldAutoReload( void ){ return cl_autoreload.GetBool(); }
void GetTargetIDDataString( bool bIsDisguised, OUT_Z_BYTECAP(iMaxLenInBytes) wchar_t *sDataString, int iMaxLenInBytes, bool &bIsAmmoData, bool &bIsKillStreakData );
void RemoveDisguise( void );
bool CanDisguise( void );
bool CanDisguise_OnKill( void );
virtual void OnAchievementAchieved( int iAchievement );
virtual void OverrideView( CViewSetup *pSetup );
bool CanAirDash( void ) const;
bool CanGetWet() const;
void CreateBoneAttachmentsFromWearables( C_TFRagdoll *pRagdoll, bool bDisguised );
bool CanUseFirstPersonCommand( void );
bool IsEffectRateLimited( EBonusEffectFilter_t effect, const C_TFPlayer* pAttacker ) const;
bool ShouldPlayEffect( EBonusEffectFilter_t filter, const C_TFPlayer* pAttacker, const C_TFPlayer* pVictim ) const;
virtual void FireGameEvent( IGameEvent *event );
virtual const char* ModifyEventParticles( const char* token );
// Set the distances the camera should use.
void SetTauntCameraTargets( float back, float up );
// TF-specific color values for GlowEffect
virtual void GetGlowEffectColor( float *r, float *g, float *b );
void UpdateGlowColor( void );
virtual const Vector& GetRenderOrigin( void );
RTime32 GetSpottedInPVSTime() const { return m_rtSpottedInPVSTime; }
RTime32 GetJoinedSpectatorTeamTime() const { return m_rtJoinedSpectatorTeam; }
RTime32 GetJoinedNormalTeamTime() const { return m_rtJoinedNormalTeam; }
// IHasAttributes
CAttributeManager *GetAttributeManager( void ) { return &m_AttributeManager; }
CAttributeContainer *GetAttributeContainer( void ) { return NULL; }
CBaseEntity *GetAttributeOwner( void ) { return NULL; }
CAttributeList *GetAttributeList( void ) { return &m_AttributeList; }
virtual void ReapplyProvision( void ) { return; }
// ITFMvMBossProgressUser
virtual const char* GetBossProgressImageName() const OVERRIDE;
virtual float GetBossStatusProgress() const OVERRIDE;
protected:
CNetworkVarEmbedded( CAttributeContainerPlayer, m_AttributeManager );
// IClientNetworkable implementation.
public:
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
public:
// Shared functions
float GetMovementForwardPull( void ) const;
bool CanPlayerMove() const;
float TeamFortress_CalculateMaxSpeed( bool bIgnoreSpecialAbility = false ) const;
void TeamFortress_SetSpeed();
bool HasItem( void ) const; // Currently can have only one item at a time.
void SetItem( C_TFItem *pItem );
C_TFItem *GetItem( void ) const;
bool HasTheFlag( ETFFlagType exceptionTypes[] = NULL, int nNumExceptions = 0 ) const;
virtual bool IsAllowedToPickUpFlag( void ) const;
float GetCritMult( void ) { return m_Shared.GetCritMult(); }
virtual void ItemPostFrame( void );
void SetOffHandWeapon( CTFWeaponBase *pWeapon );
void HolsterOffHandWeapon( void );
CTFWeaponBase* GetOffHandWeapon( void ) { return m_hOffHandWeapon; }
void GetActiveSets( CUtlVector<const CEconItemSetDefinition *> *pItemSets );
virtual int GetSkin();
float GetLastDamageTime( void ) const { return m_flLastDamageTime; }
virtual bool Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon );
virtual bool Weapon_ShouldSetLast( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) OVERRIDE;
virtual bool Weapon_Switch( C_BaseCombatWeapon *pWeapon, int viewmodelindex = 0 ) OVERRIDE;
virtual void SelectItem( const char *pstr, int iSubType = 0 ) OVERRIDE;
virtual void UpdateWearables() OVERRIDE;
CTFWearable *GetEquippedWearableForLoadoutSlot( int iLoadoutSlot );
CBaseEntity *GetEntityForLoadoutSlot( int iLoadoutSlot ); //Gets whatever entity is associated with the loadout slot (wearable or weapon)
CTFWeaponBase *Weapon_OwnsThisID( int iWeaponID ) const;
CTFWeaponBase *Weapon_GetWeaponByType( int iType );
virtual void GetStepSoundVelocities( float *velwalk, float *velrun );
virtual void SetStepSoundTime( stepsoundtimes_t iStepSoundTime, bool bWalking );
virtual const char *GetOverrideStepSound( const char *pszBaseStepSoundName );
virtual void OnEmitFootstepSound( const CSoundParameters& params, const Vector& vecOrigin, float fVolume );
virtual void ModifyEmitSoundParams( EmitSound_t &params );
virtual void ThirdPersonSwitch( bool bThirdperson );
bool DoClassSpecialSkill( void );
bool EndClassSpecialSkill( void );
bool CanGoInvisible( bool bAllowWhileCarryingFlag = false );
int GetMaxAmmo( int iAmmoIndex, int iClassIndex = -1 );
//-----------------------------------------------------------------------------------------------------
// Return true if we are a "mini boss" in Mann Vs Machine mode
bool IsMiniBoss( void ) const;
bool ShouldTauntHintIconBeVisible() const;
virtual bool IsHealthBarVisible( void ) const OVERRIDE;
bool CanStartPhase( void );
bool CanPickupBuilding( CBaseObject *pPickupObject );
bool TryToPickupBuilding( void );
void StartBuildingObjectOfType( int iType, int iObjectMode=0 );
void FeignDeath( CTakeDamageInfo& info );
C_CaptureZone *GetCaptureZoneStandingOn( void );
C_CaptureZone *GetClosestCaptureZone( void );
float GetMetersRan( void ) { return m_fMetersRan; }
void SetMetersRan( float fMeters, int iFrame );
CEconItemView *GetInspectItem( int *iLastItem );
void SetBodygroupsDirty( void );
void RecalcBodygroupsIfDirty( void );
bool CanMoveDuringTaunt();
bool ShouldStopTaunting();
bool IsTauntForceMovingForward() const { return m_bTauntForceMoveForward; }
float GetTauntMoveAcceleration() const { return m_flTauntMoveAccelerationTime; }
float GetTauntMoveSpeed() const { return m_flTauntForceMoveForwardSpeed; }
float GetTauntTurnAccelerationTime() const { return m_flTauntTurnAccelerationTime; }
bool IsReadyToTauntWithPartner( void ) const { return m_bIsReadyToHighFive; }
CTFPlayer * GetTauntPartner( void ) { return m_hHighFivePartner; }
float GetTauntYaw( void ) { return m_flTauntYaw; }
float GetPrevTauntYaw( void ) { return m_flPrevTauntYaw; }
void SetTauntYaw( float flTauntYaw );
int GetActiveTauntSlot() const { return m_nActiveTauntSlot; }
void PlayTauntSoundLoop( const char *pszSoundLoopName );
void StopTauntSoundLoop();
float GetCurrentTauntMoveSpeed() const { return m_flCurrentTauntMoveSpeed; }
void SetCurrentTauntMoveSpeed( float flSpeed ) { m_flCurrentTauntMoveSpeed = flSpeed; }
float GetVehicleReverseTime() const { return m_flVehicleReverseTime; }
void SetVehicleReverseTime( float flTime ) { m_flVehicleReverseTime = flTime; }
CEconItemView *GetTauntEconItemView() { return m_TauntEconItemView.IsValid() ? &m_TauntEconItemView : NULL; }
float GetHeadScale() const { return m_flHeadScale; }
float GetTorsoScale() const { return m_flTorsoScale; }
float GetHandScale() const { return m_flHandScale; }
float GetLastResistTime() const { return m_flLastResistTime; }
bool BRenderAsZombie( bool bWeaponsCheck = false );
static void AdjustSkinIndexForZombie( int iClassIndex, int &iSkinIndex );
// Ragdolls.
virtual C_BaseAnimating *BecomeRagdollOnClient();
virtual IRagdoll *GetRepresentativeRagdoll() const;
EHANDLE m_hRagdoll;
Vector m_vecRagdollVelocity;
// Objects
int CanBuild( int iObjectType, int iObjectMode=0 );
CUtlVector< CHandle<C_BaseObject> > m_aObjects;
virtual CStudioHdr *OnNewModel( void );
void DisplaysHintsForTarget( C_BaseEntity *pTarget );
// Shadows
virtual ShadowType_t ShadowCastType( void ) ;
virtual void GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType );
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual bool GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const;
CMaterialReference *GetInvulnMaterialRef( void ) { return &m_InvulnerableMaterial; }
bool IsNemesisOfLocalPlayer();
bool ShouldShowDuelingIcon();
bool ShouldShowNemesisIcon();
virtual IMaterial *GetHeadLabelMaterial( void );
// Spy Cigarette
bool CanLightCigarette( void );
void UpdateDemomanEyeEffect( int iDecapitations );
const char* GetDemomanEyeEffectName( int iDecapitations );
int GetCurrency( void ){ return m_nCurrency; }
virtual void UpdateMVMEyeGlowEffect( bool bVisible );
void UpdateKillStreakEffects( int iCount, bool bKillScored = false );
const char *GetEyeGlowEffect() { return m_pszEyeGlowEffectName; }
Vector GetEyeGlowColor( bool bAlternate ) { return bAlternate? m_vEyeGlowColor1 : m_vEyeGlowColor2 ; }
// Bounty Mode
int GetExperienceLevel( void ) { return m_nExperienceLevel; }
// Matchmaking
bool GetMatchSafeToLeave() { return m_bMatchSafeToLeave; }
// Halloween silliness.
void HalloweenBombHeadUpdate( void );
bool IsUsingVRHeadset( void ){ return m_bUsingVRHeadset; }
bool ShouldPlayerDrawParticles( void );
bool IsPlayerOnSteamFriendsList( C_BasePlayer *pPlayer );
protected:
void ResetFlexWeights( CStudioHdr *pStudioHdr );
virtual void CalcInEyeCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual void UpdateGlowEffect( void );
virtual void DestroyGlowEffect( void );
private:
bool ShouldShowPowerupGlowEffect();
void GetPowerupGlowEffectColor( float *r, float *g, float *b );
void HandleTaunting( void );
void TauntCamInterpolation( void );
void OnPlayerClassChange( void );
void UpdatePartyHat( void );
void InitInvulnerableMaterial( void );
void GetHorriblyHackedRailgunPosition( const Vector& vStart, Vector *out_pvStartPos );
void MaybeDrawRailgunBeam( IRecipientFilter *pFilter, CTFWeaponBase *pWeapon, const Vector& vStartPos, const Vector& vEndPos );
bool m_bWasTaunting;
bool m_bTauntInterpolating;
CameraThirdData_t m_TauntCameraData;
float m_flTauntCamCurrentDist;
float m_flTauntCamTargetDist;
float m_flTauntCamCurrentDistUp;
float m_flTauntCamTargetDistUp;
QAngle m_angTauntPredViewAngles;
QAngle m_angTauntEngViewAngles;
CSoundPatch *m_pTauntSoundLoop;
C_TFPlayerClass m_PlayerClass;
// ID Target
int m_iIDEntIndex;
int m_iForcedIDTarget;
CNewParticleEffect *m_pTeleporterEffect;
bool m_bToolRecordingVisibility;
int m_iOldSpawnCounter;
// Healer
CHandle<C_TFPlayer> m_hHealer;
bool m_bWasHealedByLocalPlayer;
float m_flHealerChargeLevel;
int m_iOldHealth;
int m_nOldMaxHealth;
float m_fMetersRan;
int m_iLastRanFrame;
HPARTICLEFFECT m_pEyeEffect;
bool m_bOldCustomModelVisible;
CHandle< C_BaseCombatWeapon > m_hOldActiveWeapon;
// Look At
/*
int m_headYawPoseParam;
int m_headPitchPoseParam;
float m_headYawMin;
float m_headYawMax;
float m_headPitchMin;
float m_headPitchMax;
float m_flLastBodyYaw;
float m_flCurrentHeadYaw;
float m_flCurrentHeadPitch;
*/
// Spy cigarette smoke
bool m_bCigaretteSmokeActive;
// Medic callout particle effect
CNewParticleEffect *m_pSaveMeEffect;
CNewParticleEffect *m_pTauntWithMeEffect;
bool m_bUpdateObjectHudState;
bool m_bBodygroupsDirty;
HPARTICLEFFECT m_hKartDamageEffect;
CNetworkVar( float, m_flKartNextAvailableBoost );
CNetworkVar( int, m_iKartHealth );
int m_iOldKartHealth;
void UpdateKartEffects();
void UpdateKartState();
int m_iOldKartState;
C_BaseAnimating *m_pKart;
public:
float GetKartSpeedBoost( void );
float GetKartHealth( void ) { return m_iKartHealth; }
CTFPlayerShared m_Shared;
friend class CTFPlayerShared;
// Called by shared code.
public:
float GetClassChangeTime() const { return m_flChangeClassTime; }
void SetFootStamps( int nFootStamps ) { m_nFootStamps = nFootStamps; }
void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 );
bool PlayAnimEventInPrediction( PlayerAnimEvent_t event );
bool GetPredictable( void ) const;
// Halloween
void CreateBombonomiconHint();
void DestroyBombonomiconHint();
void CleanUpAnimationOnSpawn();
CTFPlayerAnimState *m_PlayerAnimState;
QAngle m_angEyeAngles;
CInterpolatedVar< QAngle > m_iv_angEyeAngles;
CNetworkHandle( C_TFItem, m_hItem );
CNetworkHandle( C_TFWeaponBase, m_hOffHandWeapon );
CNetworkHandle( C_TFPlayer, m_hCoach );
CNetworkHandle( C_TFPlayer, m_hStudent );
CGlowObject *m_pStudentGlowEffect;
CGlowObject *m_pPowerupGlowEffect;
int m_iOldPlayerClass; // Used to detect player class changes
bool m_bIsDisplayingNemesisIcon;
bool m_bIsDisplayingDuelingIcon;
bool m_bIsDisplayingIconForIT;
bool m_bIsDisplayingTranqMark;
bool m_bShouldShowBirthdayEffect;
RuneTypes_t m_eDisplayingRuneIcon;
float m_flLastDamageTime;
bool m_bInPowerPlay;
int m_iSpawnCounter;
bool m_bArenaSpectator;
bool m_bIsMiniBoss;
bool m_bIsABot;
int m_nBotSkill;
int m_nOldBotSkill;
bool m_bSaveMeParity;
bool m_bOldSaveMeParity;
bool m_bIsCoaching;
private:
void UpdateTauntItem();
void ParseSharedTauntDataFromEconItemView( CEconItemView *pEconItemView );
bool m_bAllowMoveDuringTaunt;
bool m_bTauntForceMoveForward;
float m_flTauntForceMoveForwardSpeed;
float m_flTauntMoveAccelerationTime;
float m_flTauntTurnSpeed;
float m_flTauntTurnAccelerationTime;
bool m_bIsReadyToHighFive;
CNetworkHandle( C_TFPlayer, m_hHighFivePartner );
int m_nForceTauntCam;
float m_flTauntYaw;
float m_flPrevTauntYaw;
int m_nActiveTauntSlot;
int m_nPrevTauntSlot;
item_definition_index_t m_iTauntItemDefIndex;
item_definition_index_t m_iPrevTauntItemDefIndex;
float m_flCurrentTauntMoveSpeed;
float m_flVehicleReverseTime;
int m_nTauntSequence;
float m_flTauntStartTime;
float m_flTauntDuration;
CEconItemView m_TauntEconItemView;
public:
int m_nOldWaterLevel;
float m_flWaterEntryTime;
bool m_bWaterExitEffectActive;
bool m_bDuckJumpInterp;
float m_flFirstDuckJumpInterp;
float m_flLastDuckJumpInterp;
float m_flDuckJumpInterp;
CMaterialReference m_InvulnerableMaterial;
// Burning
CSoundPatch *m_pBurningSound;
HPARTICLEFFECT m_pBurningEffect;
float m_flBurnEffectStartTime;
// Urine
HPARTICLEFFECT m_pUrineEffect;
// Milk
HPARTICLEFFECT m_pMilkEffect;
// Soldier Buff
HPARTICLEFFECT m_pSoldierOffensiveBuffEffect;
HPARTICLEFFECT m_pSoldierDefensiveBuffEffect;
HPARTICLEFFECT m_pSoldierOffensiveHealthRegenBuffEffect;
HPARTICLEFFECT m_pSoldierNoHealingDamageBuffEffect;
// Speed boost
HPARTICLEFFECT m_pSpeedBoostEffect;
// Taunt effects
HPARTICLEFFECT m_pTauntEffect;
// Temp HACK for crit boost
HPARTICLEFFECT m_pCritBoostEffect;
HPARTICLEFFECT m_pOverHealedEffect;
HPARTICLEFFECT m_pPhaseStandingEffect;
HPARTICLEFFECT m_pStunnedEffect;
HPARTICLEFFECT m_pMegaHealEffect;
HPARTICLEFFECT m_pRadiusHealEffect;
HPARTICLEFFECT m_pKingRuneRadiusEffect;
HPARTICLEFFECT m_pKingBuffRadiusEffect;
HPARTICLEFFECT m_pRunePlagueEffect;
C_LocalTempEntity* m_pTempShield;
float m_flLastResistTime;
HPARTICLEFFECT m_pSappedPlayerEffect;
HPARTICLEFFECT m_pMVMEyeGlowEffect[ 2 ];
// KillStreak Weapons
char m_pszEyeGlowEffectName[MAX_PATH];
Vector m_vEyeGlowColor1;
Vector m_vEyeGlowColor2;
HPARTICLEFFECT m_pEyeGlowEffect[ 2 ];
float m_flNextSheenStartTime;
HPARTICLEFFECT m_pMVMBotRadiowave;
HPARTICLEFFECT m_pRuneChargeReadyEffect;
#ifdef STAGING_ONLY
HPARTICLEFFECT m_pRocketPackEffect;
#endif // STAGING_ONLY
enum EKartParticles
{
KART_PARTICLE_LEFT_LIGHT = 0,
KART_PARTICLE_RIGHT_LIGHT,
KART_PARTICLE_LEFT_WHEEL,
KART_PARTICLE_RIGHT_WHEEL,
NUM_KART_PARTICLES
};
HPARTICLEFFECT m_pKartParticles[ NUM_KART_PARTICLES ];
enum EKartSounds
{
KART_SOUND_ENGINE_LOOP = 0,
KART_SOUND_BURNOUT_LOOP,
NUM_KART_SOUNDS,
};
CSoundPatch *m_pKartSounds[ NUM_KART_SOUNDS ];
CNewParticleEffect *m_pDisguisingEffect;
float m_flDisguiseEffectStartTime;
float m_flDisguiseEndEffectStartTime;
EHANDLE m_hFirstGib;
EHANDLE m_hHeadGib;
CUtlVector<EHANDLE> m_hSpawnedGibs;
int m_iOldTeam;
int m_iOldClass;
int m_iOldDisguiseTeam;
int m_iOldDisguiseClass;
int m_iOldObserverMode;
EHANDLE m_hOldObserverTarget;
bool m_bDisguised;
int m_iPreviousMetal;
int GetNumActivePipebombs( void );
int m_iSpyMaskBodygroup;
Vector m_vecCustomModelOrigin;
// Halloween
CHandle<C_PlayerAttachedModel> m_hHalloweenBombHat;
CHandle<C_MerasmusBombEffect> m_hBombonomiconHint;
CHandle<C_PlayerAttachedModel> m_hHalloweenKartCage;
float m_flBombDelay;
// Achievements
float m_flSaveMeExpireTime;
//CountdownTimer m_LeaveServerTimer;
//----------------------------
// INVENTORY MANAGEMENT
public:
// IInventoryUpdateListener
virtual void InventoryUpdated( CPlayerInventory *pInventory );
virtual void SOCacheUnsubscribed( const CSteamID & steamIDOwner ) { m_Shared.SetLoadoutUnavailable( true ); }
void UpdateInventory( bool bInit );
// Inventory access
CTFPlayerInventory *Inventory( void ) { return &m_Inventory; }
bool CanDisplayAllSeeEffect( EAttackBonusEffects_t effect ) const;
void SetNextAllSeeEffectTime( EAttackBonusEffects_t effect, float flTime );
private:
CTFPlayerInventory m_Inventory;
bool m_bInventoryReceived;
private:
float m_flChangeClassTime;
float m_flWaterImpactTime;
RTime32 m_rtSpottedInPVSTime;
RTime32 m_rtJoinedSpectatorTeam;
RTime32 m_rtJoinedNormalTeam;
// Gibs.
CUtlVector< int > m_aSillyGibs;
CUtlVector< char* > m_aNormalGibs;
CUtlVector<breakmodel_t> m_aGibs;
C_TFPlayer( const C_TFPlayer & );
mutable char m_bIsCalculatingMaximumSpeed;
// In-game currency
int m_nCurrency;
int m_nOldCurrency;
// Bounty Mode
int m_nExperienceLevel;
int m_nExperienceLevelProgress;
int m_nPrevExperienceLevel;
// Matchmaking
// is this player bound to the match on penalty of abandon. Sync'd via local-player-only DT
bool m_bMatchSafeToLeave;
// Medic healtarget active weapon ammo/clip count
uint16 m_nActiveWpnClip;
// Blast jump whistle
CSoundPatch *m_pBlastJumpLoop;
float m_flBlastJumpLaunchTime;
CNetworkVar( float, m_flHeadScale );
CNetworkVar( float, m_flTorsoScale );
CNetworkVar( float, m_flHandScale );
// Allseecrit throttle - other clients ask us if we can be the source of another particle+sound
float m_flNextMiniCritEffectTime[ kBonusEffect_Count ];
CNetworkVar( bool, m_bUseBossHealthBar );
CNetworkVar( bool, m_bUsingVRHeadset );
CNetworkVar( bool, m_bForcedSkin );
CNetworkVar( int, m_nForcedSkin );
int m_nFootStamps;
vgui::DHANDLE< CTFReviveDialog > m_hRevivePrompt;
public:
void SetShowHudMenuTauntSelection( bool bShow ) { m_bShowHudMenuTauntSelection = bShow; }
bool ShouldShowHudMenuTauntSelection() const { return m_bShowHudMenuTauntSelection; }
private:
bool m_bShowHudMenuTauntSelection;
public:
CBaseEntity *GetGrapplingHookTarget() const { return m_hGrapplingHookTarget; }
bool IsUsingActionSlot() const { return m_bUsingActionSlot; }
void SetUsingActionSlot( bool bUsingActionSlot ) { m_bUsingActionSlot = bUsingActionSlot; }
void SetSecondaryLastWeapon( CBaseCombatWeapon *pSecondaryLastWeapon ) { m_hSecondaryLastWeapon = pSecondaryLastWeapon; }
CBaseCombatWeapon* GetSecondaryLastWeapon() const { return m_hSecondaryLastWeapon; }
bool CanPickupDroppedWeapon( const C_TFDroppedWeapon *pWeapon );
C_TFDroppedWeapon* GetDroppedWeaponInRange();
bool HasCampaignMedal( int iMedal );
CampaignMedalDisplayType_t GetCampaignMedalType( void );
const char *GetCampaignMedalImage( void );
void SetInspectTime( float flInspectTime ) { m_flInspectTime = flInspectTime; }
bool IsInspecting() const;
void HandleInspectHint();
bool AddOverheadEffect( const char *pszEffectName );
void RemoveOverheadEffect( const char *pszEffectName, bool bRemoveInstantly );
void UpdateOverheadEffects();
Vector GetOverheadEffectPosition();
int GetSkinOverride() const { return m_iPlayerSkinOverride; }
private:
CNetworkHandle( CBaseEntity, m_hGrapplingHookTarget );
CNetworkHandle( CBaseCombatWeapon, m_hSecondaryLastWeapon );
CNetworkVar( bool, m_bUsingActionSlot );
CNetworkVar( int, m_iCampaignMedals );
CNetworkVar( float, m_flInspectTime );
bool m_bNotifiedWeaponInspectThisLife;
C_PasstimePlayerReticle *m_pPasstimePlayerReticle;
C_PasstimeAskForBallReticle *m_pPasstimeAskForBallReticle;
CUtlMap< const char *, HPARTICLEFFECT > m_mapOverheadEffects;
float m_flOverheadEffectStartTime;
CNetworkVar( int, m_iPlayerSkinOverride );
};
inline C_TFPlayer* ToTFPlayer( C_BaseEntity *pEntity )
{
if ( !pEntity || !pEntity->IsPlayer() )
return NULL;
Assert( dynamic_cast<C_TFPlayer*>( pEntity ) != 0 );
return static_cast< C_TFPlayer* >( pEntity );
}
void SetAppropriateCamera( C_TFPlayer *pPlayer );
class C_TFPlayerPreviewEffect
{
public:
// If you re-order this list, please update TF_ImportPreview_Effect* in tf_english.txt
enum PREVIEW_EFFECT
{
PREVIEW_EFFECT_NONE,
PREVIEW_EFFECT_UBER,
//PREVIEW_EFFECT_CRIT, // Punting on particle effects for now
PREVIEW_EFFECT_URINE,
//PREVIEW_EFFECT_MILK, // Punting on particle effects for now
//PREVIEW_EFFECT_INVIS, // The CMDLPanel draw path doesn't handle transparency at the moment
PREVIEW_EFFECT_BURN,
NUM_PREVIEW_EFFECTS
};
public:
C_TFPlayerPreviewEffect();
void SetEffect(PREVIEW_EFFECT nEffect) { m_nPreviewEffect = nEffect; }
PREVIEW_EFFECT GetEffect() const { return m_nPreviewEffect; }
void SetTeam(int nTeam);
int GetTeam() const { return m_nTeam; }
CMaterialReference *GetInvulnMaterialRef( void ) { return &m_InvulnerableMaterial; }
void Reset();
protected:
PREVIEW_EFFECT m_nPreviewEffect;
int m_nTeam;
CMaterialReference m_InvulnerableMaterial;
};
extern C_TFPlayerPreviewEffect g_PlayerPreviewEffect;
#endif // C_TF_PLAYER_H
+23
View File
@@ -0,0 +1,23 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=============================================================================
#ifndef C_TF_PLAYERCLASS_H
#define C_TF_PLAYERCLASS_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_playerclass_shared.h"
//-----------------------------------------------------------------------------
// TF Player Class
//-----------------------------------------------------------------------------
class C_TFPlayerClass : public CTFPlayerClassShared
{
public:
C_TFPlayerClass() {}
};
#endif // C_TF_PLAYERCLASS_H
+337
View File
@@ -0,0 +1,337 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: TF's custom C_PlayerResource
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_tf_playerresource.h"
#include <shareddefs.h>
#include <tf_shareddefs.h>
#include "hud.h"
#include "tf_gamerules.h"
#include "tf_gc_client.h"
#include "tf_lobby_server.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ConVar tf_mvm_respec_limit;
extern ConVar tf_mvm_buybacks_method;
C_TF_PlayerResource *g_TF_PR;
IMPLEMENT_CLIENTCLASS_DT( C_TF_PlayerResource, DT_TFPlayerResource, CTFPlayerResource )
RecvPropArray3( RECVINFO_ARRAY( m_iTotalScore ), RecvPropInt( RECVINFO( m_iTotalScore[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iMaxHealth ), RecvPropInt( RECVINFO( m_iMaxHealth[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iMaxBuffedHealth ), RecvPropInt( RECVINFO( m_iMaxBuffedHealth[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iPlayerClass ), RecvPropInt( RECVINFO( m_iPlayerClass[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_bArenaSpectator ), RecvPropBool( RECVINFO( m_bArenaSpectator[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iActiveDominations ), RecvPropInt( RECVINFO( m_iActiveDominations[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_flNextRespawnTime ), RecvPropTime( RECVINFO( m_flNextRespawnTime[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iChargeLevel ), RecvPropInt( RECVINFO( m_iChargeLevel[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iDamage ), RecvPropInt( RECVINFO( m_iDamage[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iDamageAssist ), RecvPropInt( RECVINFO( m_iDamageAssist[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iDamageBoss ), RecvPropInt( RECVINFO( m_iDamageBoss[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iHealing ), RecvPropInt( RECVINFO( m_iHealing[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iHealingAssist ), RecvPropInt( RECVINFO( m_iHealingAssist[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iDamageBlocked ), RecvPropInt( RECVINFO( m_iDamageBlocked[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iCurrencyCollected ), RecvPropInt( RECVINFO( m_iCurrencyCollected[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iBonusPoints ), RecvPropInt( RECVINFO( m_iBonusPoints[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iPlayerLevel ), RecvPropInt( RECVINFO( m_iPlayerLevel[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iStreaks ), RecvPropInt( RECVINFO_ARRAY( m_iStreaks ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iUpgradeRefundCredits ), RecvPropInt( RECVINFO( m_iUpgradeRefundCredits[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iBuybackCredits ), RecvPropInt( RECVINFO( m_iBuybackCredits[0] ) ) ),
RecvPropInt( RECVINFO( m_iPartyLeaderRedTeamIndex ) ),
RecvPropInt( RECVINFO( m_iPartyLeaderBlueTeamIndex ) ),
RecvPropInt( RECVINFO( m_iEventTeamStatus ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iPlayerClassWhenKilled ), RecvPropInt( RECVINFO( m_iPlayerClassWhenKilled[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY( m_iConnectionState ), RecvPropInt( RECVINFO( m_iConnectionState[0] ) ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TF_PlayerResource::C_TF_PlayerResource()
{
m_Colors[TEAM_UNASSIGNED] = COLOR_TF_SPECTATOR;
m_Colors[TEAM_SPECTATOR] = COLOR_TF_SPECTATOR;
m_Colors[TF_TEAM_RED] = COLOR_RED;
m_Colors[TF_TEAM_BLUE] = COLOR_BLUE;
m_iPartyLeaderRedTeamIndex = 0;
m_iPartyLeaderBlueTeamIndex = 0;
m_iEventTeamStatus = 0;
ResetPlayerScoreStats();
g_TF_PR = this;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TF_PlayerResource::~C_TF_PlayerResource()
{
g_TF_PR = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetTeam( int iIndex )
{
bool bValid = ( iIndex >= 1 && iIndex <= MAX_PLAYERS );
if ( !bValid )
{
Assert( bValid );
return TEAM_UNASSIGNED;
}
int iTeam = BaseClass::GetTeam( iIndex );
if ( iTeam == TEAM_UNASSIGNED )
{
// In MvM, force everybody to show as being on the defending team,
// even if they have not picked a team yet
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
{
iTeam = TF_TEAM_PVE_DEFENDERS;
}
}
return iTeam;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
MM_PlayerConnectionState_t C_TF_PlayerResource::GetPlayerConnectionState( int iIndex ) const
{
if ( !iIndex || ( iIndex > MAX_PLAYERS ) )
return MM_DISCONNECTED;
return m_iConnectionState[iIndex];
}
//-----------------------------------------------------------------------------
// Purpose: Gets a value from an array member
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetArrayValue( int iIndex, int *pArray, int iDefaultVal )
{
if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
return iDefaultVal;
return pArray[iIndex];
}
//-----------------------------------------------------------------------------
// Purpose: Gets a streak value
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetStreak( unsigned int iIndex, CTFPlayerShared::ETFStreak streak_type )
{
if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
return 0;
return m_iStreaks[ iIndex * CTFPlayerShared::kTFStreak_COUNT + streak_type ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetNumRespecCredits( uint32 unIndex )
{
if ( !unIndex || unIndex > MAX_PLAYERS )
return 0;
if ( !tf_mvm_respec_limit.GetBool() )
return 1;
return GetArrayValue( unIndex, m_iUpgradeRefundCredits, 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetNumBuybackCredits( uint32 unIndex )
{
if ( !unIndex || unIndex > MAX_PLAYERS )
return 0;
if ( !tf_mvm_buybacks_method.GetBool() )
return 0;
return GetArrayValue( unIndex, m_iBuybackCredits, 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetCountForPlayerClass( int iTeam, int iClass, bool bExcludeLocalPlayer /*=false*/ )
{
int count = 0;
int iLocalPlayerIndex = GetLocalPlayerIndex();
for ( int i = 1 ; i <= MAX_PLAYERS ; i++ )
{
if ( bExcludeLocalPlayer && ( i == iLocalPlayerIndex ) )
{
continue;
}
if ( ( GetTeam( i ) == iTeam ) && ( GetPlayerClass( i ) == iClass ) )
{
count++;
}
}
return count;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetNumPlayersForTeam( int iTeam, bool bAliveOnly )
{
int count = 0;
for ( int playerIndex = 1 ; playerIndex <= MAX_PLAYERS; playerIndex++ )
{
if ( IsConnected( playerIndex ) )
{
if ( GetTeam( playerIndex ) == iTeam )
{
if ( bAliveOnly && !IsAlive( playerIndex ) )
continue;
count++;
}
}
}
return count;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetDamage( unsigned int nIndex )
{
Assert( nIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
return GetArrayValue( nIndex, m_iDamage, 0 ) + m_aPlayerScoreStats[nIndex].m_iPrevDamage;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetDamageAssist( unsigned int nIndex )
{
Assert( nIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
return GetArrayValue( nIndex, m_iDamageAssist, 0 ) + m_aPlayerScoreStats[nIndex].m_iPrevDamageAssist;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetDamageBoss( unsigned int nIndex )
{
Assert( nIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
return GetArrayValue( nIndex, m_iDamageBoss, 0 ) + m_aPlayerScoreStats[nIndex].m_iPrevDamageBoss;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetHealing( unsigned int nIndex )
{
Assert( nIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
return GetArrayValue( nIndex, m_iHealing, 0 ) + m_aPlayerScoreStats[nIndex].m_iPrevHealing;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetHealingAssist( unsigned int nIndex )
{
Assert( nIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
return GetArrayValue( nIndex, m_iHealingAssist, 0 ) + m_aPlayerScoreStats[nIndex].m_iPrevHealingAssist;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetDamageBlocked( unsigned int nIndex )
{
Assert( nIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
return GetArrayValue( nIndex, m_iDamageBlocked, 0 ) + m_aPlayerScoreStats[nIndex].m_iPrevDamageBlocked;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetCurrencyCollected( unsigned int nIndex )
{
Assert( nIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
return GetArrayValue( nIndex, m_iCurrencyCollected, 0 ) + m_aPlayerScoreStats[nIndex].m_iPrevCurrencyCollected;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TF_PlayerResource::GetBonusPoints( unsigned int nIndex )
{
Assert( nIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
return GetArrayValue( nIndex, m_iBonusPoints, 0 ) + m_aPlayerScoreStats[nIndex].m_iPrevBonusPoints;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TF_PlayerResource::UpdatePlayerScoreStats( void )
{
for ( int playerIndex = 0; playerIndex < ARRAYSIZE( m_aPlayerScoreStats ); playerIndex++ )
{
// Add current round stats to the accumulator
m_aPlayerScoreStats[playerIndex].m_iPrevDamage += GetArrayValue( playerIndex, m_iDamage, 0 );
m_aPlayerScoreStats[playerIndex].m_iPrevDamageAssist += GetArrayValue( playerIndex, m_iDamageAssist, 0 );
m_aPlayerScoreStats[playerIndex].m_iPrevDamageBoss += GetArrayValue( playerIndex, m_iDamageBoss, 0 );
m_aPlayerScoreStats[playerIndex].m_iPrevHealing += GetArrayValue( playerIndex, m_iHealing, 0 );
m_aPlayerScoreStats[playerIndex].m_iPrevHealingAssist += GetArrayValue( playerIndex, m_iHealingAssist, 0 );
m_aPlayerScoreStats[playerIndex].m_iPrevDamageBlocked += GetArrayValue( playerIndex, m_iDamageBlocked, 0 );
m_aPlayerScoreStats[playerIndex].m_iPrevCurrencyCollected += GetArrayValue( playerIndex, m_iCurrencyCollected, 0 );
m_aPlayerScoreStats[playerIndex].m_iPrevBonusPoints += GetArrayValue( playerIndex, m_iBonusPoints, 0 );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TF_PlayerResource::ResetPlayerScoreStats( int playerIndex /*= -1*/ )
{
if ( playerIndex == -1 )
{
Q_memset( m_aPlayerScoreStats, 0, sizeof( m_aPlayerScoreStats ) );
}
else
{
// valid playerIndex should be 1-33 (32 players)
Assert( playerIndex > 0 && playerIndex < ARRAYSIZE( m_aPlayerScoreStats ) );
m_aPlayerScoreStats[playerIndex].m_iPrevDamage = 0;
m_aPlayerScoreStats[playerIndex].m_iPrevDamageAssist = 0;
m_aPlayerScoreStats[playerIndex].m_iPrevDamageBoss = 0;
m_aPlayerScoreStats[playerIndex].m_iPrevHealing = 0;
m_aPlayerScoreStats[playerIndex].m_iPrevHealingAssist = 0;
m_aPlayerScoreStats[playerIndex].m_iPrevDamageBlocked = 0;
m_aPlayerScoreStats[playerIndex].m_iPrevCurrencyCollected = 0;
m_aPlayerScoreStats[playerIndex].m_iPrevBonusPoints = 0;
}
}
+128
View File
@@ -0,0 +1,128 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: TF's custom C_PlayerResource
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_TF_PLAYERRESOURCE_H
#define C_TF_PLAYERRESOURCE_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_shareddefs.h"
#include "c_playerresource.h"
#include "tf_player_shared.h"
class C_TF_PlayerResource : public C_PlayerResource
{
DECLARE_CLASS( C_TF_PlayerResource, C_PlayerResource );
public:
DECLARE_CLIENTCLASS();
C_TF_PlayerResource();
virtual ~C_TF_PlayerResource();
virtual int GetTeam( int index ) OVERRIDE;
int GetTotalScore( int iIndex ) { return GetArrayValue( iIndex, m_iTotalScore, 0 ); }
int GetMaxHealth( int iIndex ) { return GetArrayValue( iIndex, m_iMaxHealth, TF_HEALTH_UNDEFINED ); }
int GetMaxHealthForBuffing( int iIndex ) { return GetArrayValue( iIndex, m_iMaxBuffedHealth, TF_HEALTH_UNDEFINED ); }
int GetPlayerClass( int iIndex ) { return GetArrayValue( iIndex, m_iPlayerClass, TF_CLASS_UNDEFINED ); }
int GetActiveDominations( int iIndex ) { return GetArrayValue( iIndex, m_iActiveDominations, 0 ); }
float GetNextRespawnTime( int iIndex ) { return (IsConnected(iIndex) ? m_flNextRespawnTime[iIndex] : 0); }
int GetChargeLevel( int iIndex ) { return GetArrayValue( iIndex, m_iChargeLevel, 0 ); }
int GetDamage( unsigned int nIndex );
int GetDamageAssist( unsigned int nIndex );
int GetDamageBoss( unsigned int nIndex );
int GetHealing( unsigned int nIndex );
int GetHealingAssist( unsigned int nIndex );
int GetDamageBlocked( unsigned int nIndex );
int GetCurrencyCollected( unsigned int nIndex );
int GetBonusPoints( unsigned int nIndex );
int GetPlayerLevel( unsigned int nIndex ) { return GetArrayValue( nIndex, m_iPlayerLevel, 0 ); }
int GetStreak( unsigned int nIndex, CTFPlayerShared::ETFStreak streak_type );
int GetNumRespecCredits( uint32 unIndex );
int GetNumBuybackCredits( uint32 unIndex );
void UpdatePlayerScoreStats( void );
void ResetPlayerScoreStats( int playerIndex = -1 );
bool IsArenaSpectator( int iIndex )
{
if ( !IsConnected( iIndex ) )
{
return false;
}
return m_bArenaSpectator[iIndex];
}
int GetCountForPlayerClass( int iTeam, int iClass, bool bExcludeLocalPlayer = false );
int GetNumPlayersForTeam( int iTeam, bool bAliveOnly );
bool HasPremadeParties(){ return ( ( m_iPartyLeaderRedTeamIndex > 0 ) && ( m_iPartyLeaderBlueTeamIndex > 0 ) ); }
int GetPartyLeaderRedTeamIndex(){ return m_iPartyLeaderRedTeamIndex; }
int GetPartyLeaderBlueTeamIndex(){ return m_iPartyLeaderBlueTeamIndex; }
int GetEventTeamStatus() { return m_iEventTeamStatus; }
int GetPlayerClassWhenKilled( int iIndex ) { return GetArrayValue( iIndex, m_iPlayerClassWhenKilled, TF_CLASS_UNDEFINED ); }
MM_PlayerConnectionState_t GetPlayerConnectionState( int iIndex ) const;
protected:
int GetArrayValue( int iIndex, int *pArray, int defaultVal );
int m_iTotalScore[MAX_PLAYERS+1];
int m_iMaxHealth[MAX_PLAYERS+1];
// !! This is actually m_iMaxHealthForBuffing, but we can't fix it now because of demos :-/
int m_iMaxBuffedHealth[MAX_PLAYERS+1];
int m_iPlayerClass[MAX_PLAYERS+1];
bool m_bArenaSpectator[MAX_PLAYERS+1];
int m_iActiveDominations[MAX_PLAYERS+1];
// These variables are only networked in tournament mode
float m_flNextRespawnTime[MAX_PLAYERS+1];
int m_iChargeLevel[MAX_PLAYERS+1];
private:
int m_iDamage[MAX_PLAYERS+1];
int m_iDamageAssist[MAX_PLAYERS+1];
int m_iDamageBoss[MAX_PLAYERS+1];
int m_iHealing[MAX_PLAYERS+1];
int m_iHealingAssist[MAX_PLAYERS+1];
int m_iDamageBlocked[MAX_PLAYERS+1];
int m_iCurrencyCollected[MAX_PLAYERS+1];
int m_iBonusPoints[MAX_PLAYERS+1];
int m_iPlayerLevel[MAX_PLAYERS+1];
// Pseudo multidimensional array [MAX_PLAYERS + 1][CTFPlayerShared::kTFStreak_COUNT]
int m_iStreaks[(MAX_PLAYERS+1) * CTFPlayerShared::kTFStreak_COUNT];
int m_iUpgradeRefundCredits[MAX_PLAYERS + 1];
int m_iBuybackCredits[MAX_PLAYERS + 1];
int m_iPartyLeaderBlueTeamIndex;
int m_iPartyLeaderRedTeamIndex;
int m_iEventTeamStatus;
int m_iPlayerClassWhenKilled[MAX_PLAYERS+1];
MM_PlayerConnectionState_t m_iConnectionState[MAX_PLAYERS+1];
struct PlayerScoreboardStats_t
{
int m_iPrevDamage;
int m_iPrevDamageAssist;
int m_iPrevDamageBoss;
int m_iPrevHealing;
int m_iPrevHealingAssist;
int m_iPrevDamageBlocked;
int m_iPrevCurrencyCollected;
int m_iPrevBonusPoints;
};
PlayerScoreboardStats_t m_aPlayerScoreStats[MAX_PLAYERS+1];
};
extern C_TF_PlayerResource *g_TF_PR;
#endif // C_TF_PLAYERRESOURCE_H
+375
View File
@@ -0,0 +1,375 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "c_tf_projectile_arrow.h"
#include "particles_new.h"
#include "SpriteTrail.h"
#include "c_tf_player.h"
#include "collisionutils.h"
#include "util_shared.h"
#include "c_rope.h"
//-----------------------------------------------------------------------------
IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_Arrow, DT_TFProjectile_Arrow )
BEGIN_NETWORK_TABLE( C_TFProjectile_Arrow, DT_TFProjectile_Arrow )
RecvPropBool( RECVINFO( m_bArrowAlight ) ),
RecvPropBool( RECVINFO( m_bCritical ) ),
RecvPropInt( RECVINFO( m_iProjectileType ) ),
END_NETWORK_TABLE()
//-----------------------------------------------------------------------------
IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_HealingBolt, DT_TFProjectile_HealingBolt )
BEGIN_NETWORK_TABLE( C_TFProjectile_HealingBolt, DT_TFProjectile_HealingBolt )
END_NETWORK_TABLE()
IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_GrapplingHook, DT_TFProjectile_GrapplingHook )
BEGIN_NETWORK_TABLE( C_TFProjectile_GrapplingHook, DT_TFProjectile_GrapplingHook )
END_NETWORK_TABLE()
#define NEAR_MISS_THRESHOLD 120
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFProjectile_Arrow::C_TFProjectile_Arrow( void )
{
m_fAttachTime = 0.f;
m_nextNearMissCheck = 0.f;
m_bNearMiss = false;
m_bArrowAlight = false;
m_bCritical = true;
m_pCritEffect = NULL;
m_iCachedDeflect = false;
m_flLifeTime = 40.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFProjectile_Arrow::~C_TFProjectile_Arrow( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Arrow::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
#ifdef STAGING_ONLY
if ( m_iProjectileType == TF_PROJECTILE_SNIPERBULLET )
{
switch ( GetTeamNumber() )
{
case TF_TEAM_BLUE:
ParticleProp()->Create( "bullet_distortion_trail", PATTACH_ABSORIGIN_FOLLOW );
break;
case TF_TEAM_RED:
ParticleProp()->Create( "bullet_distortion_trail", PATTACH_ABSORIGIN_FOLLOW );
break;
}
}
else if ( m_bArrowAlight )
#else
if ( m_bArrowAlight )
#endif // STAGING_ONLY
{
ParticleProp()->Create( "flying_flaming_arrow", PATTACH_POINT_FOLLOW, "muzzle" );
}
}
if ( m_bCritical )
{
if ( updateType == DATA_UPDATE_CREATED || m_iCachedDeflect != GetDeflected() )
{
CreateCritTrail();
}
}
m_iCachedDeflect = GetDeflected();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Arrow::NotifyBoneAttached( C_BaseAnimating* attachTarget )
{
BaseClass::NotifyBoneAttached( attachTarget );
m_fAttachTime = gpGlobals->curtime;
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Arrow::ClientThink( void )
{
// Perform a near-miss check.
if ( !m_bNearMiss && (gpGlobals->curtime > m_nextNearMissCheck) )
{
CheckNearMiss();
m_nextNearMissCheck = gpGlobals->curtime + 0.05f;
}
// Remove crit effect if we hit a wall.
if ( GetMoveType() == MOVETYPE_NONE && m_pCritEffect )
{
ParticleProp()->StopEmission( m_pCritEffect );
m_pCritEffect = NULL;
}
BaseClass::ClientThink();
// DO THIS LAST: Destroy us automatically after a period of time.
if ( m_pAttachedTo )
{
if ( gpGlobals->curtime - m_fAttachTime > m_flLifeTime )
{
Release();
return;
}
else if ( m_pAttachedTo->IsEffectActive( EF_NODRAW ) && !IsEffectActive( EF_NODRAW ) )
{
AddEffects( EF_NODRAW );
UpdateVisibility();
}
else if ( !m_pAttachedTo->IsEffectActive( EF_NODRAW ) && IsEffectActive( EF_NODRAW ) && (m_pAttachedTo != C_BasePlayer::GetLocalPlayer()) )
{
RemoveEffects( EF_NODRAW );
UpdateVisibility();
}
}
if ( IsDormant() && !IsEffectActive( EF_NODRAW ) )
{
AddEffects( EF_NODRAW );
UpdateVisibility();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Arrow::CheckNearMiss( void )
{
// Check against the local player. If we're near him play a near miss sound.
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pLocalPlayer || !pLocalPlayer->IsAlive() )
return;
// If we are attached to something or stationary we don't want to do near miss checks.
if ( m_pAttachedTo || (GetMoveType() == MOVETYPE_NONE) )
{
m_bNearMiss = true;
return;
}
// Can't hear near miss sounds from friendly arrows.
if ( pLocalPlayer->GetTeamNumber() == GetTeamNumber() )
return;
Vector vecPlayerPos = pLocalPlayer->GetAbsOrigin();
Vector vecArrowPos = GetAbsOrigin(), forward;
AngleVectors( GetAbsAngles(), &forward );
Vector vecArrowDest = GetAbsOrigin() + forward * 200.f;
// If the arrow is moving away from the player just stop checking.
float dist1 = vecArrowPos.DistToSqr( vecPlayerPos );
float dist2 = vecArrowDest.DistToSqr( vecPlayerPos );
if ( dist2 > dist1 )
{
m_bNearMiss = true;
return;
}
// Check to see if the arrow is passing near the player.
Vector vecClosestPoint;
float dist;
CalcClosestPointOnLineSegment( vecPlayerPos, vecArrowPos, vecArrowDest, vecClosestPoint, &dist );
dist = vecPlayerPos.DistTo( vecClosestPoint );
if ( dist > NEAR_MISS_THRESHOLD )
return;
// The arrow is passing close to the local player.
m_bNearMiss = true;
SetNextClientThink( CLIENT_THINK_NEVER );
// If the arrow is about to hit something, don't play the sound and stop this check.
trace_t tr;
UTIL_TraceLine( vecArrowPos, vecArrowPos + forward * 400.f, CONTENTS_HITBOX|CONTENTS_MONSTER|CONTENTS_SOLID, this, COLLISION_GROUP_NONE, &tr );
if ( tr.DidHit() )
return;
// We're good for a near miss!
float soundlen = 0;
EmitSound_t params;
params.m_flSoundTime = 0;
params.m_pSoundName = "Weapon_Arrow.Nearmiss";
params.m_pflSoundDuration = &soundlen;
CSingleUserRecipientFilter localFilter( pLocalPlayer );
EmitSound( localFilter, pLocalPlayer->entindex(), params );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Arrow::CreateCritTrail( void )
{
if ( IsDormant() )
return;
if ( m_pCritEffect )
{
ParticleProp()->StopEmission( m_pCritEffect );
m_pCritEffect = NULL;
}
if ( m_bCritical )
{
switch( GetTeamNumber() )
{
case TF_TEAM_BLUE:
m_pCritEffect = ParticleProp()->Create( "critical_rocket_blue", PATTACH_ABSORIGIN_FOLLOW );
break;
case TF_TEAM_RED:
m_pCritEffect = ParticleProp()->Create( "critical_rocket_red", PATTACH_ABSORIGIN_FOLLOW );
break;
default:
break;
}
}
}
//-----------------------------------------------------------------------------
void C_TFProjectile_HealingBolt::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
switch( GetTeamNumber() )
{
case TF_TEAM_BLUE:
ParticleProp()->Create( "healshot_trail_blue", PATTACH_ABSORIGIN_FOLLOW );
break;
case TF_TEAM_RED:
ParticleProp()->Create( "healshot_trail_red", PATTACH_ABSORIGIN_FOLLOW );
break;
}
}
BaseClass::OnDataChanged( updateType );
}
void C_TFProjectile_GrapplingHook::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
int nTeam = GetTeamNumber();
C_TFPlayer *pTFPlayer = ToTFPlayer( GetOwnerEntity() );
if ( pTFPlayer && pTFPlayer->IsPlayerClass( TF_CLASS_SPY ) && pTFPlayer->m_Shared.InCond( TF_COND_DISGUISED ) && pTFPlayer->GetTeamNumber() != GetLocalPlayerTeam() )
{
nTeam = pTFPlayer->m_Shared.GetDisguiseTeam();
}
const char *pszMaterialName = "cable/cable";
switch ( nTeam )
{
case TF_TEAM_BLUE:
pszMaterialName = "cable/cable_blue";
break;
case TF_TEAM_RED:
pszMaterialName = "cable/cable_red";
break;
}
C_BaseEntity *pStartEnt = GetOwnerEntity();
int iAttachment = 0;
if ( pTFPlayer )
{
CTFWeaponBase *pWeapon = assert_cast< CTFWeaponBase* >( pTFPlayer->GetActiveWeapon() );
if ( pWeapon )
{
pStartEnt = pWeapon;
int iMuzzle = pWeapon->LookupAttachment( "muzzle" );
if ( iMuzzle != -1 )
{
iAttachment = iMuzzle;
}
}
}
int iHookAttachment = LookupAttachment( "rope_locator" );
if ( iHookAttachment == -1 )
iHookAttachment = 0;
m_hRope = C_RopeKeyframe::Create( pStartEnt, this, iAttachment, iHookAttachment, 2, pszMaterialName );
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
void C_TFProjectile_GrapplingHook::UpdateOnRemove()
{
RemoveRope();
BaseClass::UpdateOnRemove();
}
void C_TFProjectile_GrapplingHook::ClientThink()
{
UpdateRope();
}
void C_TFProjectile_GrapplingHook::UpdateRope()
{
C_TFPlayer *pTFPlayer = ToTFPlayer( GetOwnerEntity() );
if ( !pTFPlayer || !pTFPlayer->IsAlive() )
{
RemoveRope();
return;
}
Vector vecStart = pTFPlayer->WorldSpaceCenter();
if ( pTFPlayer->GetActiveWeapon() )
{
int iAttachment = pTFPlayer->GetActiveWeapon()->LookupAttachment( "muzzle" );
if ( iAttachment != -1 )
{
GetAttachment( iAttachment, vecStart );
}
}
float flDist = vecStart.DistTo( WorldSpaceCenter() );
if ( m_hRope )
{
float flHangDist = pTFPlayer->GetGrapplingHookTarget() ? 0.1f * flDist : 1.5f * flDist;
assert_cast< C_RopeKeyframe* >( m_hRope.Get() )->SetupHangDistance( flHangDist );
}
}
void C_TFProjectile_GrapplingHook::RemoveRope()
{
if ( m_hRope )
{
m_hRope->Release();
m_hRope = NULL;
}
}
+89
View File
@@ -0,0 +1,89 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_TF_PROJECTILE_ARROW_H
#define C_TF_PROJECTILE_ARROW_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_weaponbase_rocket.h"
#define CTFProjectile_Arrow C_TFProjectile_Arrow
//-----------------------------------------------------------------------------
// Purpose: Arrow projectile.
//-----------------------------------------------------------------------------
class C_TFProjectile_Arrow : public C_TFBaseRocket
{
DECLARE_CLASS( C_TFProjectile_Arrow, C_TFBaseRocket );
public:
DECLARE_NETWORKCLASS();
C_TFProjectile_Arrow();
~C_TFProjectile_Arrow();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void NotifyBoneAttached( C_BaseAnimating* attachTarget );
virtual void ClientThink( void );
void CheckNearMiss( void );
void CreateCritTrail( void );
void SetLifeTime( float flLifetime ) { m_flLifeTime = flLifetime; }
private:
float m_fAttachTime;
float m_nextNearMissCheck;
bool m_bNearMiss;
bool m_bArrowAlight;
bool m_bCritical;
CNewParticleEffect *m_pCritEffect;
int m_iCachedDeflect;
float m_flLifeTime;
CNetworkVar( int, m_iProjectileType );
};
//-----------------------------------------------------------------------------
// Purpose: Arrow projectile.
//-----------------------------------------------------------------------------
class C_TFProjectile_HealingBolt : public C_TFProjectile_Arrow
{
DECLARE_CLASS( C_TFProjectile_HealingBolt, C_TFProjectile_Arrow );
virtual void OnDataChanged( DataUpdateType_t updateType );
public:
DECLARE_NETWORKCLASS();
};
//-----------------------------------------------------------------------------
// Purpose: Grappling Hook projectile.
//-----------------------------------------------------------------------------
class C_TFProjectile_GrapplingHook : public C_TFProjectile_Arrow
{
DECLARE_CLASS( C_TFProjectile_GrapplingHook, C_TFProjectile_Arrow );
public:
DECLARE_NETWORKCLASS();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void UpdateOnRemove();
virtual void ClientThink();
private:
void UpdateRope();
void RemoveRope();
CHandle< C_RopeKeyframe > m_hRope;
};
#endif // C_TF_PROJECTILE_ARROW_H
@@ -0,0 +1,98 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "c_tf_projectile_energy_ball.h"
#include "particles_new.h"
#include "SpriteTrail.h"
#include "c_tf_player.h"
#include "collisionutils.h"
#include "util_shared.h"
#include "tf_weapon_rocketlauncher.h"
//-----------------------------------------------------------------------------
IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_EnergyBall, DT_TFProjectile_EnergyBall )
BEGIN_NETWORK_TABLE( C_TFProjectile_EnergyBall, DT_TFProjectile_EnergyBall )
RecvPropBool( RECVINFO( m_bChargedShot ) ),
RecvPropVector( RECVINFO( m_vColor1 ) ),
RecvPropVector( RECVINFO( m_vColor2 ) )
END_NETWORK_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFProjectile_EnergyBall::C_TFProjectile_EnergyBall( void )
{
pEffect = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFProjectile_EnergyBall::~C_TFProjectile_EnergyBall( void )
{
if ( pEffect )
{
ParticleProp()->StopEmission( pEffect );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_EnergyBall::CreateTrails( void )
{
if ( IsDormant() )
return;
if ( pEffect )
{
ParticleProp()->StopEmission( pEffect );
pEffect = NULL;
}
bool bDeflected = m_iCachedDeflect != GetDeflected();
if ( pEffect == NULL )
{
ParticleProp()->Init( this );
pEffect = ParticleProp()->Create( GetTrailParticleName(), PATTACH_ABSORIGIN_FOLLOW, 0 );
if ( pEffect )
{
if ( bDeflected )
{
if ( GetTeamNumber() == TF_TEAM_BLUE )
{
pEffect->SetControlPoint( CUSTOM_COLOR_CP1, TF_PARTICLE_WEAPON_BLUE_1 );
pEffect->SetControlPoint( CUSTOM_COLOR_CP2, TF_PARTICLE_WEAPON_BLUE_2 );
}
else
{
pEffect->SetControlPoint( CUSTOM_COLOR_CP1, TF_PARTICLE_WEAPON_RED_1 );
pEffect->SetControlPoint( CUSTOM_COLOR_CP2, TF_PARTICLE_WEAPON_RED_2 );
}
}
else
{
pEffect->SetControlPoint( CUSTOM_COLOR_CP1, m_vColor1 );
pEffect->SetControlPoint( CUSTOM_COLOR_CP2, m_vColor2 );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_TFProjectile_EnergyBall::GetTrailParticleName( void )
{
if ( m_bChargedShot )
return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_rockettrail_charged" : "drg_cow_rockettrail_charged_blue";
else
return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_rockettrail_normal" : "drg_cow_rockettrail_normal_blue";
}
@@ -0,0 +1,42 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_TF_PROJECTILE_ENERGY_BALL_H
#define C_TF_PROJECTILE_ENERGY_BALL_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_weaponbase_rocket.h"
#define CTFProjectile_EnergyBall C_TFProjectile_EnergyBall
//-----------------------------------------------------------------------------
// Purpose: EnergyBall projectile.
//-----------------------------------------------------------------------------
class C_TFProjectile_EnergyBall : public C_TFBaseRocket
{
DECLARE_CLASS( C_TFProjectile_EnergyBall, C_TFBaseRocket );
public:
DECLARE_NETWORKCLASS();
C_TFProjectile_EnergyBall();
~C_TFProjectile_EnergyBall();
virtual void CreateTrails( void );
virtual const char *GetTrailParticleName( void );
private:
CNewParticleEffect *pEffect;
bool m_bChargedShot;
Vector m_vColor1;
Vector m_vColor2;
};
#endif // C_TF_PROJECTILE_ENERGY_BALL_H
+108
View File
@@ -0,0 +1,108 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "c_tf_projectile_flare.h"
#include "tf_weapon_flaregun.h"
#include "c_tf_player.h"
#include "particles_new.h"
IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_Flare, DT_TFProjectile_Flare )
BEGIN_NETWORK_TABLE( C_TFProjectile_Flare, DT_TFProjectile_Flare )
RecvPropBool( RECVINFO( m_bCritical ) ),
END_NETWORK_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFProjectile_Flare::C_TFProjectile_Flare( void )
{
pEffect = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFProjectile_Flare::~C_TFProjectile_Flare( void )
{
if ( pEffect )
{
ParticleProp()->StopEmission( pEffect );
pEffect = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Flare::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
CreateTrails();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *GetFlareTrailParticleName( int iTeamNumber, bool bCritical, int nType )
{
if ( nType == FLAREGUN_GRORDBORT )
{
return "drg_manmelter_projectile";
}
else if ( nType == FLAREGUN_SCORCHSHOT )
{
if ( iTeamNumber == TF_TEAM_BLUE )
{
return ( bCritical ? "scorchshot_trail_crit_blue" : "scorchshot_trail_blue" );
}
else
{
return ( bCritical ? "scorchshot_trail_crit_red" : "scorchshot_trail_red" );
}
}
else
{
if ( iTeamNumber == TF_TEAM_BLUE )
{
return ( bCritical ? "flaregun_trail_crit_blue" : "flaregun_trail_blue" );
}
else
{
return ( bCritical ? "flaregun_trail_crit_red" : "flaregun_trail_red" );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Flare::CreateTrails( void )
{
if ( IsDormant() )
return;
if ( pEffect )
{
ParticleProp()->StopEmission( pEffect );
pEffect = NULL;
}
int nType = 0;
C_TFFlareGun *pFlareGun = dynamic_cast< C_TFFlareGun* >( GetLauncher() );
if ( pFlareGun )
{
nType = pFlareGun->GetFlareGunType();
}
pEffect = ParticleProp()->Create( GetFlareTrailParticleName( GetTeamNumber(), m_bCritical, nType ), PATTACH_ABSORIGIN_FOLLOW );
}
+41
View File
@@ -0,0 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_TF_PROJECTILE_FLARE_H
#define C_TF_PROJECTILE_FLARE_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_weaponbase_rocket.h"
#define CTFProjectile_Flare C_TFProjectile_Flare
//-----------------------------------------------------------------------------
// Purpose: Flare projectile.
//-----------------------------------------------------------------------------
class C_TFProjectile_Flare : public C_TFBaseRocket
{
DECLARE_CLASS( C_TFProjectile_Flare, C_TFBaseRocket );
public:
DECLARE_NETWORKCLASS();
C_TFProjectile_Flare();
~C_TFProjectile_Flare();
virtual void OnDataChanged( DataUpdateType_t updateType );
void CreateTrails( void );
private:
bool m_bCritical;
CNewParticleEffect *pEffect;
};
#endif // C_TF_PROJECTILE_FLARE_H
+144
View File
@@ -0,0 +1,144 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "c_tf_projectile_rocket.h"
#include "particles_new.h"
#include "tf_gamerules.h"
IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_Rocket, DT_TFProjectile_Rocket )
BEGIN_NETWORK_TABLE( C_TFProjectile_Rocket, DT_TFProjectile_Rocket )
RecvPropBool( RECVINFO( m_bCritical ) ),
END_NETWORK_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFProjectile_Rocket::C_TFProjectile_Rocket( void )
{
pEffect = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFProjectile_Rocket::~C_TFProjectile_Rocket( void )
{
if ( pEffect )
{
ParticleProp()->StopEmission( pEffect );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Rocket::OnDataChanged(DataUpdateType_t updateType)
{
BaseClass::OnDataChanged(updateType);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFProjectile_Rocket::CreateTrails( void )
{
if ( IsDormant() )
return;
bool bUsingCustom = false;
if ( pEffect )
{
ParticleProp()->StopEmission( pEffect );
pEffect = NULL;
}
int iAttachment = LookupAttachment( "trail" );
if ( iAttachment == INVALID_PARTICLE_ATTACHMENT )
return;
if ( enginetrace->GetPointContents( GetAbsOrigin() ) & MASK_WATER )
{
ParticleProp()->Create( "rockettrail_underwater", PATTACH_POINT_FOLLOW, "trail" );
bUsingCustom = true;
}
else if ( GetTeamNumber() == TEAM_UNASSIGNED )
{
ParticleProp()->Create( "rockettrail_underwater", PATTACH_POINT_FOLLOW, "trail" );
bUsingCustom = true;
}
else
{
// Halloween Spell Effect Check
int iHalloweenSpell = 0;
// if the owner is a Sentry, Check its owner
CBaseObject *pSentry = GetOwnerEntity() && GetOwnerEntity()->IsBaseObject() ? assert_cast<CBaseObject*>( GetOwnerEntity() ) : NULL;
if ( TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) )
{
if ( pSentry )
{
CALL_ATTRIB_HOOK_INT_ON_OTHER( pSentry->GetOwner(), iHalloweenSpell, halloween_pumpkin_explosions );
}
else
{
CALL_ATTRIB_HOOK_INT_ON_OTHER( GetOwnerEntity(), iHalloweenSpell, halloween_pumpkin_explosions );
}
}
// Mini rockets from airstrike RL
if ( iHalloweenSpell > 0 )
{
ParticleProp()->Create( "halloween_rockettrail", PATTACH_POINT_FOLLOW, iAttachment );
bUsingCustom = true;
}
else if ( !pSentry )
{
if ( GetLauncher() )
{
int iMiniRocket = 0;
CALL_ATTRIB_HOOK_INT_ON_OTHER( GetLauncher(), iMiniRocket, mini_rockets );
if ( iMiniRocket )
{
ParticleProp()->Create( "rockettrail_airstrike", PATTACH_POINT_FOLLOW, iAttachment );
bUsingCustom = true;
// rockettrail_airstrike_line
CTFPlayer *pPlayer = ToTFPlayer( GetOwnerEntity() );
if ( pPlayer && pPlayer->m_Shared.InCond( TF_COND_BLASTJUMPING ) )
{
ParticleProp()->Create( "rockettrail_airstrike_line", PATTACH_POINT_FOLLOW, iAttachment );
}
}
}
}
}
if ( !bUsingCustom )
{
if ( GetTrailParticleName() )
{
ParticleProp()->Create( GetTrailParticleName(), PATTACH_POINT_FOLLOW, iAttachment );
}
}
if ( m_bCritical )
{
switch( GetTeamNumber() )
{
case TF_TEAM_BLUE:
pEffect = ParticleProp()->Create( "critical_rocket_blue", PATTACH_ABSORIGIN_FOLLOW );
break;
case TF_TEAM_RED:
pEffect = ParticleProp()->Create( "critical_rocket_red", PATTACH_ABSORIGIN_FOLLOW );
break;
default:
pEffect = ParticleProp()->Create( "eyeboss_projectile", PATTACH_ABSORIGIN_FOLLOW );
break;
}
}
}
+40
View File
@@ -0,0 +1,40 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef C_TF_PROJECTILE_ROCKET_H
#define C_TF_PROJECTILE_ROCKET_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_weaponbase_rocket.h"
#define CTFProjectile_Rocket C_TFProjectile_Rocket
//-----------------------------------------------------------------------------
// Purpose: Rocket projectile.
//-----------------------------------------------------------------------------
class C_TFProjectile_Rocket : public C_TFBaseRocket
{
DECLARE_CLASS( C_TFProjectile_Rocket, C_TFBaseRocket );
public:
DECLARE_NETWORKCLASS();
C_TFProjectile_Rocket();
~C_TFProjectile_Rocket();
virtual void OnDataChanged(DataUpdateType_t updateType);
virtual void CreateTrails( void );
virtual const char *GetTrailParticleName( void ) { return "rockettrail"; }
private:
bool m_bCritical;
CNewParticleEffect *pEffect;
};
#endif // C_TF_PROJECTILE_ROCKET_H
+240
View File
@@ -0,0 +1,240 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: TF version of the stickybolt code.
// I broke off our own version because I didn't want to accidentally break HL2.
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basetempentity.h"
#include "fx.h"
#include "decals.h"
#include "iefx.h"
#include "engine/IEngineSound.h"
#include "materialsystem/imaterialvar.h"
#include "IEffects.h"
#include "engine/IEngineTrace.h"
#include "vphysics/constraints.h"
#include "engine/ivmodelinfo.h"
#include "tempent.h"
#include "c_te_legacytempents.h"
#include "engine/ivdebugoverlay.h"
#include "c_te_effect_dispatch.h"
#include "c_tf_player.h"
#include "GameEventListener.h"
#include "tf_shareddefs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern IPhysicsSurfaceProps *physprops;
IPhysicsObject *GetWorldPhysObject( void );
//-----------------------------------------------------------------------------
// Purpose: Creates a Bolt in the world and Ragdolls
// For Attached Bolts on players look at hud_bowcharge "arrow_impact" which should be moved here
//-----------------------------------------------------------------------------
void CreateCrossbowBoltTF( const Vector &vecOrigin, const Vector &vecDirection, const int iFlags, unsigned char nColor )
{
const char* pszModelName = NULL;
float flDirOffset = 5.0f;
float flScale = 1.0f;
float flLifeTime = 30.0f;
switch ( iFlags )
{
case TF_PROJECTILE_STICKY_BALL:
pszModelName = g_pszArrowModels[MODEL_SNOWBALL];
break;
case TF_PROJECTILE_ARROW:
pszModelName = g_pszArrowModels[MODEL_ARROW_REGULAR];
break;
case TF_PROJECTILE_BUILDING_REPAIR_BOLT:
pszModelName = g_pszArrowModels[MODEL_ARROW_BUILDING_REPAIR];
flDirOffset = -2.0f;
break;
case TF_PROJECTILE_FESTIVE_ARROW:
pszModelName = g_pszArrowModels[MODEL_FESTIVE_ARROW_REGULAR];
break;
case TF_PROJECTILE_HEALING_BOLT:
#ifdef STAGING_ONLY
case TF_PROJECTILE_MILK_BOLT:
#endif
pszModelName = g_pszArrowModels[MODEL_SYRINGE];
flDirOffset = 0.0f;
flScale = 3.0f;
break;
case TF_PROJECTILE_FESTIVE_HEALING_BOLT:
pszModelName = g_pszArrowModels[MODEL_FESTIVE_HEALING_BOLT];
flScale = 2.5f;
break;
case TF_PROJECTILE_BREAD_MONSTER:
case TF_PROJECTILE_BREADMONSTER_JARATE:
case TF_PROJECTILE_BREADMONSTER_MADMILK:
pszModelName = g_pszArrowModels[MODEL_BREAD_MONSTER];
flLifeTime = 8.0f;
flScale = 2.5f;
break;
case TF_PROJECTILE_GRAPPLINGHOOK:
pszModelName = g_pszArrowModels[MODEL_GRAPPLINGHOOK];
flDirOffset = 0.0f;
flLifeTime = 0.1f;
break;
#ifdef STAGING_ONLY
case TF_PROJECTILE_THROWING_KNIFE:
pszModelName = g_pszArrowModels[MODEL_THROWING_KNIFE];
break;
case TF_PROJECTILE_SNIPERBULLET:
pszModelName = g_pszArrowModels[MODEL_SYRINGE];
break;
#endif // STAGING_ONLY
default:
// Unsupported Model
Assert( 0 );
pszModelName = g_pszArrowModels[MODEL_ARROW_REGULAR];
return;
}
model_t *pModel = (model_t *)engine->LoadModel( pszModelName );
QAngle vAngles;
VectorAngles( vecDirection, vAngles );
C_LocalTempEntity *arrow = tempents->SpawnTempModel( pModel, vecOrigin - vecDirection * flDirOffset, vAngles, Vector(0, 0, 0 ), flLifeTime, FTENT_NONE );
if ( arrow )
{
arrow->SetModelScale( flScale );
arrow->m_nSkin = nColor;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void StickRagdollNowTF(
const Vector &vecOrigin,
const Vector &vecDirection,
const ClientEntityHandle_t &entHandle,
const int boneIndexAttached,
const int physicsBoneIndex,
const int iShooterIndex,
const int iHitGroup,
const int iVictim,
const int iFlags,
unsigned char nColor
) {
Ray_t shotRay;
trace_t tr;
UTIL_TraceLine( vecOrigin - vecDirection * 16, vecOrigin + vecDirection * 64, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr );
if ( tr.surface.flags & SURF_SKY )
return;
C_BaseAnimating *pModel = dynamic_cast< C_BaseAnimating * >( entHandle.Get() );
if ( pModel )
{
IPhysicsObject *pPhysicsObject = NULL;
ragdoll_t *pRagdollT = NULL;
if ( pModel->m_pRagdoll )
{
CRagdoll *pCRagdoll = dynamic_cast < CRagdoll * > ( pModel->m_pRagdoll );
if ( pCRagdoll )
{
pRagdollT = pCRagdoll->GetRagdoll();
if ( physicsBoneIndex < pRagdollT->listCount )
{
pPhysicsObject = pRagdollT->list[physicsBoneIndex].pObject;
}
}
}
IPhysicsObject *pReference = GetWorldPhysObject();
if ( pReference == NULL || pPhysicsObject == NULL )
return;
float frand = (float) rand() / VALVE_RAND_MAX;
Vector adjust = vecDirection*7 + vecDirection * frand * 7;
Vector vecBonePos;
QAngle boneAngles;
pPhysicsObject->GetPosition( &vecBonePos, &boneAngles );
QAngle angles;
pPhysicsObject->SetPosition( vecOrigin-adjust, boneAngles, true );
pPhysicsObject->EnableMotion( false );
int nNodeIndex = pRagdollT->list[physicsBoneIndex].parentIndex;
// find largest mass bone
float flTargetMass = 0;
for ( int i = 0; i < pRagdollT->listCount; i++ )
{
flTargetMass = MAX(flTargetMass, pRagdollT->list[i].pObject->GetMass() );
}
// walk the chain of bones from the pinned bone to the root and set each to the max mass
// This helps transmit the impulses required to stabilize the constraint -- it keeps the body from
// leaving the constraint because of some high mass bone hanging at the other end of the chain
while ( nNodeIndex >= 0 )
{
if ( pRagdollT->list[nNodeIndex].pConstraint )
{
float flCurrentMass = pRagdollT->list[nNodeIndex].pObject->GetMass();
flCurrentMass = MAX(flCurrentMass, flTargetMass);
pRagdollT->list[nNodeIndex].pObject->SetMass( flCurrentMass );
}
nNodeIndex = pRagdollT->list[nNodeIndex].parentIndex;
}
}
UTIL_ImpactTrace( &tr, 0 );
CreateCrossbowBoltTF( vecOrigin, vecDirection, iFlags, nColor );
//Achievement stuff.
if ( iHitGroup == HITGROUP_HEAD )
{
CTFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( pLocalPlayer && pLocalPlayer->entindex() == iShooterIndex )
{
CTFPlayer *pVictim = ToTFPlayer( UTIL_PlayerByIndex( iVictim ) );
if ( pVictim && pVictim->IsPlayerClass( TF_CLASS_HEAVYWEAPONS ) )
{
IGameEvent *event = gameeventmanager->CreateEvent( "player_pinned" );
if ( event )
{
gameeventmanager->FireEventClientSide( event );
}
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void StickyBoltCallbackTF( const CEffectData &data )
{
StickRagdollNowTF(
data.m_vOrigin,
data.m_vNormal,
data.m_hEntity,
data.m_nAttachmentIndex,
data.m_nMaterial,
data.m_nHitBox,
data.m_nDamageType,
data.m_nSurfaceProp,
data.m_fFlags,
data.m_nColor
);
}
DECLARE_CLIENT_EFFECT( "TFBoltImpact", StickyBoltCallbackTF );
+60
View File
@@ -0,0 +1,60 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Play VCD on taunt prop
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basecombatcharacter.h"
#include "choreoevent.h"
#include "c_sceneentity.h"
#include "c_tf_taunt_prop.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_TFTauntProp, DT_TFTauntProp, CTFTauntProp )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_TFTauntProp::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget )
{
switch ( event->GetType() )
{
case CChoreoEvent::SEQUENCE:
case CChoreoEvent::GESTURE:
{
// Get the (gesture) sequence.
info->m_nSequence = LookupSequence( event->GetParameters() );
if ( info->m_nSequence < 0 )
return false;
SetSequence( info->m_nSequence );
SetPlaybackRate( 1.0f );
SetCycle( scene->GetTime() / scene->GetDuration() );
}
return true;
default:
return BaseClass::StartSceneEvent( info, scene, event, actor, pTarget );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_TFTauntProp::ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled )
{
switch ( info->m_pEvent->GetType() )
{
case CChoreoEvent::SEQUENCE:
case CChoreoEvent::GESTURE:
//return StopGestureSceneEvent( info, fastKill, canceled );
default:
return BaseClass::ClearSceneEvent( info, fastKill, canceled );
}
}
+23
View File
@@ -0,0 +1,23 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Play VCD on taunt prop
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_TF_TAUNT_PROP_H
#define C_TF_TAUNT_PROP_H
#ifdef _WIN32
#pragma once
#endif
class C_TFTauntProp : public C_BaseCombatCharacter
{
DECLARE_CLASS( C_TFTauntProp, C_BaseCombatCharacter );
public:
DECLARE_CLIENTCLASS();
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, C_BaseEntity *pTarget ) OVERRIDE;
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled ) OVERRIDE;
};
#endif // C_TF_TAUNT_PROP_H
+262
View File
@@ -0,0 +1,262 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side C_TFTeam class
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "engine/IEngineSound.h"
#include "hud.h"
#include "recvproxy.h"
#include "c_tf_team.h"
#include "c_tf_player.h"
#include "tf_shareddefs.h"
#include "tf_gamerules.h"
#include "c_tf_playerresource.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: RecvProxy that converts the Player's object UtlVector to entindexes
//-----------------------------------------------------------------------------
void RecvProxy_TeamObjectList( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_TFTeam *pPlayer = (C_TFTeam*)pStruct;
CBaseHandle *pHandle = (CBaseHandle*)(&(pPlayer->m_aObjects[pData->m_iElement]));
RecvProxy_IntToEHandle( pData, pStruct, pHandle );
}
void RecvProxyArrayLength_TeamObjects( void *pStruct, int objectID, int currentArrayLength )
{
C_TFTeam *pPlayer = (C_TFTeam*)pStruct;
if ( pPlayer->m_aObjects.Count() != currentArrayLength )
{
pPlayer->m_aObjects.SetSize( currentArrayLength );
}
}
IMPLEMENT_CLIENTCLASS_DT( C_TFTeam, DT_TFTeam, CTFTeam )
RecvPropInt( RECVINFO( m_nFlagCaptures ) ),
RecvPropInt( RECVINFO( m_iRole ) ),
RecvPropArray2(
RecvProxyArrayLength_TeamObjects,
RecvPropInt( "team_object_array_element", 0, SIZEOF_IGNORE, 0, RecvProxy_TeamObjectList ),
MAX_PLAYERS * MAX_OBJECTS_PER_PLAYER,
0,
"team_object_array" ),
RecvPropEHandle( RECVINFO( m_hLeader ) ),
END_RECV_TABLE()
#define TEAM_THINK_RATE 0.5f
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFTeam::C_TFTeam()
{
m_nFlagCaptures = 0;
m_bUsingCustomTeamName = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFTeam::~C_TFTeam()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFTeam::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( gpGlobals->curtime + TEAM_THINK_RATE );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
char* C_TFTeam::Get_Name( void )
{
// Use Get_Localized_Name() instead
AssertMsg( false, "Use Get_Localized_Name() instead" );
return "";
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFTeam::ClientThink()
{
BaseClass::ClientThink();
UpdateTeamName();
SetNextClientThink( gpGlobals->curtime + TEAM_THINK_RATE );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFTeam::UpdateTeamName( void )
{
m_bUsingCustomTeamName = false;
const wchar_t *pwzName = NULL;
if ( TFGameRules() && TFGameRules()->IsInTournamentMode() && ( ( m_iTeamNum == TF_TEAM_RED ) || ( m_iTeamNum == TF_TEAM_BLUE ) ) )
{
if ( TFGameRules()->IsCompetitiveMode() )
{
if ( g_TF_PR && ( g_TF_PR->HasPremadeParties() || g_TF_PR->GetEventTeamStatus() ) )
{
wchar_t wszTempName[MAX_TEAM_NAME_LENGTH];
wchar_t *pFormat = g_pVGuiLocalize->Find( "#TF_Team_PartyLeader" );
if ( !pFormat )
{
pFormat = L"%s";
}
if ( g_TF_PR->GetEventTeamStatus() )
{
// GetEventTeamStatus() returns a value in the following range
// enum WarMatch
// {
// NOPE = 0;
// INVADERS_ARE_PYRO = 1;
// INVADERS_ARE_HEAVY = 2;
// };
const char *pszTeamName = ( m_iTeamNum == TF_TEAM_BLUE ) ?
( g_TF_PR->GetEventTeamStatus() == 1 ? "#TF_Pyro" : "#TF_HWGuy" ) :
( g_TF_PR->GetEventTeamStatus() == 1 ? "#TF_HWGuy" : "#TF_Pyro" );
wchar_t *pwzWarTeam = g_pVGuiLocalize->Find( pszTeamName );
V_swprintf_safe( m_wzTeamname, pFormat, pwzWarTeam );
m_bUsingCustomTeamName = true;
return;
}
else
{
int iPlayerIndex = ( m_iTeamNum == TF_TEAM_RED ) ? g_TF_PR->GetPartyLeaderRedTeamIndex() : g_TF_PR->GetPartyLeaderBlueTeamIndex();
if ( g_TF_PR->IsConnected( iPlayerIndex ) )
{
g_pVGuiLocalize->ConvertANSIToUnicode( UTIL_SafeName( g_TF_PR->GetPlayerName( iPlayerIndex ) ), wszTempName, sizeof( wszTempName ) );
V_swprintf_safe( m_wzTeamname, pFormat, wszTempName );
m_bUsingCustomTeamName = true;
return;
}
}
}
}
else
{
const char *pTemp = ( m_iTeamNum == TF_TEAM_BLUE ) ? mp_tournament_blueteamname.GetString() : mp_tournament_redteamname.GetString();
if ( pTemp && pTemp[0] )
{
g_pVGuiLocalize->ConvertANSIToUnicode( pTemp, m_wzTeamname, sizeof( m_wzTeamname ) );
return;
}
}
}
if ( m_iTeamNum == TF_TEAM_BLUE )
{
pwzName = g_pVGuiLocalize->Find( "#TF_BlueTeam_Name" );
if ( !pwzName )
{
pwzName = L"BLU";
}
}
else if ( m_iTeamNum == TF_TEAM_RED )
{
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
{
pwzName = g_pVGuiLocalize->Find( "#TF_Defenders" );
if ( !pwzName )
{
pwzName = L"DEFENDERS";
}
}
else
{
pwzName = g_pVGuiLocalize->Find( "#TF_RedTeam_Name" );
if ( !pwzName )
{
pwzName = L"RED";
}
}
}
else if ( m_iTeamNum == TEAM_SPECTATOR )
{
pwzName = g_pVGuiLocalize->Find( "#TF_Spectators" );
if ( !pwzName )
{
pwzName = L"SPECTATORS";
}
}
V_wcscpy_safe( m_wzTeamname, pwzName ? pwzName : L"" );
}
//-----------------------------------------------------------------------------
// Purpose: Get the C_TFTeam for the specified team number
//-----------------------------------------------------------------------------
C_TFTeam *GetGlobalTFTeam( int iTeamNumber )
{
for ( int i = 0; i < g_Teams.Count(); i++ )
{
if ( g_Teams[i]->GetTeamNumber() == iTeamNumber )
return ( dynamic_cast< C_TFTeam* >( g_Teams[i] ) );
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TFTeam::GetNumObjects( int iObjectType )
{
// Asking for a count of a specific object type?
if ( iObjectType > 0 )
{
int iCount = 0;
for ( int i = 0; i < GetNumObjects(); i++ )
{
CBaseObject *pObject = GetObject(i);
if ( pObject && pObject->GetType() == iObjectType )
{
iCount++;
}
}
return iCount;
}
return m_aObjects.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBaseObject *C_TFTeam::GetObject( int num )
{
Assert( num >= 0 && num < m_aObjects.Count() );
return m_aObjects[ num ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BasePlayer *C_TFTeam::GetTeamLeader( void )
{
return m_hLeader.Get();
}
+68
View File
@@ -0,0 +1,68 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side CTFTeam class
//
// $NoKeywords: $
//=============================================================================
#ifndef C_TF_TEAM_H
#define C_TF_TEAM_H
#ifdef _WIN32
#pragma once
#endif
#include "c_team.h"
#include "shareddefs.h"
#include "c_baseobject.h"
class C_BaseEntity;
class C_BaseObject;
class CBaseTechnology;
class C_TFPlayer;
//-----------------------------------------------------------------------------
// Purpose: TF's Team manager
//-----------------------------------------------------------------------------
class C_TFTeam : public C_Team
{
DECLARE_CLASS( C_TFTeam, C_Team );
DECLARE_CLIENTCLASS();
public:
C_TFTeam();
virtual ~C_TFTeam();
int GetFlagCaptures( void ) { return m_nFlagCaptures; }
int GetRole( void ) { return m_iRole; }
char *Get_Name( void );
int GetNumObjects( int iObjectType = -1 );
CBaseObject *GetObject( int num );
CUtlVector< CHandle<C_BaseObject> > m_aObjects;
C_BasePlayer *GetTeamLeader( void );
void UpdateTeamName( void );
const wchar_t *Get_Localized_Name( void ){ return m_wzTeamname; };
virtual void OnDataChanged( DataUpdateType_t updateType ) OVERRIDE;
bool IsUsingCustomTeamName( void ) { return m_bUsingCustomTeamName; }
// IClientThinkable override
virtual void ClientThink();
private:
int m_nFlagCaptures;
int m_iRole;
CNetworkHandle( C_BasePlayer, m_hLeader );
wchar_t m_wzTeamname[ MAX_TEAM_NAME_LENGTH ];
bool m_bUsingCustomTeamName;
};
C_TFTeam *GetGlobalTFTeam( int iTeamNumber );
#endif // C_TF_TEAM_H
+460
View File
@@ -0,0 +1,460 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CWeaponBuilder class
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hud.h"
#include "in_buttons.h"
#include "clientmode_tf.h"
#include "engine/IEngineSound.h"
#include "c_tf_weapon_builder.h"
#include "c_weapon__stubs.h"
#include "iinput.h"
#include <vgui/IVGui.h>
#include "c_tf_player.h"
#include "c_vguiscreen.h"
#include "ienginevgui.h"
STUB_WEAPON_CLASS_IMPLEMENT( tf_weapon_builder, C_TFWeaponBuilder );
PRECACHE_WEAPON_REGISTER( tf_weapon_builder );
// SUPER HACK TO FIX DEMOS. For a couple days, we accidently renamed
// CTFWeaponBuilder to C_TFWeaponBuilder on the server. This was fine for
// playing the game but broke all previously recorded demos. Fixing this and
// re-renaming the class back to the original name fixed all demos recorded
// with the brokenly-renamed class. To handle these demos that think the class
// is called C_TFWeaponBuilder on the server, we're creating a new class that derives from
// the real C_TFWeaponBuilder and does nothing special except that it calls
// IMPLEMENT_CLIENTCLASS and maps itself to serverclass "C_TFWeaponBuilder"
// (which, if you've followed along, doesn't exist anymore).
//
// As a history lesson, this broke from the change in tf_player_shared.h in cl 1722245
class C_TFWeaponBuilderReplayHack : public C_TFWeaponBuilder
{
DECLARE_CLASS( C_TFWeaponBuilderReplayHack, C_TFWeaponBuilder );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
};
IMPLEMENT_CLIENTCLASS( C_TFWeaponBuilderReplayHack, DT_TFWeaponBuilder, C_TFWeaponBuilder )
BEGIN_PREDICTION_DATA( C_TFWeaponBuilderReplayHack )
END_PREDICTION_DATA()
IMPLEMENT_NETWORKCLASS_ALIASED( TFWeaponBuilder, DT_TFWeaponBuilder )
// Recalc object sprite when we receive a new object type to build
void RecvProxy_ObjectType( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
// Pass to normal Int recvproxy
RecvProxy_Int32ToInt32( pData, pStruct, pOut );
// Reset the object sprite
C_TFWeaponBuilder *pBuilder = ( C_TFWeaponBuilder * )pStruct;
pBuilder->SetupObjectSelectionSprite();
}
BEGIN_NETWORK_TABLE_NOBASE( C_TFWeaponBuilder, DT_BuilderLocalData )
RecvPropInt( RECVINFO(m_iObjectType), 0, RecvProxy_ObjectType ),
RecvPropEHandle( RECVINFO(m_hObjectBeingBuilt) ),
RecvPropArray3( RECVINFO_ARRAY( m_aBuildableObjectTypes ), RecvPropBool( RECVINFO( m_aBuildableObjectTypes[0] ) ) ),
END_NETWORK_TABLE()
BEGIN_NETWORK_TABLE( C_TFWeaponBuilder, DT_TFWeaponBuilder )
RecvPropInt( RECVINFO(m_iBuildState) ),
RecvPropDataTable( "BuilderLocalData", 0, 0, &REFERENCE_RECV_TABLE( DT_BuilderLocalData ) ),
RecvPropInt( RECVINFO(m_iObjectMode) ),
RecvPropFloat( RECVINFO( m_flWheatleyTalkingUntil) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
IMPLEMENT_NETWORKCLASS_ALIASED( TFWeaponSapper, DT_TFWeaponSapper )
BEGIN_NETWORK_TABLE( C_TFWeaponSapper, DT_TFWeaponSapper )
RecvPropFloat( RECVINFO( m_flChargeBeginTime ) ),
END_NETWORK_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFWeaponBuilder::C_TFWeaponBuilder()
{
m_iBuildState = 0;
m_iObjectType = BUILDER_INVALID_OBJECT;
m_pSelectionTextureActive = NULL;
m_pSelectionTextureInactive = NULL;
m_iValidBuildPoseParam = -1;
m_flWheatleyTalkingUntil = 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_TFWeaponBuilder::~C_TFWeaponBuilder()
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : char const
//-----------------------------------------------------------------------------
const char *C_TFWeaponBuilder::GetCurrentSelectionObjectName( void )
{
if ( m_iObjectType == -1 || (m_iBuildState == BS_SELECTING) )
return "";
return GetObjectInfo( m_iObjectType )->m_pBuilderWeaponName;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_TFWeaponBuilder::Deploy( void )
{
bool bDeploy = BaseClass::Deploy();
if ( bDeploy )
{
m_flNextPrimaryAttack = gpGlobals->curtime + 0.35f;
m_flNextSecondaryAttack = gpGlobals->curtime; // asap
CTFPlayer *pPlayer = ToTFPlayer( GetOwner() );
if (!pPlayer)
return false;
pPlayer->SetNextAttack( gpGlobals->curtime );
m_iWorldModelIndex = modelinfo->GetModelIndex( GetWorldModel() );
}
return bDeploy;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFWeaponBuilder::SecondaryAttack( void )
{
if ( m_bInAttack2 )
return;
// require a re-press
m_bInAttack2 = true;
CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
if ( !pOwner )
return;
pOwner->DoClassSpecialSkill();
m_flNextSecondaryAttack = gpGlobals->curtime + 0.2f;
}
//-----------------------------------------------------------------------------
// Purpose: cache the build pos pose param
//-----------------------------------------------------------------------------
CStudioHdr *C_TFWeaponBuilder::OnNewModel( void )
{
CStudioHdr *hdr = BaseClass::OnNewModel();
m_iValidBuildPoseParam = LookupPoseParameter( "valid_build_pos" );
return hdr;
}
//-----------------------------------------------------------------------------
// Purpose:
// ----------------------------------------------------------------------------
void C_TFWeaponBuilder::PostDataUpdate( DataUpdateType_t type )
{
if ( type == DATA_UPDATE_CREATED )
{
// m_iViewModelIndex is set by the base Precache(), which didn't know what
// type of object we built, so it didn't get the right viewmodel index.
// Now that our data is filled in, go and get the right index.
const char *pszViewModel = GetViewModel(0);
if ( pszViewModel && pszViewModel[0] )
{
m_iViewModelIndex = CBaseEntity::PrecacheModel( pszViewModel );
}
}
BaseClass::PostDataUpdate( type );
}
//-----------------------------------------------------------------------------
// Purpose: only called for local player
//-----------------------------------------------------------------------------
void C_TFWeaponBuilder::Redraw()
{
if ( m_iValidBuildPoseParam >= 0 )
{
CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
if ( !pOwner )
return;
// Assuming here that our model is the same as our viewmodel's model!
CBaseViewModel *pViewModel = pOwner->GetViewModel(0);
if ( pViewModel )
{
float flPoseParamValue = pViewModel->GetPoseParameter( m_iValidBuildPoseParam );
C_BaseObject *pObj = m_hObjectBeingBuilt.Get();
if ( pObj && pObj->WasLastPlacementPosValid() )
{
// pose param approach 1.0
flPoseParamValue = Approach( 1.0, flPoseParamValue, 3.0 * gpGlobals->frametime );
}
else
{
// pose param approach 0.0
flPoseParamValue = Approach( 0.0, flPoseParamValue, 1.5 * gpGlobals->frametime );
}
pViewModel->SetPoseParameter( m_iValidBuildPoseParam, flPoseParamValue );
}
}
BaseClass::Redraw();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_TFWeaponBuilder::IsPlacingObject( void )
{
if ( m_iBuildState == BS_PLACING || m_iBuildState == BS_PLACING_INVALID )
return true;
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TFWeaponBuilder::GetSlot( void ) const
{
return GetObjectInfo( m_iObjectType )->m_SelectionSlot;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TFWeaponBuilder::GetPosition( void ) const
{
return GetObjectInfo( m_iObjectType )->m_SelectionPosition;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TFWeaponBuilder::SetupObjectSelectionSprite( void )
{
#ifdef CLIENT_DLL
// Use the sprite details from the text file, with a custom sprite
char *iconTexture = GetObjectInfo( m_iObjectType )->m_pIconActive;
if ( iconTexture && iconTexture[ 0 ] )
{
m_pSelectionTextureActive = gHUD.GetIcon( iconTexture );
}
else
{
m_pSelectionTextureActive = NULL;
}
iconTexture = GetObjectInfo( m_iObjectType )->m_pIconInactive;
if ( iconTexture && iconTexture[ 0 ] )
{
m_pSelectionTextureInactive = gHUD.GetIcon( iconTexture );
}
else
{
m_pSelectionTextureInactive = NULL;
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CHudTexture const *C_TFWeaponBuilder::GetSpriteActive( void ) const
{
return m_pSelectionTextureActive;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CHudTexture const *C_TFWeaponBuilder::GetSpriteInactive( void ) const
{
return m_pSelectionTextureInactive;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : char const
//-----------------------------------------------------------------------------
const char *C_TFWeaponBuilder::GetPrintName( void ) const
{
return GetObjectInfo( m_iObjectType )->m_AltModes[m_iObjectMode].pszStatusName;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_TFWeaponBuilder::GetSubType( void )
{
return m_iObjectType;
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this weapon can be selected via the weapon selection
//-----------------------------------------------------------------------------
bool C_TFWeaponBuilder::CanBeSelected( void )
{
CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
if ( !pOwner )
return false;
if ( pOwner->CanBuild( m_iObjectType, m_iObjectMode ) != CB_CAN_BUILD )
return false;
return HasAmmo();
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this weapon should be visible in the weapon selection
//-----------------------------------------------------------------------------
bool C_TFWeaponBuilder::VisibleInWeaponSelection( void )
{
if ( BaseClass::VisibleInWeaponSelection() == false )
return false;
if ( m_iObjectType != BUILDER_INVALID_OBJECT )
return GetObjectInfo( m_iObjectType )->m_bVisibleInWeaponSelection;
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this weapon has some ammo
//-----------------------------------------------------------------------------
bool C_TFWeaponBuilder::HasAmmo( void )
{
CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
if ( !pOwner )
return false;
int iCost = pOwner->m_Shared.CalculateObjectCost( pOwner, m_iObjectType );
return ( pOwner->GetBuildResources() >= iCost );
}
// -----------------------------------------------------------------------------
// Purpose:
// -----------------------------------------------------------------------------
bool C_TFWeaponBuilder::CanBuildObjectType( int iObjectType )
{
if ( iObjectType < 0 || iObjectType >= OBJ_LAST )
return false;
return m_aBuildableObjectTypes[iObjectType];
}
// -----------------------------------------------------------------------------
// Purpose:
// -----------------------------------------------------------------------------
void C_TFWeaponBuilder::UpdateAttachmentModels( void )
{
if ( m_iObjectType != BUILDER_INVALID_OBJECT && GetObjectInfo( m_iObjectType )->m_bUseItemInfo )
{
BaseClass::UpdateAttachmentModels();
}
}
// -----------------------------------------------------------------------------
// Purpose:
// -----------------------------------------------------------------------------
const char *C_TFWeaponBuilder::GetViewModel( int iViewModel ) const
{
if ( GetPlayerOwner() == NULL )
{
return BaseClass::GetViewModel();
}
if ( m_iObjectType != BUILDER_INVALID_OBJECT )
{
if ( GetObjectInfo( m_iObjectType )->m_bUseItemInfo )
return BaseClass::GetViewModel();
return GetObjectInfo( m_iObjectType )->m_pViewModel;
}
return BaseClass::GetViewModel();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_TFWeaponBuilder::GetWorldModel( void ) const
{
if ( GetPlayerOwner() == NULL )
{
return BaseClass::GetWorldModel();
}
if ( m_iObjectType != BUILDER_INVALID_OBJECT )
{
return GetObjectInfo( m_iObjectType )->m_pPlayerModel;
}
return BaseClass::GetWorldModel();
}
Activity C_TFWeaponBuilder::GetDrawActivity( void )
{
// sapper used to call different draw animations , one when invis and one when not.
// now you can go invis *while* deploying, so let's always use the one-handed deploy.
if ( GetType() == OBJ_ATTACHMENT_SAPPER )
{
return ACT_VM_DRAW_DEPLOYED;
}
return BaseClass::GetDrawActivity();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_TFWeaponBuilder::EffectMeterShouldFlash( void )
{
if ( !GetOwner() )
return false;
int iRoboSapper = 0;
CALL_ATTRIB_HOOK_INT_ON_OTHER( GetOwner(), iRoboSapper, robo_sapper );
return ( iRoboSapper && GetEffectBarProgress() >= 1.f );
}
const char *C_TFWeaponSapper::GetViewModel( int iViewModel ) const
{
// Skip over Builder's version
return C_TFWeaponBase::GetViewModel();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *C_TFWeaponSapper::GetWorldModel( void ) const
{
// Skip over Builder's version
return C_TFWeaponBase::GetWorldModel();
}
+132
View File
@@ -0,0 +1,132 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_TF_WEAPON_BUILDER_H
#define C_TF_WEAPON_BUILDER_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_weaponbase.h"
#include "c_baseobject.h"
#define CTFWeaponBuilder C_TFWeaponBuilder
#define CTFWeaponSapper C_TFWeaponSapper
//=============================================================================
// Purpose: Client version of CWeaponBuiler
//=============================================================================
class C_TFWeaponBuilder : public C_TFWeaponBase
{
DECLARE_CLASS( C_TFWeaponBuilder, C_TFWeaponBase );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
C_TFWeaponBuilder();
~C_TFWeaponBuilder();
virtual void Redraw();
virtual void SecondaryAttack();
virtual bool IsPlacingObject( void );
virtual const char *GetCurrentSelectionObjectName( void );
virtual const char *GetViewModel( int iViewModel ) const;
virtual const char *GetWorldModel( void ) const;
virtual bool Deploy( void );
virtual void PostDataUpdate( DataUpdateType_t type );
C_BaseObject *GetPlacementModel( void ) { return m_hObjectBeingBuilt.Get(); }
virtual void UpdateAttachmentModels( void );
virtual int GetSlot( void ) const;
virtual int GetPosition( void ) const;
void SetupObjectSelectionSprite( void );
virtual CHudTexture const *GetSpriteActive( void ) const;
virtual CHudTexture const *GetSpriteInactive( void ) const;
virtual const char *GetPrintName( void ) const;
virtual int GetSubType( void );
virtual bool CanBeSelected( void );
virtual bool VisibleInWeaponSelection( void );
virtual bool HasAmmo( void );
virtual int GetWeaponID( void ) const { return TF_WEAPON_BUILDER; }
int GetType( void ) { return m_iObjectType; }
bool CanBuildObjectType( int iObjectType );
virtual Activity GetDrawActivity( void );
virtual CStudioHdr *OnNewModel( void );
virtual float InternalGetEffectBarRechargeTime( void ) { return 15.0; }
virtual int GetEffectBarAmmo( void ) { return TF_AMMO_GRENADES2; }
float GetProgress( void ) { return GetEffectBarProgress(); }
const char* GetEffectLabelText( void ) { return "#TF_Sapper"; }
virtual bool EffectMeterShouldFlash( void );
public:
// Builder Data
int m_iBuildState;
unsigned int m_iObjectType;
unsigned int m_iObjectMode;
float m_flStartTime;
float m_flTotalTime;
CHudTexture *m_pSelectionTextureActive;
CHudTexture *m_pSelectionTextureInactive;
// Our placement model
CHandle<C_BaseObject> m_hObjectBeingBuilt;
int m_iValidBuildPoseParam;
// Wheatly Data
float m_flWheatleyTalkingUntil;
private:
C_TFWeaponBuilder( const C_TFWeaponBuilder & );
bool m_aBuildableObjectTypes[OBJ_LAST];
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_TFWeaponSapper : public C_TFWeaponBuilder, public ITFChargeUpWeapon
{
DECLARE_CLASS( C_TFWeaponSapper, C_TFWeaponBuilder );
public:
DECLARE_NETWORKCLASS();
//DECLARE_PREDICTABLE();
// ITFChargeUpWeapon
virtual bool CanCharge( void ) { return GetChargeMaxTime() > 0; }
virtual float GetChargeBeginTime( void ) { return m_flChargeBeginTime; }
virtual float GetChargeMaxTime( void ) { float flChargeTime = 0; CALL_ATTRIB_HOOK_FLOAT( flChargeTime, sapper_deploy_time ); return flChargeTime; };
virtual const char *GetViewModel( int iViewModel ) const;
virtual const char *GetWorldModel( void ) const;
bool IsWheatleyTalking( void ) { return gpGlobals->curtime <= m_flWheatleyTalkingUntil; }
CNetworkVar( float, m_flChargeBeginTime );
};
#endif // C_TF_WEAPON_BUILDER_H
File diff suppressed because it is too large Load Diff
+161
View File
@@ -0,0 +1,161 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef TF_CLIENTMODE_H
#define TF_CLIENTMODE_H
#ifdef _WIN32
#pragma once
#endif
#include "clientmode_shared.h"
#include "tf_viewport.h"
#include "GameUI/IGameUI.h"
#include "halloween/tf_weapon_spellbook.h"
#include "tf_hud_teamgoal_tournament.h"
class CHudMenuEngyBuild;
class CHudMenuEngyDestroy;
class CHudMenuSpyDisguise;
class CTFFreezePanel;
class CItemQuickSwitchPanel;
class CHudEurekaEffectTeleportMenu;
class CHudMenuTauntSelection;
class CHudInspectPanel;
class CHudUpgradePanel;
#ifdef STAGING_ONLY
class CHudMenuSpyBuild;
#endif // STAGING_ONLY
#if defined( _X360 )
class CTFClientScoreBoardDialog;
#endif
class ClientModeTFNormal : public ClientModeShared
{
DECLARE_CLASS( ClientModeTFNormal, ClientModeShared );
private:
// IClientMode overrides.
public:
ClientModeTFNormal();
virtual ~ClientModeTFNormal();
virtual void Init();
virtual void InitViewport();
virtual void Shutdown();
virtual void LevelInit( const char *newmap ) OVERRIDE;
// virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding );
virtual float GetViewModelFOV( void );
virtual bool ShouldDrawViewModel();
virtual bool ShouldDrawCrosshair( void );
virtual bool ShouldBlackoutAroundHUD() OVERRIDE;
virtual HeadtrackMovementMode_t ShouldOverrideHeadtrackControl() OVERRIDE;
int GetDeathMessageStartHeight( void );
virtual void FireGameEvent( IGameEvent *event );
virtual void PostRenderVGui();
virtual bool CreateMove( float flInputSampleTime, CUserCmd *cmd );
virtual int HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding );
virtual int HandleSpectatorKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding );
virtual bool DoPostScreenSpaceEffects( const CViewSetup *pSetup );
virtual void Update();
virtual void ComputeVguiResConditions( KeyValues *pkvConditions ) OVERRIDE;
virtual bool IsInfoPanelAllowed() OVERRIDE;
virtual void InfoPanelDisplayed() OVERRIDE;
virtual bool IsHTMLInfoPanelAllowed() OVERRIDE;
IGameUI *GameUI( void ) { return m_pGameUI; }
const char *GetLastConnectedServerName( void ) const; // return the name of the last server we have connected to
uint32 GetLastConnectedServerIP( void ) const; // return the IP of the last server we have connected to
int GetLastConnectedServerPort( void ) const; // return the port of the last server we have connected to
void PrintTextToChat( const char *pText, KeyValues *pKeyValues = NULL );
void PrintTextToChatPlayer( int iPlayerIndex, const char *pText, KeyValues *pKeyValues = NULL );
#if !defined(NO_STEAM)
STEAM_CALLBACK_MANUAL( ClientModeTFNormal, OnScreenshotRequested, ScreenshotRequested_t, m_CallbackScreenshotRequested );
#endif
bool IsEngyBuildVisible() const;
bool IsEngyDestroyVisible() const;
bool IsEngyEurekaTeleportVisible() const;
bool IsSpyDisguiseVisible() const;
bool IsUpgradePanelVisible() const;
bool IsTauntSelectPanelVisible() const;
virtual void OnDemoRecordStart( char const* pDemoBaseName ) OVERRIDE;
virtual void OnDemoRecordStop() OVERRIDE;
private:
// void UpdateSpectatorMode( void );
private:
CHudMenuEngyBuild *m_pMenuEngyBuild;
CHudMenuEngyDestroy *m_pMenuEngyDestroy;
CHudMenuSpyDisguise *m_pMenuSpyDisguise;
CHudMenuTauntSelection *m_pMenuTauntSelection;
CHudUpgradePanel *m_pMenuUpgradePanel;
#ifdef STAGING_ONLY
CHudMenuSpyBuild *m_pMenuSpyBuild;
#endif // STAGING_ONLY
CHudSpellMenu *m_pMenuSpell;
CHudEurekaEffectTeleportMenu *m_pEurekaTeleportMenu;
CHudTeamGoalTournament *m_pTeamGoalTournament;
CTFFreezePanel *m_pFreezePanel;
CItemQuickSwitchPanel *m_pQuickSwitch;
CHudInspectPanel *m_pInspectPanel;
IGameUI *m_pGameUI;
bool m_wasConnectedLastUpdate;
char *m_lastServerName;
uint32 m_lastServerIP;
int m_lastServerPort;
uint32 m_lastServerConnectTime;
float m_flNextAllowedHighFiveHintTime;
bool m_bInfoPanelShown;
bool m_bRestrictInfoPanel;
void AskFavoriteOrBlacklist() const;
#if defined( _X360 )
CTFClientScoreBoardDialog *m_pScoreboard;
#endif
};
inline const char *ClientModeTFNormal::GetLastConnectedServerName( void ) const
{
return m_lastServerName;
}
inline uint32 ClientModeTFNormal::GetLastConnectedServerIP( void ) const
{
return m_lastServerIP;
}
inline int ClientModeTFNormal::GetLastConnectedServerPort( void ) const
{
return m_lastServerPort;
}
extern IClientMode *GetClientModeNormal();
extern ClientModeTFNormal* GetClientModeTFNormal();
void PlayOutOfGameSound( const char *pszSound );
float PlaySoundEntry( const char* pszSoundEntryName ); // Returns the duration of the sound
#endif // TF_CLIENTMODE_H
+273
View File
@@ -0,0 +1,273 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
// c_eyeball_boss.cpp
#include "cbase.h"
#include "NextBot/C_NextBot.h"
#include "c_eyeball_boss.h"
#include "tf_shareddefs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#undef NextBot
#ifdef STAGING_ONLY
static ConVar cl_eyeball_boss_debug( "cl_eyeball_boss_debug", "0" );
#endif
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EyeballBoss, DT_EyeballBoss, CEyeballBoss )
RecvPropVector( RECVINFO( m_lookAtSpot ) ),
RecvPropInt( RECVINFO( m_attitude ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_EyeballBoss::C_EyeballBoss()
{
m_ghostEffect = NULL;
m_auraEffect = NULL;
m_attitude = EYEBALL_CALM;
m_priorAttitude = m_attitude;
}
//-----------------------------------------------------------------------------
C_EyeballBoss::~C_EyeballBoss()
{
if ( m_ghostEffect )
{
ParticleProp()->StopEmission( m_ghostEffect );
m_ghostEffect = NULL;
}
if ( m_auraEffect )
{
ParticleProp()->StopEmission( m_auraEffect );
m_auraEffect = NULL;
}
}
//-----------------------------------------------------------------------------
void C_EyeballBoss::Spawn( void )
{
BaseClass::Spawn();
m_leftRightPoseParameter = -1;
m_upDownPoseParameter = -1;
m_myAngles = vec3_angle;
m_attitude = EYEBALL_CALM;
m_priorAttitude = m_attitude;
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//-----------------------------------------------------------------------------
void C_EyeballBoss::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_priorAttitude = m_attitude;
}
//-----------------------------------------------------------------------------
void C_EyeballBoss::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
const char *pszMaterial = NULL;
const char *pszAuraEffect = "eyeboss_aura_calm";
switch ( GetTeamNumber() )
{
case TF_TEAM_RED:
{
pszAuraEffect = "eyeboss_team_red";
//pszMaterial = "models/effects/invulnfx_red.vmt";
}
break;
case TF_TEAM_BLUE:
{
pszAuraEffect = "eyeboss_team_blue";
//pszMaterial = "models/effects/invulnfx_blue.vmt";
}
break;
default:
{
if ( !m_ghostEffect )
{
m_ghostEffect = ParticleProp()->Create( "ghost_pumpkin", PATTACH_ABSORIGIN_FOLLOW );
}
}
break;
}
if ( !m_auraEffect )
{
m_auraEffect = ParticleProp()->Create( pszAuraEffect, PATTACH_ABSORIGIN_FOLLOW );
}
if ( pszMaterial )
{
m_InvulnerableMaterial.Init( pszMaterial, TEXTURE_GROUP_CLIENT_EFFECTS );
}
else
{
m_InvulnerableMaterial.Shutdown();
}
}
else if ( GetTeamNumber() == TF_TEAM_HALLOWEEN )
{
// update eyeball aura
if ( m_attitude != m_priorAttitude )
{
// kill the old aura
if ( m_auraEffect )
{
ParticleProp()->StopEmission( m_auraEffect );
}
switch( m_attitude )
{
case EYEBALL_CALM:
m_auraEffect = ParticleProp()->Create( "eyeboss_aura_calm", PATTACH_ABSORIGIN_FOLLOW );
break;
case EYEBALL_GRUMPY:
m_auraEffect = ParticleProp()->Create( "eyeboss_aura_grumpy", PATTACH_ABSORIGIN_FOLLOW );
break;
case EYEBALL_ANGRY:
m_auraEffect = ParticleProp()->Create( "eyeboss_aura_angry", PATTACH_ABSORIGIN_FOLLOW );
break;
}
m_priorAttitude = m_attitude;
}
}
}
//-----------------------------------------------------------------------------
void C_EyeballBoss::ClientThink( void )
{
// update eyeball aim
if ( m_leftRightPoseParameter < 0 )
{
m_leftRightPoseParameter = LookupPoseParameter( "left_right" );
}
if ( m_upDownPoseParameter < 0 )
{
m_upDownPoseParameter = LookupPoseParameter( "up_down" );
}
Vector myForward, myRight, myUp;
AngleVectors( m_myAngles, &myForward, &myRight, &myUp );
#ifdef STAGING_ONLY
if ( cl_eyeball_boss_debug.GetBool() )
{
QAngle myAbsAngles = GetAbsAngles();
DevMsg( "%3.2f: EYEBALL BEFORE AIM m_myAngles( %f, %f, %f ), myForward( %f, %f, %f ), GetAbsAngles( %f, %f, %f )\n",
gpGlobals->curtime, m_myAngles.x, m_myAngles.y, m_myAngles.z, myForward.x, myForward.y, myForward.z,
myAbsAngles.x, myAbsAngles.y, myAbsAngles.z );
}
#endif
const float myApproachRate = 3.0f; // 1.0f;
Vector toTarget = m_lookAtSpot - WorldSpaceCenter();
toTarget.NormalizeInPlace();
myForward += toTarget * myApproachRate * gpGlobals->frametime;
myForward.NormalizeInPlace();
QAngle myNewAngles;
VectorAngles( myForward, myNewAngles );
SetAbsAngles( myNewAngles );
m_myAngles = myNewAngles;
#ifdef STAGING_ONLY
if ( cl_eyeball_boss_debug.GetBool() )
{
QAngle myAbsAngles = GetAbsAngles();
DevMsg( "%3.2f: EYEBALL AFTER AIM m_myAngles( %f, %f, %f ), myForward( %f, %f, %f ), GetAbsAngles( %f, %f, %f )\n",
gpGlobals->curtime, m_myAngles.x, m_myAngles.y, m_myAngles.z, myForward.x, myForward.y, myForward.z,
myAbsAngles.x, myAbsAngles.y, myAbsAngles.z );
}
#endif
// set pose parameters to aim pupil directly at target
float toTargetRight = DotProduct( myRight, toTarget );
float toTargetUp = DotProduct( myUp, toTarget );
if ( m_leftRightPoseParameter >= 0 )
{
int angle = -50 * toTargetRight;
SetPoseParameter( m_leftRightPoseParameter, angle );
}
if ( m_upDownPoseParameter >= 0 )
{
int angle = -50 * toTargetUp;
SetPoseParameter( m_upDownPoseParameter, angle );
}
}
//-----------------------------------------------------------------------------
void C_EyeballBoss::SetDormant( bool bDormant )
{
BaseClass::SetDormant( bDormant );
}
//-----------------------------------------------------------------------------
void C_EyeballBoss::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
}
//-----------------------------------------------------------------------------
QAngle const &C_EyeballBoss::GetRenderAngles( void )
{
return m_myAngles;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int C_EyeballBoss::InternalDrawModel( int flags )
{
bool bUseInvulnMaterial = ( GetTeamNumber() == TF_TEAM_RED ) || ( GetTeamNumber() == TF_TEAM_BLUE );
if ( bUseInvulnMaterial )
{
modelrender->ForcedMaterialOverride( m_InvulnerableMaterial );
}
int ret = BaseClass::InternalDrawModel( flags );
if ( bUseInvulnMaterial )
{
modelrender->ForcedMaterialOverride( NULL );
}
return ret;
}
+55
View File
@@ -0,0 +1,55 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_EYEBALL_BOSS_H
#define C_EYEBALL_BOSS_H
#include "c_ai_basenpc.h"
#define EYEBALL_ANGRY 2
#define EYEBALL_GRUMPY 1
#define EYEBALL_CALM 0
//--------------------------------------------------------------------------------------------------------
/**
* The client-side implementation of the Halloween Eyeball Boss
*/
class C_EyeballBoss : public C_NextBotCombatCharacter
{
public:
DECLARE_CLASS( C_EyeballBoss, C_NextBotCombatCharacter );
DECLARE_CLIENTCLASS();
C_EyeballBoss();
virtual ~C_EyeballBoss();
virtual void Spawn( void );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual bool IsNextBot() { return true; }
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void ClientThink();
virtual void SetDormant( bool bDormant );
virtual QAngle const &GetRenderAngles( void );
virtual int InternalDrawModel( int flags );
private:
C_EyeballBoss( const C_EyeballBoss & ); // not defined, not accessible
Vector m_lookAtSpot;
int m_attitude;
int m_priorAttitude;
QAngle m_myAngles;
int m_leftRightPoseParameter;
int m_upDownPoseParameter;
HPARTICLEFFECT m_ghostEffect;
HPARTICLEFFECT m_auraEffect;
CMaterialReference m_InvulnerableMaterial;
};
#endif // C_EYEBALL_BOSS_H
@@ -0,0 +1,101 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
// C_HeadlessHatman.cpp
#include "cbase.h"
#include "NextBot/C_NextBot.h"
#include "c_headless_hatman.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#undef NextBot
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_HeadlessHatman, DT_HeadlessHatman, CHeadlessHatman )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_HeadlessHatman::C_HeadlessHatman()
{
m_ghostEffect = NULL;
m_leftEyeEffect = NULL;
m_rightEyeEffect = NULL;
}
//-----------------------------------------------------------------------------
C_HeadlessHatman::~C_HeadlessHatman()
{
if ( m_ghostEffect )
{
ParticleProp()->StopEmission( m_ghostEffect );
m_ghostEffect = NULL;
}
if ( m_leftEyeEffect )
{
ParticleProp()->StopEmission( m_leftEyeEffect );
m_leftEyeEffect = NULL;
}
if ( m_rightEyeEffect )
{
ParticleProp()->StopEmission( m_rightEyeEffect );
m_rightEyeEffect = NULL;
}
}
//-----------------------------------------------------------------------------
void C_HeadlessHatman::Spawn( void )
{
BaseClass::Spawn();
m_vecViewOffset = Vector( 0, 0, 100.0f );
if ( !m_ghostEffect )
{
m_ghostEffect = ParticleProp()->Create( "ghost_pumpkin", PATTACH_ABSORIGIN_FOLLOW );
}
SetNextClientThink( gpGlobals->curtime + 1.0f );
}
//-----------------------------------------------------------------------------
void C_HeadlessHatman::ClientThink( void )
{
if ( !m_leftEyeEffect )
{
m_leftEyeEffect = ParticleProp()->Create( "halloween_boss_eye_glow", PATTACH_POINT_FOLLOW, "lefteye" );
}
if ( !m_rightEyeEffect )
{
m_rightEyeEffect = ParticleProp()->Create( "halloween_boss_eye_glow", PATTACH_POINT_FOLLOW, "righteye" );
}
SetNextClientThink( CLIENT_THINK_NEVER );
}
//-----------------------------------------------------------------------------
// Return the origin for player observers tracking this target
Vector C_HeadlessHatman::GetObserverCamOrigin( void )
{
return EyePosition();
}
//-----------------------------------------------------------------------------
void C_HeadlessHatman::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
if ( event == 7001 )
{
// footstep event
EmitSound( "Halloween.HeadlessBossFootfalls" );
ParticleProp()->Create( "halloween_boss_foot_impact", PATTACH_ABSORIGIN, 0 );
}
}
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_HEADLESS_HATMAN_H
#define C_HEADLESS_HATMAN_H
#include "c_ai_basenpc.h"
//--------------------------------------------------------------------------------------------------------
/**
* The client-side implementation of the Dark Knight
*/
class C_HeadlessHatman : public C_NextBotCombatCharacter
{
public:
DECLARE_CLASS( C_HeadlessHatman, C_NextBotCombatCharacter );
DECLARE_CLIENTCLASS();
C_HeadlessHatman();
virtual ~C_HeadlessHatman();
public:
virtual void Spawn( void );
virtual bool IsNextBot() { return true; }
virtual Vector GetObserverCamOrigin( void ); // Return the origin for player observers tracking this target
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void ClientThink();
private:
C_HeadlessHatman( const C_HeadlessHatman & ); // not defined, not accessible
HPARTICLEFFECT m_ghostEffect;
HPARTICLEFFECT m_leftEyeEffect;
HPARTICLEFFECT m_rightEyeEffect;
};
#endif // C_HEADLESS_HATMAN_H
+148
View File
@@ -0,0 +1,148 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#include "cbase.h"
#include "NextBot/C_NextBot.h"
#include "c_merasmus.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#undef NextBot
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_Merasmus, DT_Merasmus, CMerasmus )
RecvPropBool( RECVINFO( m_bRevealed ) ),
RecvPropBool( RECVINFO( m_bIsDoingAOEAttack ) ),
RecvPropBool( RECVINFO( m_bStunned ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_Merasmus::C_Merasmus()
{
m_ghostEffect = NULL;
m_aoeEffect = NULL;
m_stunEffect = NULL;
m_bRevealed = false;
m_bWasRevealed = false;
m_bIsDoingAOEAttack = false;
m_bStunned = false;
}
//-----------------------------------------------------------------------------
C_Merasmus::~C_Merasmus()
{
if ( m_ghostEffect )
{
ParticleProp()->StopEmission( m_ghostEffect );
m_ghostEffect = NULL;
}
if ( m_aoeEffect )
{
ParticleProp()->StopEmission( m_aoeEffect );
m_aoeEffect = NULL;
}
if ( m_stunEffect )
{
ParticleProp()->StopEmission( m_stunEffect );
m_stunEffect = NULL;
}
}
//-----------------------------------------------------------------------------
void C_Merasmus::Spawn( void )
{
BaseClass::Spawn();
m_vecViewOffset = Vector( 0, 0, 100.0f );
}
//-----------------------------------------------------------------------------
// Return the origin for player observers tracking this target
Vector C_Merasmus::GetObserverCamOrigin( void )
{
return EyePosition();
}
//-----------------------------------------------------------------------------
void C_Merasmus::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_bWasRevealed = m_bRevealed;
}
//-----------------------------------------------------------------------------
void C_Merasmus::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( m_bRevealed != m_bWasRevealed )
{
if ( m_bRevealed )
{
if ( !m_ghostEffect )
{
m_ghostEffect = ParticleProp()->Create( "merasmus_ambient_body", PATTACH_ABSORIGIN_FOLLOW );
}
}
else
{
if ( m_ghostEffect )
{
ParticleProp()->StopEmission( m_ghostEffect );
m_ghostEffect = NULL;
}
}
}
// book attack
if ( m_bIsDoingAOEAttack )
{
if ( !m_aoeEffect )
{
m_aoeEffect = ParticleProp()->Create( "merasmus_book_attack", PATTACH_POINT_FOLLOW, LookupAttachment( "effect_hand_R" ), Vector( 16.f, 0.f, 0.f ) );
}
}
else
{
if ( m_aoeEffect )
{
ParticleProp()->StopEmission( m_aoeEffect );
m_aoeEffect = NULL;
}
}
// stunned
if ( m_bStunned )
{
if ( !m_stunEffect )
{
m_stunEffect = ParticleProp()->Create( "merasmus_dazed", PATTACH_POINT_FOLLOW, LookupAttachment( "head" ) );
}
}
else
{
if ( m_stunEffect )
{
ParticleProp()->StopEmission( m_stunEffect );
m_stunEffect = NULL;
}
}
}
int C_Merasmus::GetSkin()
{
return ( m_bIsDoingAOEAttack || m_bStunned ) ? 0 : 1;
}
+49
View File
@@ -0,0 +1,49 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#ifndef C_MERASMUS_H
#define C_MERASMUS_H
#include "c_ai_basenpc.h"
//--------------------------------------------------------------------------------------------------------
/**
* The client-side implementation of the Dark Knight
*/
class C_Merasmus : public C_NextBotCombatCharacter
{
public:
DECLARE_CLASS( C_Merasmus, C_NextBotCombatCharacter );
DECLARE_CLIENTCLASS();
C_Merasmus();
virtual ~C_Merasmus();
public:
virtual void Spawn( void );
virtual bool IsNextBot() { return true; }
virtual Vector GetObserverCamOrigin( void ); // Return the origin for player observers tracking this target
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual int GetSkin();
private:
C_Merasmus( const C_Merasmus & ); // not defined, not accessible
HPARTICLEFFECT m_ghostEffect;
HPARTICLEFFECT m_aoeEffect;
HPARTICLEFFECT m_stunEffect;
bool m_bWasRevealed;
CNetworkVar( bool, m_bRevealed );
CNetworkVar( bool, m_bIsDoingAOEAttack );
CNetworkVar( bool, m_bStunned );
};
#endif // C_MERASMUS_H
@@ -0,0 +1,29 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#include "cbase.h"
#include "c_merasmus_dancer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_MerasmusDancer, DT_MerasmusDancer, CMerasmusDancer )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_MerasmusDancer::C_MerasmusDancer()
{
}
//-----------------------------------------------------------------------------
C_MerasmusDancer::~C_MerasmusDancer()
{
}
@@ -0,0 +1,26 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#ifndef C_MERASMUS_DANCER_H
#define C_MERASMUS_DANCER_H
#include "c_baseanimating.h"
//--------------------------------------------------------------------------------------------------------
class C_MerasmusDancer : public C_BaseAnimating
{
public:
DECLARE_CLASS( C_MerasmusDancer, C_BaseAnimating );
DECLARE_CLIENTCLASS();
C_MerasmusDancer();
virtual ~C_MerasmusDancer();
private:
C_MerasmusDancer( const C_MerasmusDancer & ); // not defined, not accessible
};
#endif // C_MERASMUS_DANCER_H
+38
View File
@@ -0,0 +1,38 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
// c_eyeball_boss.cpp
#include "cbase.h"
#include "NextBot/C_NextBot.h"
#include "c_zombie.h"
#include "tf_shareddefs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_Zombie, DT_Zombie, CZombie )
RecvPropFloat( RECVINFO( m_flHeadScale ) ),
END_RECV_TABLE()
C_Zombie::C_Zombie()
{
}
bool C_Zombie::ShouldCollide( int collisionGroup, int contentsMask ) const
{
if ( collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT )
return false;
return BaseClass::ShouldCollide( collisionGroup, contentsMask );
}
extern void BuildBigHeadTransformations( CBaseAnimating *pObject, CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed, float flScale );
void C_Zombie::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed )
{
BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed );
m_BoneAccessor.SetWritableBones( BONE_USED_BY_ANYTHING );
BuildBigHeadTransformations( this, hdr, pos, q, cameraTransform, boneMask, boneComputed, m_flHeadScale );
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_ZOMBIE_H
#define C_ZOMBIE_H
#include "c_ai_basenpc.h"
#include "props_shared.h"
//--------------------------------------------------------------------------------------------------------
/**
* The client-side implementation of the Halloween Zombie
*/
class C_Zombie : public C_NextBotCombatCharacter
{
public:
DECLARE_CLASS( C_Zombie, C_NextBotCombatCharacter );
DECLARE_CLIENTCLASS();
C_Zombie();
virtual bool IsNextBot() { return true; }
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
virtual void BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed ) OVERRIDE;
private:
C_Zombie( const C_Zombie & ); // not defined, not accessible
float m_flHeadScale;
};
#endif // C_EYEBALL_BOSS_H
+920
View File
@@ -0,0 +1,920 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Draws CSPort's death notices
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "hudelement.h"
#include "hud_macros.h"
#include "c_playerresource.h"
#include "iclientmode.h"
#include <vgui_controls/Controls.h>
#include <vgui_controls/Panel.h>
#include <vgui/ISurface.h>
#include <vgui/ILocalize.h>
#include <KeyValues.h>
#include <game_controls/baseviewport.h>
#include "clientmode_shared.h"
#include "c_baseplayer.h"
#include "c_team.h"
#include "tf_shareddefs.h"
#include "tf_shareddefs.h"
#include "tf_gamerules.h"
#include "tf_logic_player_destruction.h"
#include "hud_basedeathnotice.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static ConVar hud_deathnotice_time( "hud_deathnotice_time", "6", 0 );
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CHudBaseDeathNotice::CHudBaseDeathNotice( const char *pElementName ) :
CHudElement( pElementName ), BaseClass( NULL, "HudDeathNotice" )
{
vgui::Panel *pParent = g_pClientMode->GetViewport();
SetParent( pParent );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::ApplySchemeSettings( IScheme *scheme )
{
BaseClass::ApplySchemeSettings( scheme );
SetPaintBackgroundEnabled( false );
CalcRoundedCorners();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::Init( void )
{
ListenForGameEvent( "player_death" );
ListenForGameEvent( "object_destroyed" );
ListenForGameEvent( "teamplay_point_captured" );
ListenForGameEvent( "teamplay_capture_blocked" );
ListenForGameEvent( "teamplay_flag_event" );
ListenForGameEvent( "rd_robot_killed" );
ListenForGameEvent( "special_score" );
ListenForGameEvent( "team_leader_killed" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::VidInit( void )
{
m_DeathNotices.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose: Draw if we've got at least one death notice in the queue
//-----------------------------------------------------------------------------
bool CHudBaseDeathNotice::ShouldDraw( void )
{
return ( CHudElement::ShouldDraw() && ( m_DeathNotices.Count() ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Color CHudBaseDeathNotice::GetTeamColor( int iTeamNumber, bool bLocalPlayerInvolved /* = false */ )
{
// By default, return the standard team color. Subclasses may override this.
return g_PR->GetTeamColor( iTeamNumber );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CHudBaseDeathNotice::UseExistingNotice( IGameEvent *event )
{
if ( FStrEq( event->GetName(), "special_score" ) )
{
int iIndex = event->GetInt( "player" );
// Look for a matching pre-existing notice.
for ( int i = 0; i < m_DeathNotices.Count(); ++i )
{
DeathNoticeItem &msg = m_DeathNotices[i];
if ( !msg.bSpecialScore )
continue;
if ( msg.iKillerID != iIndex )
continue;
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::Paint()
{
// Retire any death notices that have expired
RetireExpiredDeathNotices();
CBaseViewport *pViewport = dynamic_cast<CBaseViewport *>( GetClientModeNormal()->GetViewport() );
int yStart = pViewport->GetDeathMessageStartHeight();
surface()->DrawSetTextFont( m_hTextFont );
int xMargin = XRES( 10 );
int xSpacing = UTIL_ComputeStringWidth( m_hTextFont, L" " );
int iCount = m_DeathNotices.Count();
for ( int i = 0; i < iCount; i++ )
{
DeathNoticeItem &msg = m_DeathNotices[i];
CHudTexture *icon = msg.iconDeath;
CHudTexture *iconPostKillerName = msg.iconPostKillerName;
CHudTexture *iconPreKillerName = msg.iconPreKillerName;
CHudTexture *iconPostVictimName = msg.iconPostVictimName;
wchar_t victim[256]=L"";
wchar_t killer[256]=L"";
// TEMP - print the death icon name if we don't have a material for it
g_pVGuiLocalize->ConvertANSIToUnicode( msg.Victim.szName, victim, sizeof( victim ) );
g_pVGuiLocalize->ConvertANSIToUnicode( msg.Killer.szName, killer, sizeof( killer ) );
int iVictimTextWide = UTIL_ComputeStringWidth( m_hTextFont, victim ) + xSpacing;
int iDeathInfoTextWide= msg.wzInfoText[0] ? UTIL_ComputeStringWidth( m_hTextFont, msg.wzInfoText ) + xSpacing : 0;
int iDeathInfoEndTextWide= msg.wzInfoTextEnd[0] ? UTIL_ComputeStringWidth( m_hTextFont, msg.wzInfoTextEnd ) + xSpacing : 0;
int iKillerTextWide = killer[0] ? UTIL_ComputeStringWidth( m_hTextFont, killer ) + xSpacing : 0;
int iLineTall = m_flLineHeight;
int iTextTall = surface()->GetFontTall( m_hTextFont );
int iconWide = 0, iconTall = 0, iDeathInfoOffset = 0, iVictimTextOffset = 0, iconActualWide = 0;
int iPreKillerTextWide = msg.wzPreKillerText[0] ? UTIL_ComputeStringWidth( m_hTextFont, msg.wzPreKillerText ) - xSpacing : 0;
int iconPrekillerWide = 0, iconPrekillerActualWide = 0, iconPrekillerTall = 0;
int iconPostkillerWide = 0, iconPostkillerActualWide = 0, iconPostkillerTall = 0;
int iconPostVictimWide = 0, iconPostVictimActualWide = 0, iconPostVictimTall = 0;
// Get the local position for this notice
if ( icon )
{
iconActualWide = icon->EffectiveWidth( 1.0f );
iconWide = iconActualWide + xSpacing;
iconTall = icon->EffectiveHeight( 1.0f );
int iconTallDesired = iLineTall-YRES(2);
Assert( 0 != iconTallDesired );
float flScale = (float) iconTallDesired / (float) iconTall;
iconActualWide *= flScale;
iconTall *= flScale;
iconWide *= flScale;
}
if ( iconPreKillerName )
{
iconPrekillerActualWide = iconPreKillerName->EffectiveWidth( 1.0f );
iconPrekillerWide = iconPrekillerActualWide;
iconPrekillerTall = iconPreKillerName->EffectiveHeight( 1.0f );
int iconTallDesired = iLineTall - YRES( 2 );
Assert( 0 != iconTallDesired );
float flScale = (float)iconTallDesired / (float)iconPrekillerTall;
iconPrekillerActualWide *= flScale;
iconPrekillerTall *= flScale;
iconPrekillerWide *= flScale;
}
if ( iconPostKillerName )
{
iconPostkillerActualWide = iconPostKillerName->EffectiveWidth( 1.0f );
iconPostkillerWide = iconPostkillerActualWide;
iconPostkillerTall = iconPostKillerName->EffectiveHeight( 1.0f );
int iconTallDesired = iLineTall-YRES(2);
Assert( 0 != iconTallDesired );
float flScale = (float) iconTallDesired / (float) iconPostkillerTall;
iconPostkillerActualWide *= flScale;
iconPostkillerTall *= flScale;
iconPostkillerWide *= flScale;
}
if ( iconPostVictimName )
{
iconPostVictimActualWide = iconPostVictimName->EffectiveWidth( 1.0f );
iconPostVictimWide = iconPostVictimActualWide;
iconPostVictimTall = iconPostVictimName->EffectiveHeight( 1.0f );
int iconTallDesired = iLineTall - YRES( 2 );
Assert( 0 != iconTallDesired );
float flScale = (float)iconTallDesired / (float)iconPostVictimTall;
iconPostVictimActualWide *= flScale;
iconPostVictimTall *= flScale;
iconPostVictimWide *= flScale;
}
int iTotalWide = iKillerTextWide + iconWide + iVictimTextWide + iDeathInfoTextWide + iDeathInfoEndTextWide + ( xMargin * 2 );
iTotalWide += iconPrekillerWide + iconPostkillerWide + iPreKillerTextWide + iconPostVictimWide;
int y = yStart + ( ( iLineTall + m_flLineSpacing ) * i );
int yText = y + ( ( iLineTall - iTextTall ) / 2 );
int yIcon = y + ( ( iLineTall - iconTall ) / 2 );
int x=0;
if ( m_bRightJustify )
{
x = GetWide() - iTotalWide;
}
// draw a background panel for the message
Vertex_t vert[NUM_BACKGROUND_COORD];
GetBackgroundPolygonVerts( x, y+1, x+iTotalWide, y+iLineTall-1, ARRAYSIZE( vert ), vert );
surface()->DrawSetTexture( -1 );
surface()->DrawSetColor( GetBackgroundColor ( i ) );
surface()->DrawTexturedPolygon( ARRAYSIZE( vert ), vert );
x += xMargin;
// prekiller icon
if ( iconPreKillerName )
{
int yPreIconTall = y + ( ( iLineTall - iconPrekillerTall ) / 2 );
iconPreKillerName->DrawSelf( x, yPreIconTall, iconPrekillerActualWide, iconPrekillerTall, m_clrIcon);
x += iconPrekillerWide + xSpacing;
}
if ( killer[0] )
{
// Draw killer's name
DrawText( x, yText, m_hTextFont, GetTeamColor( msg.Killer.iTeam, msg.bLocalPlayerInvolved ), killer );
x += iKillerTextWide;
}
// prekiller text
if ( msg.wzPreKillerText[0] )
{
x += xSpacing;
DrawText( x + iDeathInfoOffset, yText, m_hTextFont, GetInfoTextColor( i ), msg.wzPreKillerText );
x += iPreKillerTextWide;
}
// postkiller icon
if ( iconPostKillerName )
{
int yPreIconTall = y + ( ( iLineTall - iconPostkillerTall ) / 2 );
iconPostKillerName->DrawSelf( x, yPreIconTall, iconPostkillerActualWide, iconPostkillerTall, m_clrIcon );
x += iconPostkillerWide + xSpacing;
}
// Draw glow behind weapon icon to show it was a crit death
if ( msg.bCrit && msg.iconCritDeath )
{
msg.iconCritDeath->DrawSelf( x, yIcon, iconActualWide, iconTall, m_clrIcon );
}
// Draw death icon
if ( icon )
{
icon->DrawSelf( x, yIcon, iconActualWide, iconTall, m_clrIcon );
x += iconWide;
}
// Draw additional info text next to death icon
if ( msg.wzInfoText[0] )
{
if ( msg.bSelfInflicted )
{
iDeathInfoOffset += iVictimTextWide;
iVictimTextOffset -= iDeathInfoTextWide;
}
DrawText( x + iDeathInfoOffset, yText, m_hTextFont, GetInfoTextColor( i ), msg.wzInfoText );
x += iDeathInfoTextWide;
}
// Draw victims name
DrawText( x + iVictimTextOffset, yText, m_hTextFont, GetTeamColor( msg.Victim.iTeam, msg.bLocalPlayerInvolved ), victim );
x += iVictimTextWide;
// postkiller icon
if ( iconPostVictimName )
{
int yPreIconTall = y + ( ( iLineTall - iconPostVictimTall ) / 2 );
iconPostVictimName->DrawSelf( x, yPreIconTall, iconPostVictimActualWide, iconPostVictimTall, m_clrIcon );
x += iconPostkillerWide + xSpacing;
}
// Draw Additional Text on the end of the victims name
if ( msg.wzInfoTextEnd[0] )
{
DrawText( x , yText, m_hTextFont, GetInfoTextColor( i ), msg.wzInfoTextEnd );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: This message handler may be better off elsewhere
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::RetireExpiredDeathNotices()
{
// Remove any expired death notices. Loop backwards because we might remove one
int iCount = m_DeathNotices.Count();
for ( int i = iCount-1; i >= 0; i-- )
{
if ( gpGlobals->curtime > m_DeathNotices[i].GetExpiryTime() )
{
m_DeathNotices.Remove(i);
}
}
// Do we have too many death messages in the queue?
if ( m_DeathNotices.Count() > 0 &&
m_DeathNotices.Count() > (int)m_flMaxDeathNotices )
{
// First, remove any notices not involving the local player, since they are lower priority.
iCount = m_DeathNotices.Count();
int iNeedToRemove = iCount - (int)m_flMaxDeathNotices;
// loop condition is iCount-1 because we won't remove the most recent death notice, otherwise
// new non-local-player-involved messages would not appear if the queue was full of messages involving the local player
for ( int i = 0; i < iCount-1 && iNeedToRemove > 0 ; i++ )
{
if ( !m_DeathNotices[i].bLocalPlayerInvolved )
{
m_DeathNotices.Remove( i );
iCount--;
iNeedToRemove--;
}
}
// Now that we've culled any non-local-player-involved messages up to the amount we needed to remove, see
// if we've removed enough
iCount = m_DeathNotices.Count();
iNeedToRemove = iCount - (int)m_flMaxDeathNotices;
if ( iNeedToRemove > 0 )
{
// if we still have too many messages, then just remove however many we need, oldest first
for ( int i = 0; i < iNeedToRemove; i++ )
{
m_DeathNotices.Remove( 0 );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CHudBaseDeathNotice::EventIsPlayerDeath( const char* eventName )
{
if ( FStrEq( eventName, "player_death" ) )
return true;
else
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Server's told us that someone's died
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::FireGameEvent( IGameEvent *event )
{
if ( !g_PR )
{
return;
}
if ( hud_deathnotice_time.GetFloat() == 0 )
{
return;
}
int iLocalPlayerIndex = GetLocalPlayerIndex();
const char *pszEventName = event->GetName();
bool bPlayerDeath = EventIsPlayerDeath( pszEventName );
bool bObjectDeath = FStrEq( pszEventName, "object_destroyed" );
bool bSpecialScore = FStrEq( pszEventName, "special_score" );
bool bTeamLeaderKilled = false;
bool bIsFeignDeath = event->GetInt( "death_flags" ) & TF_DEATH_FEIGN_DEATH;
if ( bPlayerDeath )
{
if ( !ShouldShowDeathNotice( event ) )
return;
if ( bIsFeignDeath )
{
// Only display fake death messages to the enemy team.
int victimid = event->GetInt( "userid" );
int victim = engine->GetPlayerForUserID( victimid );
CBasePlayer *pVictim = UTIL_PlayerByIndex( victim );
CBasePlayer *pLocalPlayer = CBasePlayer::GetLocalPlayer();
if ( pVictim && pLocalPlayer &&
!BAreTeamsEnemies( pLocalPlayer->GetTeamNumber(), pVictim->GetTeamNumber() ) )
{
return;
}
if ( iLocalPlayerIndex == victim )
{
return;
}
}
}
// Add a new death message. Note we always look it up by index rather than create a reference or pointer to it;
// additional messages may get added during this function that cause the underlying array to get realloced, so don't
// ever keep a pointer to memory here.
int iMsg = -1;
if ( bPlayerDeath || bSpecialScore )
{
iMsg = UseExistingNotice( event );
}
if ( iMsg == -1 )
{
iMsg = AddDeathNoticeItem();
}
if ( bPlayerDeath || bObjectDeath )
{
int victim = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
int killer = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
const char *killedwith = event->GetString( "weapon" );
const char *killedwithweaponlog = event->GetString( "weapon_logclassname" );
if ( bObjectDeath && victim == 0 )
{
// for now, no death notices of map placed objects
m_DeathNotices.Remove( iMsg );
return;
}
// Get the names of the players
const char *killer_name = ( killer > 0 ) ? g_PR->GetPlayerName( killer ) : "";
const char *victim_name = g_PR->GetPlayerName( victim );
if ( !killer_name )
{
killer_name = "";
}
if ( !victim_name )
{
victim_name = "";
}
// Make a new death notice
bool bLocalPlayerInvolved = false;
if ( iLocalPlayerIndex == killer || iLocalPlayerIndex == victim )
{
bLocalPlayerInvolved = true;
}
if ( event->GetInt( "death_flags" ) & TF_DEATH_AUSTRALIUM )
{
m_DeathNotices[iMsg].bCrit= true;
m_DeathNotices[iMsg].iconCritDeath = GetIcon( "d_australium", bLocalPlayerInvolved ? kDeathNoticeIcon_Inverted : kDeathNoticeIcon_Standard );
}
else if ( event->GetInt( "damagebits" ) & DMG_CRITICAL )
{
m_DeathNotices[iMsg].bCrit= true;
m_DeathNotices[iMsg].iconCritDeath = GetIcon( "d_crit", bLocalPlayerInvolved ? kDeathNoticeIcon_Inverted : kDeathNoticeIcon_Standard );
}
else
{
m_DeathNotices[iMsg].bCrit= false;
m_DeathNotices[iMsg].iconCritDeath = NULL;
}
m_DeathNotices[iMsg].bLocalPlayerInvolved = bLocalPlayerInvolved;
m_DeathNotices[iMsg].Killer.iTeam = ( killer > 0 ) ? g_PR->GetTeam( killer ) : 0;
m_DeathNotices[iMsg].Victim.iTeam = g_PR->GetTeam( victim );
Q_strncpy( m_DeathNotices[iMsg].Killer.szName, killer_name, ARRAYSIZE( m_DeathNotices[iMsg].Killer.szName ) );
Q_strncpy( m_DeathNotices[iMsg].Victim.szName, victim_name, ARRAYSIZE( m_DeathNotices[iMsg].Victim.szName ) );
if ( killedwith && *killedwith )
{
Q_snprintf( m_DeathNotices[iMsg].szIcon, sizeof(m_DeathNotices[iMsg].szIcon), "d_%s", killedwith );
}
if ( !killer || killer == victim )
{
m_DeathNotices[iMsg].bSelfInflicted = true;
m_DeathNotices[iMsg].Killer.szName[0] = 0;
if ( event->GetInt( "death_flags" ) & TF_DEATH_PURGATORY )
{
// special case icon for dying in purgatory
Q_strncpy( m_DeathNotices[iMsg].szIcon, "d_purgatory", ARRAYSIZE( m_DeathNotices[iMsg].szIcon ) );
}
else if ( event->GetInt( "damagebits" ) & DMG_FALL )
{
// special case text for falling death
V_wcsncpy( m_DeathNotices[iMsg].wzInfoText, g_pVGuiLocalize->Find( "#DeathMsg_Fall" ), sizeof( m_DeathNotices[iMsg].wzInfoText ) );
}
else if ( ( event->GetInt( "damagebits" ) & DMG_VEHICLE ) || ( 0 == Q_stricmp( m_DeathNotices[iMsg].szIcon, "d_tracktrain" ) ) )
{
// special case icon for hit-by-vehicle death
Q_strncpy( m_DeathNotices[iMsg].szIcon, "d_vehicle", ARRAYSIZE( m_DeathNotices[iMsg].szIcon ) );
}
}
m_DeathNotices[iMsg].iWeaponID = event->GetInt( "weaponid" );
m_DeathNotices[iMsg].iKillerID = event->GetInt( "attacker" );
m_DeathNotices[iMsg].iVictimID = event->GetInt( "userid" );
char sDeathMsg[512];
// Record the death notice in the console
if ( m_DeathNotices[iMsg].bSelfInflicted )
{
if ( !strcmp( m_DeathNotices[iMsg].szIcon, "d_worldspawn" ) )
{
Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s died.", m_DeathNotices[iMsg].Victim.szName );
}
else // d_world
{
Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s suicided.", m_DeathNotices[iMsg].Victim.szName );
}
}
else
{
Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s killed %s", m_DeathNotices[iMsg].Killer.szName, m_DeathNotices[iMsg].Victim.szName );
if ( killedwithweaponlog && killedwithweaponlog[0] && ( killedwithweaponlog[0] > 13 ) )
{
Q_strncat( sDeathMsg, VarArgs( " with %s.", killedwithweaponlog ), sizeof( sDeathMsg ), COPY_ALL_CHARACTERS );
}
else if ( m_DeathNotices[iMsg].szIcon[0] && ( m_DeathNotices[iMsg].szIcon[0] > 13 ) )
{
Q_strncat( sDeathMsg, VarArgs( " with %s.", &m_DeathNotices[iMsg].szIcon[2] ), sizeof( sDeathMsg ), COPY_ALL_CHARACTERS );
}
}
if ( FStrEq( pszEventName, "player_death" ) )
{
if ( m_DeathNotices[iMsg].bCrit )
{
Msg( "%s (crit)\n", sDeathMsg );
}
else
{
Msg( "%s\n", sDeathMsg );
}
}
}
else if ( FStrEq( "teamplay_point_captured", pszEventName ) )
{
GetLocalizedControlPointName( event, m_DeathNotices[iMsg].Victim.szName, ARRAYSIZE( m_DeathNotices[iMsg].Victim.szName ) );
// Array of capper indices
const char *cappers = event->GetString("cappers");
char szCappers[256];
szCappers[0] = '\0';
int len = Q_strlen(cappers);
for( int i=0;i<len;i++ )
{
int iPlayerIndex = (int)cappers[i];
Assert( iPlayerIndex > 0 && iPlayerIndex <= gpGlobals->maxClients );
const char *pPlayerName = g_PR->GetPlayerName( iPlayerIndex );
if ( i == 0 )
{
// use first player as the team
m_DeathNotices[iMsg].Killer.iTeam = g_PR->GetTeam( iPlayerIndex );
m_DeathNotices[iMsg].Victim.iTeam = TEAM_UNASSIGNED;
}
else
{
Q_strncat( szCappers, ", ", sizeof(szCappers), 2 );
}
Q_strncat( szCappers, pPlayerName, sizeof(szCappers), COPY_ALL_CHARACTERS );
if ( iLocalPlayerIndex == iPlayerIndex )
m_DeathNotices[iMsg].bLocalPlayerInvolved = true;
}
Q_strncpy( m_DeathNotices[iMsg].Killer.szName, szCappers, sizeof(m_DeathNotices[iMsg].Killer.szName) );
V_wcsncpy( m_DeathNotices[iMsg].wzInfoText, g_pVGuiLocalize->Find( len > 1 ? "#Msg_Captured_Multiple" : "#Msg_Captured" ), sizeof( m_DeathNotices[iMsg].wzInfoText ) );
// print a log message
Msg( "%s captured %s for team #%d\n", m_DeathNotices[iMsg].Killer.szName, m_DeathNotices[iMsg].Victim.szName, m_DeathNotices[iMsg].Killer.iTeam );
}
else if ( FStrEq( "teamplay_capture_blocked", pszEventName ) )
{
GetLocalizedControlPointName( event, m_DeathNotices[iMsg].Victim.szName, ARRAYSIZE( m_DeathNotices[iMsg].Victim.szName ) );
V_wcsncpy( m_DeathNotices[iMsg].wzInfoText, g_pVGuiLocalize->Find( "#Msg_Defended" ), sizeof( m_DeathNotices[iMsg].wzInfoText ) );
int iPlayerIndex = event->GetInt( "blocker" );
const char *blocker_name = g_PR->GetPlayerName( iPlayerIndex );
Q_strncpy( m_DeathNotices[iMsg].Killer.szName, blocker_name, ARRAYSIZE( m_DeathNotices[iMsg].Killer.szName ) );
m_DeathNotices[iMsg].Killer.iTeam = g_PR->GetTeam( iPlayerIndex );
if ( iLocalPlayerIndex == iPlayerIndex )
m_DeathNotices[iMsg].bLocalPlayerInvolved = true;
// print a log message
Msg( "%s defended %s for team #%d\n", m_DeathNotices[iMsg].Killer.szName, m_DeathNotices[iMsg].Victim.szName, m_DeathNotices[iMsg].Killer.iTeam );
}
else if ( FStrEq( "teamplay_flag_event", pszEventName ) )
{
// don't handle any flag events for death notices while in player destruction mode
if ( CTFPlayerDestructionLogic::GetRobotDestructionLogic() && CTFPlayerDestructionLogic::GetRobotDestructionLogic()->GetType() == CTFPlayerDestructionLogic::TYPE_PLAYER_DESTRUCTION )
{
// don't put anything up
m_DeathNotices.Remove( iMsg );
return;
}
const char *pszMsgKey = NULL;
int iEventType = event->GetInt( "eventtype" );
bool bIsMvM = TFGameRules() && TFGameRules()->IsMannVsMachineMode();
if ( bIsMvM )
{
// MvM only cares about Defend notifications
if ( iEventType != TF_FLAGEVENT_DEFEND )
{
// unsupported, don't put anything up
m_DeathNotices.Remove( iMsg );
return;
}
}
bool bIsHalloween2014 = TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY );
switch ( iEventType )
{
case TF_FLAGEVENT_PICKUP:
pszMsgKey = bIsHalloween2014 ? "#Msg_PickedUpFlagHalloween2014" : "#Msg_PickedUpFlag";
break;
case TF_FLAGEVENT_CAPTURE:
pszMsgKey = bIsHalloween2014 ? "#Msg_CapturedFlagHalloween2014" : "#Msg_CapturedFlag";
break;
case TF_FLAGEVENT_DEFEND:
if ( bIsMvM )
{
pszMsgKey = "#Msg_DefendedBomb";
}
else
{
pszMsgKey = bIsHalloween2014 ? "#Msg_DefendedFlagHalloween2014" : "#Msg_DefendedFlag";
}
break;
// Add this when we can get localization for it
//case TF_FLAGEVENT_DROPPED:
// pszMsgKey = "#Msg_DroppedFlag";
// break;
default:
// unsupported, don't put anything up
m_DeathNotices.Remove( iMsg );
return;
}
wchar_t *pwzEventText = g_pVGuiLocalize->Find( pszMsgKey );
Assert( pwzEventText );
if ( pwzEventText )
{
V_wcsncpy( m_DeathNotices[iMsg].wzInfoText, pwzEventText, sizeof( m_DeathNotices[iMsg].wzInfoText ) );
}
else
{
V_memset( m_DeathNotices[iMsg].wzInfoText, 0, sizeof( m_DeathNotices[iMsg].wzInfoText ) );
}
int iPlayerIndex = event->GetInt( "player" );
const char *szPlayerName = g_PR->GetPlayerName( iPlayerIndex );
Q_strncpy( m_DeathNotices[iMsg].Killer.szName, szPlayerName, ARRAYSIZE( m_DeathNotices[iMsg].Killer.szName ) );
m_DeathNotices[iMsg].Killer.iTeam = g_PR->GetTeam( iPlayerIndex );
if ( iLocalPlayerIndex == iPlayerIndex )
m_DeathNotices[iMsg].bLocalPlayerInvolved = true;
}
else if ( bSpecialScore )
{
DeathNoticeItem &msg = m_DeathNotices[iMsg];
int iScorer = event->GetInt( "player" );
const char *pszScorer = ( iScorer > 0 ) ? g_PR->GetPlayerName( iScorer ) : "";
if ( !pszScorer )
{
pszScorer = "";
}
Q_strncpy( msg.Killer.szName, pszScorer, ARRAYSIZE( msg.Killer.szName ) );
m_DeathNotices[iMsg].Killer.iTeam = ( iScorer > 0 ) ? g_PR->GetTeam( iScorer ) : 0;
msg.bLocalPlayerInvolved = ( iScorer == GetLocalPlayerIndex() );
msg.iKillerID = iScorer;
msg.bCrit = false;
msg.iconCritDeath = NULL;
msg.bSpecialScore = true;
wchar_t wzCount[10];
_snwprintf( wzCount, ARRAYSIZE( wzCount ), L"%d", ++msg.iCount );
g_pVGuiLocalize->ConstructString_safe( msg.wzInfoText, g_pVGuiLocalize->Find( "#SpecialScore_Count" ), 1, wzCount );
}
else if ( FStrEq( "team_leader_killed", pszEventName ) )
{
DeathNoticeItem &msg = m_DeathNotices[iMsg];
int iKiller = event->GetInt( "killer" );
const char *pszKiller = ( iKiller > 0 ) ? g_PR->GetPlayerName( iKiller ) : "";
if ( !pszKiller )
{
pszKiller = "";
}
Q_strncpy( msg.Killer.szName, pszKiller, ARRAYSIZE( msg.Killer.szName ) );
m_DeathNotices[iMsg].Killer.iTeam = ( iKiller > 0 ) ? g_PR->GetTeam( iKiller ) : 0;
int iVictim = event->GetInt( "victim" );
const char *pszVictim = ( iVictim > 0 ) ? g_PR->GetPlayerName( iVictim ) : "";
if ( !pszVictim )
{
pszVictim = "";
}
Q_strncpy( msg.Victim.szName, pszVictim, ARRAYSIZE( msg.Victim.szName ) );
m_DeathNotices[iMsg].Victim.iTeam = ( iVictim > 0 ) ? g_PR->GetTeam( iVictim ) : 0;
msg.bLocalPlayerInvolved = ( ( iKiller == GetLocalPlayerIndex() ) || ( iVictim == GetLocalPlayerIndex() ) );
msg.iKillerID = iKiller;
msg.iVictimID = iVictim;
msg.bCrit = false;
msg.iconCritDeath = NULL;
wchar_t *pwzEventText = g_pVGuiLocalize->Find( "#TeamLeader_Kill" );
Assert( pwzEventText );
if ( pwzEventText )
{
V_wcsncpy( m_DeathNotices[iMsg].wzInfoText, pwzEventText, sizeof( m_DeathNotices[iMsg].wzInfoText ) );
}
bTeamLeaderKilled = true;
}
OnGameEvent( event, iMsg );
if ( !bSpecialScore && !bTeamLeaderKilled )
{
if ( !m_DeathNotices[iMsg].iconDeath && m_DeathNotices[iMsg].szIcon )
{
// Try and find the death identifier in the icon list
// On consoles, we flip usage of the inverted icon to make it more visible
bool bInverted = m_DeathNotices[iMsg].bLocalPlayerInvolved;
if ( IsConsole() )
{
bInverted = !bInverted;
}
m_DeathNotices[iMsg].iconDeath = GetIcon( m_DeathNotices[iMsg].szIcon, bInverted ? kDeathNoticeIcon_Inverted : kDeathNoticeIcon_Standard );
if ( !m_DeathNotices[iMsg].iconDeath )
{
// Can't find it, so use the default skull & crossbones icon
m_DeathNotices[iMsg].iconDeath = GetIcon( "d_skull_tf", m_DeathNotices[iMsg].bLocalPlayerInvolved ? kDeathNoticeIcon_Inverted : kDeathNoticeIcon_Standard );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Gets the localized name of the control point sent in the event
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::GetLocalizedControlPointName( IGameEvent *event, char *namebuf, int namelen )
{
// Cap point name ( MATTTODO: can't we find this from the point index ? )
const char *pName = event->GetString( "cpname", "Unnamed Control Point" );
const wchar_t *pLocalizedName = g_pVGuiLocalize->Find( pName );
if ( pLocalizedName )
{
g_pVGuiLocalize->ConvertUnicodeToANSI( pLocalizedName, namebuf, namelen );
}
else
{
Q_strncpy( namebuf, pName, namelen );
}
}
//-----------------------------------------------------------------------------
// Purpose: Adds a new death notice to the queue
//-----------------------------------------------------------------------------
int CHudBaseDeathNotice::AddDeathNoticeItem()
{
int iMsg = m_DeathNotices.AddToTail();
DeathNoticeItem &msg = m_DeathNotices[iMsg];
msg.flCreationTime = gpGlobals->curtime;
return iMsg;
}
//-----------------------------------------------------------------------------
// Purpose: draw text helper
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::DrawText( int x, int y, HFont hFont, Color clr, const wchar_t *szText )
{
surface()->DrawSetTextPos( x, y );
surface()->DrawSetTextColor( clr );
surface()->DrawSetTextFont( hFont ); //reset the font, draw icon can change it
surface()->DrawUnicodeString( szText, vgui::FONT_DRAW_NONADDITIVE );
}
//-----------------------------------------------------------------------------
// Purpose: Creates a rounded-corner polygon that fits in the specified bounds
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::GetBackgroundPolygonVerts( int x0, int y0, int x1, int y1, int iVerts, vgui::Vertex_t vert[] )
{
Assert( iVerts == NUM_BACKGROUND_COORD );
// use the offsets we generated for one corner and apply those to the passed-in dimensions to create verts for the poly
for ( int i = 0; i < NUM_CORNER_COORD; i++ )
{
int j = ( NUM_CORNER_COORD-1 ) - i;
// upper left corner
vert[i].Init( Vector2D( x0 + m_CornerCoord[i].x, y0 + m_CornerCoord[i].y ) );
// upper right corner
vert[i+NUM_CORNER_COORD].Init( Vector2D( x1 - m_CornerCoord[j].x, y0 + m_CornerCoord[j].y ) );
// lower right corner
vert[i+(NUM_CORNER_COORD*2)].Init( Vector2D( x1 - m_CornerCoord[i].x, y1 - m_CornerCoord[i].y ) );
// lower left corner
vert[i+(NUM_CORNER_COORD*3)].Init( Vector2D( x0 + m_CornerCoord[j].x, y1 - m_CornerCoord[j].y) );
}
}
//-----------------------------------------------------------------------------
// Purpose: Creates the offsets for rounded corners based on current screen res
//-----------------------------------------------------------------------------
void CHudBaseDeathNotice::CalcRoundedCorners()
{
// generate the offset geometry for upper left corner
int iMax = ARRAYSIZE( m_CornerCoord );
for ( int i = 0; i < iMax; i++ )
{
m_CornerCoord[i].x = m_flCornerRadius * ( 1 - cos( ( (float) i / (float) (iMax - 1 ) ) * ( M_PI / 2 ) ) );
m_CornerCoord[i].y = m_flCornerRadius * ( 1 - sin( ( (float) i / (float) (iMax - 1 ) ) * ( M_PI / 2 ) ) );
}
}
//-----------------------------------------------------------------------------
// Purpose: Gets specified icon
//-----------------------------------------------------------------------------
CHudTexture *CHudBaseDeathNotice::GetIcon( const char *szIcon, EDeathNoticeIconFormat eIconFormat )
{
// adjust the style (prefix) of the icon if requested
if ( eIconFormat != kDeathNoticeIcon_Standard && V_strncmp( "d_", szIcon, 2 ) == 0 )
{
Assert( eIconFormat == kDeathNoticeIcon_Inverted );
const char *cszNewPrefix = "dneg_";
unsigned int iNewPrefixLen = V_strlen( cszNewPrefix );
// generate new string with correct prefix
enum { kIconTempStringLen = 256 };
char szIconTmp[kIconTempStringLen];
V_strncpy( szIconTmp, cszNewPrefix, kIconTempStringLen );
V_strncat( szIconTmp, szIcon + 2, kIconTempStringLen - iNewPrefixLen );
CHudTexture *pIcon = gHUD.GetIcon( szIconTmp );
// return inverted version if found
if ( pIcon )
return pIcon;
}
// we either requested the default style or we requested an alternate style but
// didn't have the art for it; either way, we can't, so fall back to our default
return gHUD.GetIcon( szIcon );
}
//-----------------------------------------------------------------------------
// Purpose: Gets the expiry time for this death notice item
//-----------------------------------------------------------------------------
float DeathNoticeItem::GetExpiryTime()
{
float flDuration = hud_deathnotice_time.GetFloat();
if ( bLocalPlayerInvolved )
{
// if the local player is involved, make the message last longer
flDuration *= 2;
}
return flCreationTime + flDuration;
}
+145
View File
@@ -0,0 +1,145 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef HUD_BASEDEATHNOTICE_H
#define HUD_BASEDEATHNOTICE_H
#ifdef _WIN32
#pragma once
#endif
// Player entries in a death notice
struct DeathNoticePlayer
{
DeathNoticePlayer()
{
szName[0] = 0;
iTeam = TEAM_UNASSIGNED;
}
char szName[MAX_PLAYER_NAME_LENGTH*2]; // big enough for player name and additional information
int iTeam; // team #
};
// Contents of each entry in our list of death notices
struct DeathNoticeItem
{
DeathNoticeItem()
{
szIcon[0]=0;
wzInfoText[0]=0;
wzInfoTextEnd[0]=0;
iconDeath = NULL;
iconCritDeath = NULL;
bSelfInflicted = false;
bLocalPlayerInvolved = false;
bCrit = false;
flCreationTime = 0;
iCount = 0;
iWeaponID = -1;
iKillerID = -1;
iVictimID = -1;
iconPreKillerName = NULL;
iconPostKillerName = NULL;
wzPreKillerText[0] = 0;
iconPostVictimName = NULL;
bSpecialScore = false;
}
float GetExpiryTime();
DeathNoticePlayer Killer;
DeathNoticePlayer Victim;
char szIcon[32]; // name of icon to display
wchar_t wzInfoText[32]; // any additional text to display next to icon
wchar_t wzInfoTextEnd[32]; // any additional text to display next to victim name
CHudTexture *iconDeath;
CHudTexture *iconCritDeath; // crit background icon
CHudTexture *iconPreKillerName;
CHudTexture *iconPostKillerName;
wchar_t wzPreKillerText[32];
CHudTexture *iconPostVictimName;
bool bSelfInflicted;
bool bLocalPlayerInvolved;
bool bCrit;
float flCreationTime;
int iWeaponID;
int iKillerID;
int iVictimID;
int iCount;
bool bSpecialScore;
};
#define NUM_CORNER_COORD 10
#define NUM_BACKGROUND_COORD NUM_CORNER_COORD*4
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CHudBaseDeathNotice : public CHudElement, public vgui::Panel
{
DECLARE_CLASS_SIMPLE( CHudBaseDeathNotice, vgui::Panel );
public:
CHudBaseDeathNotice( const char *pElementName );
void VidInit( void );
virtual void Init( void );
virtual bool ShouldDraw( void );
virtual void Paint( void );
virtual void ApplySchemeSettings( vgui::IScheme *scheme );
void RetireExpiredDeathNotices( void );
virtual void FireGameEvent( IGameEvent *event );
virtual bool ShouldShowDeathNotice( IGameEvent *event ){ return true; }
protected:
virtual Color GetTeamColor( int iTeamNumber, bool bLocalPlayerInvolved = false );
virtual void OnGameEvent( IGameEvent *event, int iDeathNoticeMsg ) {};
void DrawText( int x, int y, vgui::HFont hFont, Color clr, const wchar_t *szText );
int AddDeathNoticeItem();
void GetBackgroundPolygonVerts( int x0, int y0, int x1, int y1, int iVerts, vgui::Vertex_t vert[] );
void CalcRoundedCorners();
enum EDeathNoticeIconFormat
{
kDeathNoticeIcon_Standard,
kDeathNoticeIcon_Inverted, // used for display on lighter background when kill involved the local player
};
CHudTexture *GetIcon( const char *szIcon, EDeathNoticeIconFormat eIconFormat );
virtual bool EventIsPlayerDeath( const char *eventName );
virtual int UseExistingNotice( IGameEvent *event );
void GetLocalizedControlPointName( IGameEvent *event, char *namebuf, int namelen );
virtual Color GetInfoTextColor( int iDeathNoticeMsg ){ return Color( 255, 255, 255, 255 ); }
virtual Color GetBackgroundColor ( int iDeathNoticeMsg ) { return m_DeathNotices[iDeathNoticeMsg].bLocalPlayerInvolved ? m_clrLocalBGColor : m_clrBaseBGColor; }
CPanelAnimationVarAliasType( float, m_flLineHeight, "LineHeight", "16", "proportional_float" );
CPanelAnimationVarAliasType( float, m_flLineSpacing, "LineSpacing", "4", "proportional_float" );
CPanelAnimationVarAliasType( float, m_flCornerRadius, "CornerRadius", "3", "proportional_float" );
CPanelAnimationVar( float, m_flMaxDeathNotices, "MaxDeathNotices", "4" );
CPanelAnimationVar( bool, m_bRightJustify, "RightJustify", "1" );
CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "Default" );
CPanelAnimationVar( Color, m_clrIcon, "IconColor", "255 80 0 255" );
CPanelAnimationVar( Color, m_clrBaseBGColor, "BaseBackgroundColor", "46 43 42 220" );
CPanelAnimationVar( Color, m_clrLocalBGColor, "LocalBackgroundColor", "245 229 196 200" );
CPanelAnimationVar( Color, m_clrKillStreakBg, "KillStreakBackgroundColor", "224 223 219 200" );
CUtlVector<DeathNoticeItem> m_DeathNotices;
Vector2D m_CornerCoord[NUM_CORNER_COORD];
};
#endif // HUD_BASEDEATHNOTICE_H
@@ -0,0 +1,85 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
// c_boss_alpha.cpp
#include "cbase.h"
#include "NextBot/C_NextBot.h"
#include "c_boss_alpha.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#undef NextBot
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_BossAlpha, DT_BossAlpha, CBossAlpha )
RecvPropBool( RECVINFO( m_isNuking ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_BossAlpha::C_BossAlpha()
{
}
//-----------------------------------------------------------------------------
C_BossAlpha::~C_BossAlpha()
{
if ( m_nukeEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_nukeEffect );
m_nukeEffect = NULL;
}
}
//-----------------------------------------------------------------------------
void C_BossAlpha::Spawn( void )
{
BaseClass::Spawn();
m_vecViewOffset = Vector( 0, 0, 180.0f );
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//-----------------------------------------------------------------------------
void C_BossAlpha::ClientThink( void )
{
if ( m_isNuking )
{
if ( !m_nukeEffect )
{
m_nukeEffect = ParticleProp()->Create( "charge_up", PATTACH_POINT_FOLLOW, LookupAttachment( "head" ) );
}
}
else
{
if ( m_nukeEffect )
{
ParticleProp()->StopEmissionAndDestroyImmediately( m_nukeEffect );
m_nukeEffect = NULL;
}
}
}
//-----------------------------------------------------------------------------
// Return the origin for player observers tracking this target
Vector C_BossAlpha::GetObserverCamOrigin( void )
{
return EyePosition();
}
//-----------------------------------------------------------------------------
void C_BossAlpha::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
if ( event == 7001 )
{
EmitSound( "RobotBoss.Footstep" );
}
}
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_BOSS_ALPHA_H
#define C_BOSS_ALPHA_H
#include "c_ai_basenpc.h"
//--------------------------------------------------------------------------------------------------------
/**
* The client-side implementation of Boss Alpha
*/
class C_BossAlpha : public C_NextBotCombatCharacter
{
public:
DECLARE_CLASS( C_BossAlpha, C_NextBotCombatCharacter );
DECLARE_CLIENTCLASS();
C_BossAlpha();
virtual ~C_BossAlpha();
public:
virtual void Spawn( void );
virtual bool IsNextBot() { return true; }
virtual Vector GetObserverCamOrigin( void ); // Return the origin for player observers tracking this target
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void ClientThink();
private:
C_BossAlpha( const C_BossAlpha & ); // not defined, not accessible
CNetworkVar( bool, m_isNuking );
HPARTICLEFFECT m_nukeEffect;
};
#endif // C_BOSS_ALPHA_H
@@ -0,0 +1,25 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#include "cbase.h"
#include "c_tf_tank_boss.h"
#include "tf_hud_boss_health.h"
#include "tf_gamerules.h"
IMPLEMENT_CLIENTCLASS_DT(C_TFBaseBoss, DT_TFBaseBoss, CTFBaseBoss)
RecvPropFloat( RECVINFO( m_lastHealthPercentage ) ),
END_RECV_TABLE()
LINK_ENTITY_TO_CLASS( base_boss, C_TFBaseBoss );
ShadowType_t C_TFBaseBoss::ShadowCastType( void )
{
if ( !IsVisible() )
return SHADOWS_NONE;
if ( IsEffectActive(EF_NODRAW | EF_NOSHADOW) )
return SHADOWS_NONE;
return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
}
@@ -0,0 +1,26 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_TF_BASE_BOSS_H
#define C_TF_BASE_BOSS_H
#include "NextBot/C_NextBot.h"
#include "c_tf_mvm_boss_progress_user.h"
class C_TFBaseBoss : public C_NextBotCombatCharacter, public C_TFMvMBossProgressUser
{
public:
DECLARE_CLASS( C_TFBaseBoss, C_NextBotCombatCharacter );
DECLARE_CLIENTCLASS();
virtual ~C_TFBaseBoss() {}
ShadowType_t ShadowCastType( void );
// ITFMvMBossProgressUser
virtual float GetBossStatusProgress() const OVERRIDE { return m_lastHealthPercentage; }
private:
float m_lastHealthPercentage;
};
#endif // C_TF_BASE_BOSS_H
@@ -0,0 +1,24 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#include "cbase.h"
#include "c_tf_tank_boss.h"
#include "teamplayroundbased_gamerules.h"
IMPLEMENT_CLIENTCLASS_DT(C_TFTankBoss, DT_TFTankBoss, CTFTankBoss)
//RecvPropVector(RECVINFO(m_shadowDirection)),
END_RECV_TABLE()
LINK_ENTITY_TO_CLASS( tank_boss, C_TFTankBoss );
C_TFTankBoss::C_TFTankBoss()
{
}
void C_TFTankBoss::GetGlowEffectColor( float *r, float *g, float *b )
{
TeamplayRoundBasedRules()->GetTeamGlowColor( GetTeamNumber(), *r, *g, *b );
}
@@ -0,0 +1,22 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef C_TF_TANK_BOSS_H
#define C_TF_TANK_BOSS_H
#include "c_tf_base_boss.h"
#include "NextBot/C_NextBot.h"
class C_TFTankBoss : public C_TFBaseBoss
{
public:
DECLARE_CLASS( C_TFTankBoss, C_TFBaseBoss );
DECLARE_CLIENTCLASS();
C_TFTankBoss();
virtual void GetGlowEffectColor( float *r, float *g, float *b );
// ITFMvMBossProgressUser
virtual const char* GetBossProgressImageName() const OVERRIDE { return "tank"; }
};
#endif // C_TF_TANK_BOSS_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,267 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Load item upgrade data from KeyValues
//
// $NoKeywords: $
//=============================================================================
#ifndef C_TF_UPGRADES_H
#define C_TF_UPGRADES_H
#include "c_baseentity.h"
#include "networkvar.h"
#include "econ_item_constants.h"
#include "tf_shareddefs.h"
#include "c_tf_player.h"
#include "hudelement.h"
#include "vgui_controls/EditablePanel.h"
#include "tf_controls.h"
#define MAX_ITEM_SLOT_BUY_PANELS 6
class CItemModelPanel;
class CImageButton;
namespace vgui
{
class ImagePanel;
class Button;
}
enum costlabel_chache_t
{
CLCACHE_DIRTY,
CLCACHE_NOT_AFFORDABLE_1,
CLCACHE_NOT_AFFORDABLE_2,
CLCACHE_NOT_AFFORDABLE_3,
CLCACHE_NOT_AFFORDABLE_4,
CLCACHE_NOT_AFFORDABLE_5,
CLCACHE_NOT_AFFORDABLE_6,
CLCACHE_NOT_AFFORDABLE_7,
CLCACHE_NOT_AFFORDABLE_8,
CLCACHE_NOT_AFFORDABLE_9,
CLCACHE_AFFORDABLE,
};
//-----------------------------------------------------------------------------
// Purpose: HUD Element that provides the interface to the upgrade options
//-----------------------------------------------------------------------------
class CUpgradeBuyPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CUpgradeBuyPanel, vgui::EditablePanel );
public:
enum ColorSet
{
COLOR_SET_DEFAULT,
COLOR_SET_OWNED,
COLOR_SET_PURCHASED,
COLOR_SET_DISABLED,
};
public:
CUpgradeBuyPanel( Panel *parent, const char *panelName );
virtual ~CUpgradeBuyPanel();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
bool ValidateUpgradeStepData( void );
void SetNumLevelImages( int nValues );
void SetSkillTreeButtonColors( int nButton, ColorSet nColorSet );
void SetInspectMode( bool bValue ) { m_bInspectMode = bValue; }
void SetPlayer( C_TFPlayer *pPlayer ) { m_hPlayer = pPlayer; }
void UpdateImages( int nCurrentMoney );
public:
KeyValues *m_pSkillTreeButtonKVs;
vgui::ImagePanel *m_pIcon;
vgui::Label *m_pPriceLabel;
vgui::Label *m_pShortDescriptionLabel;
CImageButton *m_pIncrementButton;
CImageButton *m_pDecrementButton;
CUtlVector< vgui::ImagePanel* > m_SkillTreeImages;
int m_nWeaponSlot;
int m_nUpgradeIndex;
int m_nPrice;
int m_nGridPositionX;
int m_nGridPositionY;
int m_nCurrentStep;
int m_nPurchases;
bool m_bOverCap;
char m_szAttribName[MAX_ATTRIBUTE_DESCRIPTION_LENGTH];
bool m_bInspectMode;
CPanelAnimationVarAliasType( int, m_iUpgradeButtonXPos, "upgradebutton_xpos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iUpgradeButtonYPos, "upgradebutton_ypos", "0", "proportional_int" );
static Color m_rgbaDefaultFG;
static Color m_rgbaDefaultBG;
static Color m_rgbaArmedFG;
static Color m_rgbaArmedBG;
static Color m_rgbaDepressedFG;
static Color m_rgbaDepressedBG;
static Color m_rgbaSelectedFG;
static Color m_rgbaSelectedBG;
static Color m_rgbaDisabledFG;
static Color m_rgbaDisabledBG;
private:
CHandle< C_TFPlayer > m_hPlayer;
};
struct ItemSlotBuyPanels
{
static const int CHARACTER_UPGRADE = -1;
static const int INVALID_SLOT = -2;
typedef CUpgradeBuyPanel *UPGRADEPTR;
class CUpgradeBuyPanelLess
{
public:
bool Less( const UPGRADEPTR &src1, const UPGRADEPTR &src2, void *pCtx )
{
if ( src1->m_nPrice > src2->m_nPrice )
return true;
if ( src1->m_nPrice == src2->m_nPrice && src1->m_nUpgradeIndex < src2->m_nUpgradeIndex )
return true;
return false;
}
};
ItemSlotBuyPanels()
{
nSlot = INVALID_SLOT;
m_iItemID = INVALID_ITEM_ID;
}
void SetItemID( int iIndex ) { m_iItemID = iIndex; }
itemid_t GetItemID( void ) { return m_iItemID; }
int nSlot;
CUtlSortVector< CUpgradeBuyPanel*, CUpgradeBuyPanelLess > upgradeBuyPanels;
itemid_t m_iItemID;
};
//-----------------------------------------------------------------------------
// Purpose: HUD Element that provides the interface to the upgrade options
//-----------------------------------------------------------------------------
class CHudUpgradePanel : public CHudElement, public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CHudUpgradePanel, vgui::EditablePanel );
public:
CHudUpgradePanel( const char *pElementName );
virtual ~CHudUpgradePanel();
virtual void ApplySchemeSettings( vgui::IScheme *scheme );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void PerformLayout( void );
virtual bool ShouldDraw( void );
virtual void SetVisible( bool bVisible );
virtual void SetActive( bool bActive );
virtual int GetRenderGroupPriority( void ) { return 35; } // less than statpanel
virtual void OnCommand( const char *command );
virtual void OnTick( void );
virtual void FireGameEvent( IGameEvent *event );
void InspectUpgradesForPlayer( C_TFPlayer *pPlayer ) { m_hPlayer = pPlayer; m_bInspectMode = true; m_bShowUpgradeMenu = true; }
C_TFPlayer *GetPlayer( void ) { return m_hPlayer; }
void PlayerInventoryChanged( C_TFPlayer *pPlayer );
MESSAGE_FUNC_PTR( OnItemPanelEntered, "ItemPanelEntered", panel );
MESSAGE_FUNC_PTR( OnItemPanelExited, "ItemPanelExited", panel );
MESSAGE_FUNC_PTR( OnItemPanelMousePressed, "ItemPanelMousePressed", panel );
virtual GameActionSet_t GetPreferredActionSet() { return GAME_ACTION_SET_MENUCONTROLS; }
protected:
void CreateItemModelPanel( int iLoadoutSlot );
void UpdateModelPanels( void );
virtual void SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver );
void UpgradeItemInSlot( int iSlot );
void UpdateUpgradeButtons( void );
void UpdateButtonStates( int nCurrentCurrency, int nUpgrade = 0, int nNumPurchased = 0 );
void UpdateJoystickControls( void );
void UpdateHighlights( void );
void UpdateMouseOverHighlight( void );
void UpdateItemStatsLabel( void );
void CancelUpgrades( void );
void AddItemStatText( const locchar_t *loc_AttrDescText, attrib_colors_t eColor, wchar_t *out_wszAttribDesc, int iAttribDescSize );
CEconItemView* GetLocalPlayerBottleFromInventory( void );
bool QuickEquipBottle( void );
protected:
vgui::EditablePanel *m_pTipPanel;
vgui::EditablePanel *m_pSelectWeaponPanel;
CExLabel *m_pUpgradeItemStatsLabel;
vgui::Panel *m_pPlayerUpgradeButton;
vgui::Panel *m_pActiveTabPanel;
vgui::Panel *m_pMouseOverTabPanel;
vgui::Panel *m_pMouseOverUpgradePanel;
CUpgradeBuyPanel *m_pActiveUpgradeBuyPanel;
vgui::Panel *m_pPlayerRespecButton;
CUtlVector< CItemModelPanel* > m_pItemPanels;
KeyValues *m_pItemModelPanelKVs;
int m_iVisibleItemPanels;
int m_iWeaponSlotBeingUpgraded;
bool m_bShowUpgradeMenu;
bool m_bCancelUpgrades;
bool m_bOpenLoadout;
bool m_bWasInZone;
bool m_bHighlightedTab;
bool m_bInspectMode;
int m_nCurrency;
int m_nUpgradeActivity;
bool m_bAwardMaxSlotAchievement;
bool m_bAwardMaxResistAchievement;
ItemSlotBuyPanels m_ItemSlotBuyPanels[ MAX_ITEM_SLOT_BUY_PANELS ];
CPanelAnimationVarAliasType( int, m_iItemPanelXPos, "itempanel_xpos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iItemPanelYPos, "itempanel_ypos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iItemPanelXDelta, "itempanel_xdelta", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iItemPanelYDelta, "itempanel_ydelta", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iUpgradeBuyPanelXPos, "upgradebuypanel_xpos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iUpgradeBuyPanelYPos, "upgradebuypanel_ypos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iUpgradeBuyPanelDelta, "upgradebuypanel_delta", "0", "proportional_int" );
bool m_bNavUpDownPressed;
bool m_bNavLeftRightPressed;
bool m_bNavButtonPressed;
bool m_bUsingController;
private:
void UpdateTip();
CHandle< C_TFPlayer > m_hPlayer;
};
extern bool MannVsMachine_GetUpgradeInfo( int iAttribute, int iQuality, float &flValue );
#endif // C_TF_UPGRADES_H
+87
View File
@@ -0,0 +1,87 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=============================================================================
#include "cbase.h"
#include "proxyentity.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "c_team.h"
#include "tf_shareddefs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//=============================================================================
//
// Team Material Proxy
//
// Handles changing team color (skins).
//
class CTeamMaterialProxy : public CEntityMaterialProxy
{
public:
CTeamMaterialProxy();
virtual ~CTeamMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues* pKeyValues );
virtual void OnBind( C_BaseEntity *pEnt );
virtual IMaterial *GetMaterial();
private:
IMaterialVar* m_FrameVar;
};
//-----------------------------------------------------------------------------
// Purpose: Constructor.
//-----------------------------------------------------------------------------
CTeamMaterialProxy::CTeamMaterialProxy()
{
m_FrameVar = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor.
//-----------------------------------------------------------------------------
CTeamMaterialProxy::~CTeamMaterialProxy()
{
}
//-----------------------------------------------------------------------------
// Purpose: Initialization.
//-----------------------------------------------------------------------------
bool CTeamMaterialProxy::Init( IMaterial *pMaterial, KeyValues* pKeyValues )
{
bool foundVar;
m_FrameVar = pMaterial->FindVar( "$frame", &foundVar, false );
if( !foundVar )
{
m_FrameVar = 0;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Set the appropriate texture (in the animated texture).
//-----------------------------------------------------------------------------
void CTeamMaterialProxy::OnBind( C_BaseEntity *pEnt )
{
if( !m_FrameVar )
return;
int team = pEnt->GetRenderTeamNumber();
team -= 2;
// Use that as an animated frame number
m_FrameVar->SetIntValue( team );
}
IMaterial *CTeamMaterialProxy::GetMaterial()
{
if ( !m_FrameVar )
return NULL;
return m_FrameVar->GetOwningMaterial();
}
EXPOSE_INTERFACE( CTeamMaterialProxy, IMaterialProxy, "TeamTexture" IMATERIAL_PROXY_INTERFACE_VERSION );
+116
View File
@@ -0,0 +1,116 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Generic in-game abuse reporting
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "tf_abuse_report.h"
#include "abuse_report_ui.h"
#include "game/client/iviewport.h"
#include "tf_shareddefs.h"
#include "tf_hud_mainmenuoverride.h"
#include "tf_gcmessages.h"
#include "c_tf_player.h"
#include "tf_quickplay_shared.h"
#include "tf_gc_client.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
/// Declare singleton object
CTFAbuseReportManager theAbuseReportManager;
CTFAbuseReportManager::CTFAbuseReportManager() {}
CTFAbuseReportManager::~CTFAbuseReportManager() {}
bool CTFAbuseReportManager::CreateAndPopulateIncident()
{
if ( !CAbuseReportManager::CreateAndPopulateIncident() )
{
return false;
}
if ( m_bTestReport )
{
return true;
}
for ( int iPlayer = 0 ; iPlayer < m_pIncidentData->m_vecPlayers.Count() ; ++iPlayer )
{
AbuseIncidentData_t::PlayerData_t *p = &m_pIncidentData->m_vecPlayers[iPlayer];
CPlayerInventory *pInv = InventoryManager()->GetInventoryForAccount( p->m_steamID.GetAccountID() );
//C_TFPlayer *pTFPlayer = dynamic_cast<C_TFPlayer *> ( UTIL_PlayerByIndex( p->m_iClientIndex ) );
//if ( pTFPlayer == NULL )
//{
// Assert( !p->m_bHasEntity );
// continue;
//}
//CTFPlayerInventory *pInv = pTFPlayer->Inventory();
if ( pInv == NULL )
{
Warning( "No inventory data for player '%s'; we won't be able to report this person for inappropriate custom images\n", p->m_sPersona.String() );
continue;
}
for ( int i = 0 ; i < pInv->GetItemCount() ; ++i)
{
CEconItemView *pItem = pInv->GetItem( i );
// Get custom texture ID, if any
uint64 hCustomtextureID = pItem->GetCustomUserTextureID();
// Most items won't have a custom texture
if ( hCustomtextureID == 0 )
{
continue;
}
// Discard duplicates, as it makes the UI confusing
bool bDup = false;
for ( int j = 0 ; j < p->m_vecImages.Count() ; ++j )
{
if ( p->m_vecImages[ j ].m_hUGCHandle == hCustomtextureID )
{
bDup = true;
break;
}
}
if ( bDup )
{
continue;
}
AbuseIncidentData_t::PlayerImage_t img;
img.m_eType = AbuseIncidentData_t::k_PlayerImageType_UGC;
img.m_hUGCHandle = hCustomtextureID;
p->m_vecImages.AddToTail( img );
}
}
// Check if we can report abuse against the game server.
if (m_pIncidentData->m_adrGameServer.IsValid() &&
!GTFGCClientSystem()->BIsIPRecentMatchServer( m_pIncidentData->m_adrGameServer ) )
{
m_pIncidentData->m_bCanReportGameServer = true;
}
return true;
}
void CTFAbuseReportManager::ActivateSubmitReportUI()
{
Assert( g_AbuseReportDlg.Get() == NULL );
Assert( m_pIncidentData != NULL );
IViewPortPanel *pMMOverride = ( gViewPortInterface->FindPanelByName( PANEL_MAINMENUOVERRIDE ) );
engine->ExecuteClientCmd("gameui_activate");
vgui::SETUP_PANEL( new CAbuseReportDlg( (CHudMainMenuOverride*)pMMOverride, m_pIncidentData ) );
Assert( g_AbuseReportDlg.Get() != NULL );
g_AbuseReportDlg->MakeModal();
}

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