upload "kind" alien swarm

This commit is contained in:
nillerusr
2023-10-03 17:23:56 +03:00
parent b7bd94c52e
commit 7d3c0d8b5a
4229 changed files with 462900 additions and 495155 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Drops particles where the entity was.
//
+8 -5
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright (c) 1996-2006, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -23,10 +23,12 @@ class CGameEventListener : public IGameEventListener2
public:
CGameEventListener() : m_bRegisteredForEvents(false)
{
m_nDebugID = EVENT_DEBUG_ID_INIT;
}
~CGameEventListener()
{
m_nDebugID = EVENT_DEBUG_ID_SHUTDOWN;
StopListeningForAllEvents();
}
@@ -39,8 +41,8 @@ public:
#else
bool bServerSide = true;
#endif
if ( gameeventmanager )
gameeventmanager->AddListener( this, name, bServerSide );
gameeventmanager->AddListener( this, name, bServerSide );
}
void StopListeningForAllEvents()
@@ -48,14 +50,15 @@ public:
// remove me from list
if ( m_bRegisteredForEvents )
{
if ( gameeventmanager )
gameeventmanager->RemoveListener( this );
gameeventmanager->RemoveListener( this );
m_bRegisteredForEvents = false;
}
}
// Intentionally abstract
virtual void FireGameEvent( IGameEvent *event ) = 0;
int m_nDebugID;
virtual int GetEventDebugID( void ) { return m_nDebugID; }
private:
+5 -1512
View File
File diff suppressed because it is too large Load Diff
+200
View File
@@ -0,0 +1,200 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef GAMESTATS_H
#define GAMESTATS_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utldict.h"
#include "tier1/utlbuffer.h"
#include "igamesystem.h"
const int GAMESTATS_VERSION = 1;
enum StatSendType_t
{
STATSEND_LEVELSHUTDOWN,
STATSEND_APPSHUTDOWN
};
struct StatsBufferRecord_t
{
float m_flFrameRate; // fps
float m_flServerPing; // client ping to server
};
#define STATS_WINDOW_SIZE ( 60 * 10 ) // # of records to hold
#define STATS_RECORD_INTERVAL 1 // # of seconds between data grabs. 2 * 300 = every 10 minutes
class CGameStats;
void UpdatePerfStats( void );
void SetGameStatsHandler( CGameStats *pGameStats );
class CBasePlayer;
class CPropVehicleDriveable;
class CTakeDamageInfo;
#ifdef GAME_DLL
#define GAMESTATS_STANDARD_NOT_SAVED 0xFEEDBEEF
enum GameStatsVersions_t
{
GAMESTATS_FILE_VERSION_OLD = 001,
GAMESTATS_FILE_VERSION_OLD2,
GAMESTATS_FILE_VERSION_OLD3,
GAMESTATS_FILE_VERSION_OLD4,
GAMESTATS_FILE_VERSION_OLD5,
GAMESTATS_FILE_VERSION
};
struct BasicGameStatsRecord_t
{
};
struct BasicGameStats_t
{
};
#endif // GAME_DLL
class CBaseGameStats
{
public:
CBaseGameStats() { }
// override this to declare what format you want to send. New products should use new format.
virtual bool UseOldFormat()
{
#ifdef GAME_DLL
return true; // servers by default send old format for backward compat
#else
return false; // clients never used old format so no backward compat issues, they use new format by default
#endif
}
// Implement this if you support new format gamestats.
// Return true if you added data to KeyValues, false if you have no data to report
virtual bool AddDataForSend( KeyValues *pKV, StatSendType_t sendType ) { return false; }
// These methods used for new format gamestats only and control when data gets sent.
virtual bool ShouldSendDataOnLevelShutdown()
{
// by default, servers send data at every level change and clients don't
#ifdef GAME_DLL
return true;
#else
return false;
#endif
}
virtual bool ShouldSendDataOnAppShutdown()
{
// by default, clients send data at app shutdown and servers don't
#ifdef GAME_DLL
return false;
#else
return true;
#endif
}
virtual void Event_Init( void ) { }
virtual void Event_Shutdown( void ) { }
virtual void Event_MapChange( const char *szOldMapName, const char *szNewMapName ) { }
virtual void Event_LevelInit( void ) { }
virtual void Event_LevelShutdown( float flElapsed ) { }
virtual void Event_SaveGame( void ) { }
virtual void Event_LoadGame( void ) { }
void StatsLog( char const *fmt, ... ) { }
// This is the first call made, so that we can "subclass" the CBaseGameStats based on gamedir as needed (e.g., ep2 vs. episodic)
virtual CBaseGameStats *OnInit( CBaseGameStats *pCurrentGameStats, char const *gamedir ) { return pCurrentGameStats; }
// Frees up data from gamestats and resets it to a clean state.
virtual void Clear( void ) { }
virtual bool StatTrackingEnabledForMod( void ) { return false; } //Override this to turn on the system. Stat tracking is disabled by default and will always be disabled at the user's request
static bool StatTrackingAllowed( void ) { } //query whether stat tracking is possible and warranted by the user
virtual bool HaveValidData( void ) { return true; } // whether we currently have an interesting enough data set to upload. Called at upload time { } if false, data is not uploaded.
virtual bool ShouldTrackStandardStats( void ) { return true; } //exactly what was tracked for EP1 release
//Get mod specific strings used for tracking, defaults should work fine for most cases
virtual const char *GetStatSaveFileName( void ) { return ""; }
virtual const char *GetStatUploadRegistryKeyName( void ) { return ""; }
const char *GetUserPseudoUniqueID( void ) { }
virtual bool UserPlayedAllTheMaps( void ) { return false; } //be sure to override this to determine user completion time
#ifdef GAME_DLL
virtual void Event_PlayerKilled( CBasePlayer *pPlayer, const CTakeDamageInfo &info ) { }
virtual void Event_PlayerConnected( CBasePlayer *pBasePlayer ) { }
virtual void Event_PlayerDisconnected( CBasePlayer *pBasePlayer ) { }
virtual void Event_PlayerDamage( CBasePlayer *pBasePlayer, const CTakeDamageInfo &info ) { }
virtual void Event_PlayerKilledOther( CBasePlayer *pAttacker, CBaseEntity *pVictim, const CTakeDamageInfo &info ) { }
virtual void Event_Credits() { }
virtual void Event_Commentary() { }
virtual void Event_CrateSmashed() { }
virtual void Event_Punted( CBaseEntity *pObject ) { }
virtual void Event_PlayerTraveled( CBasePlayer *pBasePlayer, float distanceInInches, bool bInVehicle, bool bSprinting ) { }
virtual void Event_WeaponFired( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName ) { }
virtual void Event_WeaponHit( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName, const CTakeDamageInfo &info ) { }
virtual void Event_FlippedVehicle( CBasePlayer *pDriver, CPropVehicleDriveable *pVehicle ) { }
virtual void Event_PreSaveGameLoaded( char const *pSaveName, bool bInGame ) { }
virtual void Event_PlayerEnteredGodMode( CBasePlayer *pBasePlayer ) { }
virtual void Event_PlayerEnteredNoClip( CBasePlayer *pBasePlayer ) { }
virtual void Event_DecrementPlayerEnteredNoClip( CBasePlayer *pBasePlayer ) { }
virtual void Event_IncrementCountedStatistic( const Vector& vecAbsOrigin, char const *pchStatisticName, float flIncrementAmount ) { }
//custom data to tack onto existing stats if you're not doing a complete overhaul
virtual void AppendCustomDataToSaveBuffer( CUtlBuffer &SaveBuffer ) { } //custom data you want thrown into the default save and upload path
virtual void LoadCustomDataFromBuffer( CUtlBuffer &LoadBuffer ) { } //when loading the saved stats file, this will point to where you started saving data to the save buffer
virtual void LoadingEvent_PlayerIDDifferentThanLoadedStats( void ) { } //Only called if you use the base SaveToFileNOW() and LoadFromFile() functions. Used in case you want to keep/invalidate data that was just loaded.
virtual bool LoadFromFile( void ) { return false; } //called just before Event_Init()
virtual bool SaveToFileNOW( bool bForceSyncWrite = false ) { return false; } //saves buffers to their respective files now, returns success or failure
virtual bool UploadStatsFileNOW( void ) { return false; } //uploads data to the CSER now, returns success or failure
static bool AppendLump( int nMaxLumpCount, CUtlBuffer &SaveBuffer, unsigned short iLump, unsigned short iLumpCount, size_t nSize, void *pData ) { return false; }
static bool GetLumpHeader( int nMaxLumpCount, CUtlBuffer &LoadBuffer, unsigned short &iLump, unsigned short &iLumpCount, bool bPermissive = false ) { return false; }
static void LoadLump( CUtlBuffer &LoadBuffer, unsigned short iLumpCount, size_t nSize, void *pData ) { }
//default save behavior is to save on level shutdown, and game shutdown
virtual bool AutoSave_OnInit( void ) { return false; }
virtual bool AutoSave_OnShutdown( void ) { return true; }
virtual bool AutoSave_OnMapChange( void ) { return false; }
virtual bool AutoSave_OnLevelInit( void ) { return false; }
virtual bool AutoSave_OnLevelShutdown( void ) { return true; }
//default upload behavior is to upload on game shutdown
virtual bool AutoUpload_OnInit( void ) { return false; }
virtual bool AutoUpload_OnShutdown( void ) { return true; }
virtual bool AutoUpload_OnMapChange( void ) { return false; }
virtual bool AutoUpload_OnLevelInit( void ) { return false; }
virtual bool AutoUpload_OnLevelShutdown( void ) { return false; }
// Helper for builtin stuff
void SetSteamStatistic( bool bUsingSteam ) { }
void SetCyberCafeStatistic( bool bIsCyberCafeUser ) { }
void SetHDRStatistic( bool bHDREnabled ) { }
void SetCaptionsStatistic( bool bClosedCaptionsEnabled ) { }
void SetSkillStatistic( int iSkillSetting ) { }
void SetDXLevelStatistic( int iDXLevel ) { }
#endif // GAMEDLL
public:
#ifdef GAME_DLL
BasicGameStats_t m_BasicStats; //exposed in case you do a complete overhaul and still want to save it
#endif
bool m_bLogging : 1;
bool m_bLoggingToFile : 1;
};
extern CBaseGameStats *gamestats; //starts out pointing at a singleton of the class above, overriding this in any constructor should work for replacing it
#endif // GAMESTATS_H
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client-server neutral effects interface
//
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
+14 -4
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
@@ -10,6 +10,10 @@
#include "eventlist.h"
#include "scriptevent.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
extern ISoundEmitterSystemBase *soundemitterbase;
CStudioHdr *ModelSoundsCache_LoadModel( char const *filename );
@@ -33,6 +37,10 @@ void VerifySequenceIndex( CStudioHdr *pstudiohdr );
extern ISoundEmitterSystemBase *soundemitterbase;
CModelSoundsCache::CModelSoundsCache()
{
}
CModelSoundsCache::CModelSoundsCache( const CModelSoundsCache& src )
{
sounds = src.sounds;
@@ -139,15 +147,17 @@ void CModelSoundsCache::BuildAnimationEventSoundList( CStudioHdr *hdr, CUtlVecto
// Now read out all the sound events with their timing
for ( int iEvent=0; iEvent < (int)pSeq->numevents; iEvent++ )
{
mstudioevent_t *pEvent = pSeq->pEvent( iEvent );
mstudioevent_t *pEvent = (mstudioevent_for_client_server_t*)pSeq->pEvent( iEvent );
switch ( pEvent->event )
int nEvent = pEvent->Event();
switch ( nEvent )
{
default:
{
if ( pEvent->type & AE_TYPE_NEWEVENTSYSTEM )
{
if ( pEvent->event == AE_SV_PLAYSOUND )
if ( nEvent == AE_SV_PLAYSOUND )
{
FindOrAddScriptSound( sounds, pEvent->pszOptions() );
}
+2 -2
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
@@ -23,7 +23,7 @@ class CModelSoundsCache : public IBaseCacheInfo
public:
CUtlVector< unsigned short > sounds;
CModelSoundsCache() = default;
CModelSoundsCache();
CModelSoundsCache( const CModelSoundsCache& src );
void PrecacheSoundList();
File diff suppressed because it is too large Load Diff
@@ -1,343 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef MULTIPLAYERANIMSTATE_H
#define MULTIPLAYERANIMSTATE_H
#ifdef _WIN32
#pragma once
#endif
#include "convar.h"
#include "basecombatweapon_shared.h"
#include "iplayeranimstate.h"
#if defined( CLIENT_DLL )
class C_BasePlayer;
#define CPlayer C_BasePlayer
#else
class CBasePlayer;
#endif
enum PlayerAnimEvent_t
{
PLAYERANIMEVENT_ATTACK_PRIMARY,
PLAYERANIMEVENT_ATTACK_SECONDARY,
PLAYERANIMEVENT_ATTACK_GRENADE,
PLAYERANIMEVENT_RELOAD,
PLAYERANIMEVENT_RELOAD_LOOP,
PLAYERANIMEVENT_RELOAD_END,
PLAYERANIMEVENT_JUMP,
PLAYERANIMEVENT_SWIM,
PLAYERANIMEVENT_DIE,
PLAYERANIMEVENT_FLINCH_CHEST,
PLAYERANIMEVENT_FLINCH_HEAD,
PLAYERANIMEVENT_FLINCH_LEFTARM,
PLAYERANIMEVENT_FLINCH_RIGHTARM,
PLAYERANIMEVENT_FLINCH_LEFTLEG,
PLAYERANIMEVENT_FLINCH_RIGHTLEG,
PLAYERANIMEVENT_DOUBLEJUMP,
// Cancel.
PLAYERANIMEVENT_CANCEL,
PLAYERANIMEVENT_SPAWN,
// Snap to current yaw exactly
PLAYERANIMEVENT_SNAP_YAW,
PLAYERANIMEVENT_CUSTOM, // Used to play specific activities
PLAYERANIMEVENT_CUSTOM_GESTURE,
PLAYERANIMEVENT_CUSTOM_SEQUENCE, // Used to play specific sequences
PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE,
// TF Specific. Here until there's a derived game solution to this.
PLAYERANIMEVENT_ATTACK_PRE,
PLAYERANIMEVENT_ATTACK_POST,
PLAYERANIMEVENT_GRENADE1_DRAW,
PLAYERANIMEVENT_GRENADE2_DRAW,
PLAYERANIMEVENT_GRENADE1_THROW,
PLAYERANIMEVENT_GRENADE2_THROW,
PLAYERANIMEVENT_VOICE_COMMAND_GESTURE,
PLAYERANIMEVENT_DOUBLEJUMP_CROUCH,
PLAYERANIMEVENT_STUN_BEGIN,
PLAYERANIMEVENT_STUN_MIDDLE,
PLAYERANIMEVENT_STUN_END,
PLAYERANIMEVENT_ATTACK_PRIMARY_SUPER,
PLAYERANIMEVENT_COUNT
};
// Gesture Slots.
enum
{
GESTURE_SLOT_ATTACK_AND_RELOAD,
GESTURE_SLOT_GRENADE,
GESTURE_SLOT_JUMP,
GESTURE_SLOT_SWIM,
GESTURE_SLOT_FLINCH,
GESTURE_SLOT_VCD,
GESTURE_SLOT_CUSTOM,
GESTURE_SLOT_COUNT,
};
#define GESTURE_SLOT_INVALID -1
struct GestureSlot_t
{
int m_iGestureSlot;
Activity m_iActivity;
bool m_bAutoKill;
bool m_bActive;
CAnimationLayer *m_pAnimLayer;
};
inline bool IsCustomPlayerAnimEvent( PlayerAnimEvent_t event )
{
return ( event == PLAYERANIMEVENT_CUSTOM ) || ( event == PLAYERANIMEVENT_CUSTOM_GESTURE ) ||
( event == PLAYERANIMEVENT_CUSTOM_SEQUENCE ) || ( event == PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE );
}
struct MultiPlayerPoseData_t
{
int m_iMoveX;
int m_iMoveY;
int m_iAimYaw;
int m_iAimPitch;
int m_iBodyHeight;
int m_iMoveYaw;
int m_iMoveScale;
float m_flEstimateYaw;
float m_flLastAimTurnTime;
void Init()
{
m_iMoveX = 0;
m_iMoveY = 0;
m_iAimYaw = 0;
m_iAimPitch = 0;
m_iBodyHeight = 0;
m_iMoveYaw = 0;
m_iMoveScale = 0;
m_flEstimateYaw = 0.0f;
m_flLastAimTurnTime = 0.0f;
}
};
struct DebugPlayerAnimData_t
{
float m_flSpeed;
float m_flAimPitch;
float m_flAimYaw;
float m_flBodyHeight;
Vector2D m_vecMoveYaw;
void Init()
{
m_flSpeed = 0.0f;
m_flAimPitch = 0.0f;
m_flAimYaw = 0.0f;
m_flBodyHeight = 0.0f;
m_vecMoveYaw.Init();
}
};
struct MultiPlayerMovementData_t
{
// Set speeds to -1 if they are not used.
float m_flWalkSpeed;
float m_flRunSpeed;
float m_flSprintSpeed;
float m_flBodyYawRate;
};
//=============================================================================
//
// Multi-Player Animation State
//
class CMultiPlayerAnimState
{
public:
DECLARE_CLASS_NOBASE( CMultiPlayerAnimState );
// Creation/Destruction
CMultiPlayerAnimState() {}
CMultiPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData );
virtual ~CMultiPlayerAnimState();
// This is called by both the client and the server in the same way to trigger events for
// players firing, jumping, throwing grenades, etc.
virtual void ClearAnimationState();
virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 );
virtual Activity CalcMainActivity();
virtual void Update( float eyeYaw, float eyePitch );
virtual void Release( void );
const QAngle &GetRenderAngles();
virtual Activity TranslateActivity( Activity actDesired );
virtual void SetRunSpeed( float flSpeed ) { m_MovementData.m_flRunSpeed = flSpeed; }
virtual void SetWalkSpeed( float flSpeed ) { m_MovementData.m_flWalkSpeed = flSpeed; }
virtual void SetSprintSpeed( float flSpeed ) { m_MovementData.m_flSprintSpeed = flSpeed; }
// Debug
virtual void ShowDebugInfo( void );
virtual void DebugShowAnimState( int iStartLine );
Activity GetCurrentMainActivity( void ) { return m_eCurrentMainSequenceActivity; }
void OnNewModel( void );
// Gestures.
void ResetGestureSlots( void );
void ResetGestureSlot( int iGestureSlot );
void AddVCDSequenceToGestureSlot( int iGestureSlot, int iGestureSequence, float flCycle = 0.0f, bool bAutoKill = true );
CAnimationLayer* GetGestureSlotLayer( int iGestureSlot );
bool IsGestureSlotActive( int iGestureSlot );
bool VerifyAnimLayerInSlot( int iGestureSlot );
// Feet.
bool m_bForceAimYaw;
protected:
virtual void Init( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData );
CBasePlayer *GetBasePlayer( void ) { return m_pPlayer; }
// Allow inheriting classes to override SelectWeightedSequence
virtual int SelectWeightedSequence( Activity activity ) { return GetBasePlayer()->SelectWeightedSequence( activity ); }
virtual void RestartMainSequence();
virtual void GetOuterAbsVelocity( Vector& vel );
float GetOuterXYSpeed();
virtual bool HandleJumping( Activity &idealActivity );
virtual bool HandleDucking( Activity &idealActivity );
virtual bool HandleMoving( Activity &idealActivity );
virtual bool HandleSwimming( Activity &idealActivity );
virtual bool HandleDying( Activity &idealActivity );
// Gesture Slots
CUtlVector<GestureSlot_t> m_aGestureSlots;
bool InitGestureSlots( void );
void ShutdownGestureSlots( void );
bool IsGestureSlotPlaying( int iGestureSlot, Activity iGestureActivity );
void AddToGestureSlot( int iGestureSlot, Activity iGestureActivity, bool bAutoKill );
virtual void RestartGesture( int iGestureSlot, Activity iGestureActivity, bool bAutoKill = true );
void ComputeGestureSequence( CStudioHdr *pStudioHdr );
void UpdateGestureLayer( CStudioHdr *pStudioHdr, GestureSlot_t *pGesture );
void DebugGestureInfo( void );
virtual float GetGesturePlaybackRate( void ) { return 1.0f; }
#ifdef CLIENT_DLL
void RunGestureSlotAnimEventsToCompletion( GestureSlot_t *pGesture );
#endif
virtual void PlayFlinchGesture( Activity iActivity );
virtual float CalcMovementSpeed( bool *bIsMoving );
virtual float CalcMovementPlaybackRate( bool *bIsMoving );
void DoMovementTest( CStudioHdr *pStudioHdr, float flX, float flY );
void DoMovementTest( CStudioHdr *pStudioHdr );
void GetMovementFlags( CStudioHdr *pStudioHdr );
// Pose parameters.
bool SetupPoseParameters( CStudioHdr *pStudioHdr );
virtual void ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr );
virtual void ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr );
virtual void ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr );
void ComputePoseParam_BodyHeight( CStudioHdr *pStudioHdr );
virtual void EstimateYaw( void );
void ConvergeYawAngles( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw );
virtual float GetCurrentMaxGroundSpeed();
virtual void ComputeSequences( CStudioHdr *pStudioHdr );
void ComputeMainSequence();
void UpdateInterpolators();
void ResetGroundSpeed( void );
float GetInterpolatedGroundSpeed( void );
void ComputeFireSequence();
void ComputeDeployedSequence();
virtual bool ShouldUpdateAnimState();
void DebugShowAnimStateForPlayer( bool bIsServer );
void DebugShowEyeYaw( void );
// Client specific.
#ifdef CLIENT_DLL
// Debug.
void DebugShowActivity( Activity activity );
#endif
protected:
CBasePlayer *m_pPlayer;
QAngle m_angRender;
// Pose parameters.
bool m_bPoseParameterInit;
MultiPlayerPoseData_t m_PoseParameterData;
DebugPlayerAnimData_t m_DebugAnimData;
bool m_bCurrentFeetYawInitialized;
float m_flLastAnimationStateClearTime;
float m_flEyeYaw;
float m_flEyePitch;
float m_flGoalFeetYaw;
float m_flCurrentFeetYaw;
float m_flLastAimTurnTime;
MultiPlayerMovementData_t m_MovementData;
// Jumping.
bool m_bJumping;
float m_flJumpStartTime;
bool m_bFirstJumpFrame;
// Swimming.
bool m_bInSwim;
bool m_bFirstSwimFrame;
// Dying
bool m_bDying;
bool m_bFirstDyingFrame;
// Last activity we've used on the lower body. Used to determine if animations should restart.
Activity m_eCurrentMainSequenceActivity;
// Specific full-body sequence to play
int m_nSpecificMainSequence;
// Weapon data.
CHandle<CBaseCombatWeapon> m_hActiveWeapon;
// Ground speed interpolators.
#ifdef CLIENT_DLL
float m_flLastGroundSpeedUpdateTime;
CInterpolatedVar<float> m_iv_flMaxGroundSpeed;
#endif
float m_flMaxGroundSpeed;
// movement playback options
int m_nMovementSequence;
LegAnimType_t m_LegAnimType;
};
// If this is set, then the game code needs to make sure to send player animation events
// to the local player if he's the one being watched.
extern ConVar cl_showanimstate;
#endif // DOD_PLAYERANIMSTATE_H
+5 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
@@ -9,6 +9,10 @@
#include "choreoscene.h"
#include "choreoevent.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
extern ISoundEmitterSystemBase *soundemitterbase;
CChoreoScene *BlockingLoadScene( const char *filename );
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
+8 -7
View File
@@ -1,20 +1,20 @@
// SharedFunctorUtils.cpp
// Useful functors
//========= Copyright Valve Corporation, All rights reserved. ============//
// Copyright 2006 Turtle Rock Studios, Inc.
#include "cbase.h"
#include "SharedFunctorUtils.h"
#include "collisionutils.h"
#ifdef CLIENT_DLL
#include "ClientTerrorPlayer.h"
#else
#include "TerrorPlayer.h"
#endif
// #ifdef CLIENT_DLL
// #include "ClientTerrorPlayer.h"
// #else
// #include "TerrorPlayer.h"
// #endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if 0
//--------------------------------------------------------------------------------------------------------
bool AvoidActors::operator()( CBaseCombatCharacter *obj )
{
@@ -81,3 +81,4 @@ bool AvoidActors::operator()( CBaseCombatCharacter *obj )
//--------------------------------------------------------------------------------------------------------
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
// SharedFunctorUtils.h
// Useful functors for client and server
//========= Copyright Valve Corporation, All rights reserved. ============//
// Author: Graham Smallwood, August 2006, Copyright 2006 Turtle Rock Studios, Inc.
//--------------------------------------------------------------------------------------------------------
/**
File diff suppressed because it is too large Load Diff
+57 -61
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc.
//
@@ -15,9 +15,7 @@
#include "enginesprite.h"
#include "iclientmode.h"
#include "c_baseviewmodel.h"
# ifdef PORTAL
#include "c_prop_portal.h"
# endif //ifdef PORTAL
#else
#include "baseviewmodel.h"
#endif
@@ -49,10 +47,7 @@ BEGIN_DATADESC( CSprite )
DEFINE_KEYFIELD( m_flSpriteScale, FIELD_FLOAT, "scale" ),
DEFINE_KEYFIELD( m_flSpriteFramerate, FIELD_FLOAT, "framerate" ),
DEFINE_KEYFIELD( m_flFrame, FIELD_FLOAT, "frame" ),
#ifdef PORTAL
DEFINE_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN ),
#endif
DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ),
DEFINE_KEYFIELD( m_flGlowProxySize, FIELD_FLOAT, "GlowProxySize" ),
@@ -94,10 +89,7 @@ BEGIN_PREDICTION_DATA( CSprite )
DEFINE_PRED_FIELD( m_flSpriteScale, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flSpriteFramerate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
#ifdef PORTAL
DEFINE_PRED_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
#endif
DEFINE_PRED_FIELD( m_flBrightnessTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_nBrightness, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
@@ -145,10 +137,7 @@ BEGIN_NETWORK_TABLE( CSprite, DT_Sprite )
SendPropFloat( SENDINFO(m_flSpriteFramerate ), 8, SPROP_ROUNDUP, 0, 60.0f),
SendPropFloat( SENDINFO(m_flFrame), 20, SPROP_ROUNDDOWN, 0.0f, 256.0f),
#ifdef PORTAL
SendPropBool( SENDINFO(m_bDrawInMainRender) ),
SendPropBool( SENDINFO(m_bDrawInPortalRender) ),
#endif //#ifdef PORTAL
SendPropFloat( SENDINFO(m_flBrightnessTime ), 0, SPROP_NOSCALE ),
SendPropInt( SENDINFO(m_nBrightness), 8, SPROP_UNSIGNED ),
SendPropBool( SENDINFO(m_bWorldSpaceScale) ),
@@ -163,10 +152,7 @@ BEGIN_NETWORK_TABLE( CSprite, DT_Sprite )
RecvPropFloat( RECVINFO(m_flHDRColorScale )),
RecvPropFloat(RECVINFO(m_flFrame)),
#ifdef PORTAL
RecvPropBool( RECVINFO(m_bDrawInMainRender) ),
RecvPropBool( RECVINFO(m_bDrawInPortalRender) ),
#endif //#ifdef PORTAL
RecvPropFloat(RECVINFO(m_flBrightnessTime)),
RecvPropInt(RECVINFO(m_nBrightness)),
RecvPropBool( RECVINFO(m_bWorldSpaceScale) ),
@@ -174,15 +160,12 @@ BEGIN_NETWORK_TABLE( CSprite, DT_Sprite )
END_NETWORK_TABLE()
CSprite::CSprite() : BaseClass()
CSprite::CSprite()
{
m_flGlowProxySize = 2.0f;
m_flHDRColorScale = 1.0f;
#ifdef PORTAL
m_bDrawInMainRender = true;
m_bDrawInPortalRender = true;
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
@@ -200,11 +183,14 @@ void CSprite::Spawn( void )
m_flMaxFrame = (float)modelinfo->GetModelFrameCount( GetModel() ) - 1;
AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW );
#if defined( CLIENT_DLL )
SetNextClientThink( CLIENT_THINK_ALWAYS );
#endif
#if !defined( CLIENT_DLL )
if ( m_flGlowProxySize > MAX_GLOW_PROXY_SIZE )
{
// Clamp on Spawn to prevent per-frame spew
DevWarning( "env_sprite at setpos %0.0f %0.0f %0.0f has invalid glow size %f - clamping to %f\n",
GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, m_flGlowProxySize.Get(), MAX_GLOW_PROXY_SIZE );
m_flGlowProxySize = MAX_GLOW_PROXY_SIZE;
}
if ( GetEntityName() != NULL_STRING && !(m_spawnflags & SF_SPRITE_STARTON) )
{
TurnOff();
@@ -232,13 +218,13 @@ void CSprite::Spawn( void )
if ( scale < 0 || scale > MAX_SPRITE_SCALE )
{
#if !defined( CLIENT_DLL )
DevMsg( "LEVEL DESIGN ERROR: Sprite %s with bad scale %f [0..%f]\n", GetDebugName(), m_flSpriteScale.Get(), MAX_SPRITE_SCALE );
DevMsg( "LEVEL DESIGN ERROR: Sprite %s with bad scale %f [0..%f]\n", GetDebugName(), m_flSpriteScale, MAX_SPRITE_SCALE );
#endif
scale = clamp( (float) m_flSpriteScale, 0.f, MAX_SPRITE_SCALE );
scale = clamp( m_flSpriteScale, 0, MAX_SPRITE_SCALE );
}
//Set our state
SetBrightness( m_clrRender->a );
SetBrightness( GetRenderAlpha() );
SetScale( scale );
#if defined( CLIENT_DLL )
@@ -346,7 +332,7 @@ int CSprite::ShouldTransmit( const CCheckTransmitInfo *pInfo )
if ( GetMoveParent() )
{
CBaseViewModel *pViewModel = dynamic_cast<CBaseViewModel *>( GetMoveParent() );
CBaseViewModel *pViewModel = ToBaseViewModel( GetMoveParent() );
if ( pViewModel )
{
@@ -472,14 +458,14 @@ void CSprite::ExpandThink( void )
SetSpriteScale( m_flSpriteScale + m_flSpeed * frametime );
int sub = (int)(m_iHealth * frametime);
if ( sub > m_clrRender->a )
if ( sub > GetRenderAlpha() )
{
SetRenderColorA( 0 );
SetRenderAlpha( 0 );
Remove( );
}
else
{
SetRenderColorA( m_clrRender->a - sub );
SetRenderAlpha( GetRenderAlpha() - sub );
SetNextThink( gpGlobals->curtime );
m_flLastTime = gpGlobals->curtime;
}
@@ -603,19 +589,19 @@ void CSprite::InputShowSprite( inputdata_t &inputdata )
void CSprite::InputColorRedValue( inputdata_t &inputdata )
{
int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 );
int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
SetColor( nNewColor, m_clrRender->g, m_clrRender->b );
}
void CSprite::InputColorGreenValue( inputdata_t &inputdata )
{
int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 );
int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
SetColor( m_clrRender->r, nNewColor, m_clrRender->b );
}
void CSprite::InputColorBlueValue( inputdata_t &inputdata )
{
int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 );
int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
SetColor( m_clrRender->r, m_clrRender->g, nNewColor );
}
@@ -707,9 +693,6 @@ int CSprite::GetRenderBrightness( void )
void CSprite::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// Only think when sapping
SetNextClientThink( CLIENT_THINK_ALWAYS );
if ( updateType == DATA_UPDATE_CREATED )
{
m_flStartScale = m_flDestScale = m_flSpriteScale;
@@ -717,18 +700,27 @@ void CSprite::OnDataChanged( DataUpdateType_t updateType )
}
UpdateVisibility();
if ( m_flSpriteScale != m_flDestScale || m_nBrightness != m_nDestBrightness )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
else
{
SetNextClientThink( CLIENT_THINK_NEVER );
}
}
void CSprite::ClientThink( void )
{
BaseClass::ClientThink();
bool bDisableThink = true;
// Module render colors over time
if ( m_flSpriteScale != m_flDestScale )
{
m_flStartScale = m_flDestScale;
m_flDestScale = m_flSpriteScale;
m_flScaleTimeStart = gpGlobals->curtime;
bDisableThink = false;
}
if ( m_nBrightness != m_nDestBrightness )
@@ -736,6 +728,12 @@ void CSprite::ClientThink( void )
m_nStartBrightness = m_nDestBrightness;
m_nDestBrightness = m_nBrightness;
m_flBrightnessTimeStart = gpGlobals->curtime;
bDisableThink = false;
}
if ( bDisableThink )
{
SetNextClientThink(CLIENT_THINK_NEVER);
}
}
@@ -747,26 +745,20 @@ extern ConVar r_drawviewmodel;
// Input : flags -
// Output : int
//-----------------------------------------------------------------------------
int CSprite::DrawModel( int flags )
int CSprite::DrawModel( int flags, const RenderableInstance_t &instance )
{
VPROF_BUDGET( "CSprite::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
//See if we should draw
if ( !IsVisible() || ( m_bReadyToDraw == false ) )
return 0;
#ifdef PORTAL
if ( ( !g_pPortalRender->IsRenderingPortal() && !m_bDrawInMainRender ) ||
( g_pPortalRender->IsRenderingPortal() && !m_bDrawInPortalRender ) )
{
return 0;
}
#endif //#ifdef PORTAL
// Tracker 16432: If rendering a savegame screenshot then don't draw sprites
// who have viewmodels as their moveparent
if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() )
{
C_BaseViewModel *vm = dynamic_cast< C_BaseViewModel * >( GetMoveParent() );
C_BaseViewModel *vm = ToBaseViewModel( GetMoveParent() );
if ( vm )
{
return 0;
@@ -776,7 +768,11 @@ int CSprite::DrawModel( int flags )
//Must be a sprite
if ( modelinfo->GetModelType( GetModel() ) != mod_sprite )
{
Assert( 0 );
const char *modelName = modelinfo->GetModelName( GetModel() );
char msg[256];
V_snprintf( msg, 256, "Sprite %d has non-mod_sprite model %s (type %d)\n",
entindex(), modelName, modelinfo->GetModelType( GetModel() ) );
AssertMsgOnce( 0, msg );
return 0;
}
@@ -798,11 +794,11 @@ int CSprite::DrawModel( int flags )
m_hAttachedToEntity, // attach to
m_nAttachment, // attachment point
GetRenderMode(), // rendermode
m_nRenderFX,
GetRenderBrightness(), // alpha
m_clrRender->r,
m_clrRender->g,
m_clrRender->b,
GetRenderFX(),
(float)( GetRenderBrightness() * instance.m_nAlpha ) * ( 1.0f / 255.0f ) + 0.5f, // alpha
GetRenderColorR(),
GetRenderColorG(),
GetRenderColorB(),
renderscale, // sprite scale
GetHDRColorScale() // HDR Color Scale
);
@@ -860,9 +856,9 @@ void CSpriteOriented::Spawn( void )
#else
bool CSpriteOriented::IsTransparent( void )
RenderableTranslucencyType_t CSpriteOriented::ComputeTranslucencyType()
{
return true;
return RENDERABLE_IS_TRANSLUCENT;
}
#endif
+13 -17
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -93,6 +93,13 @@ public:
CSprite();
virtual void SetModel( const char *szModelName );
#if defined( CLIENT_DLL )
virtual bool IsSprite( void ) const
{
return true;
};
#endif
void Spawn( void );
void Precache( void );
virtual void ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
@@ -159,10 +166,10 @@ public:
SetRenderMode( (RenderMode_t)rendermode );
SetColor( r, g, b );
SetBrightness( a );
m_nRenderFX = fx;
SetRenderFX( (RenderFx_t)fx );
}
inline void SetTexture( int spriteIndex ) { SetModelIndex( spriteIndex ); }
inline void SetColor( int r, int g, int b ) { SetRenderColor( r, g, b, GetRenderColor().a ); }
inline void SetColor( int r, int g, int b ) { SetRenderColor( r, g, b ); }
void SetBrightness( int brightness, float duration = 0.0f );
void SetScale( float scale, float duration = 0.0f );
@@ -222,20 +229,12 @@ public:
virtual float GetRenderScale( void );
virtual int GetRenderBrightness( void );
virtual int DrawModel( int flags );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual const Vector& GetRenderOrigin();
virtual void GetRenderBounds( Vector &vecMins, Vector &vecMaxs );
virtual float GlowBlend( CEngineSprite *psprite, const Vector& entorigin, int rendermode, int renderfx, int alpha, float *scale );
virtual void GetToolRecordingState( KeyValues *msg );
// Only supported in TF2 right now
#if defined( INVASION_CLIENT_DLL )
virtual bool ShouldPredict( void )
{
return true;
}
#endif
virtual void ClientThink( void );
virtual void OnDataChanged( DataUpdateType_t updateType );
@@ -245,10 +244,7 @@ public:
CNetworkVar( int, m_nAttachment );
CNetworkVar( float, m_flSpriteFramerate );
CNetworkVar( float, m_flFrame );
#ifdef PORTAL
CNetworkVar( bool, m_bDrawInMainRender );
CNetworkVar( bool, m_bDrawInPortalRender );
#endif
float m_flDieTime;
@@ -284,7 +280,7 @@ public:
void Spawn( void );
#else
DECLARE_CLIENTCLASS();
virtual bool IsTransparent( void );
virtual RenderableTranslucencyType_t ComputeTranslucencyType();
#endif
};
+9 -84
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -10,9 +10,9 @@
#ifdef CLIENT_DLL
#include "clientsideeffects.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imesh.h"
#include "mathlib/vmatrix.h"
#include "materialsystem/IMaterialSystem.h"
#include "materialsystem/IMesh.h"
#include "mathlib/VMatrix.h"
#include "view.h"
#include "beamdraw.h"
#include "enginesprite.h"
@@ -37,6 +37,7 @@ extern CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int fr
#if defined( CLIENT_DLL )
BEGIN_SIMPLE_DATADESC( TrailPoint_t )
// DEFINE_FIELD( m_vecScreenPos, FIELD_CLASSCHECK_IGNORE ) // do this or else we get a warning about multiply-defined fields
#if SCREEN_SPACE_TRAILS
DEFINE_FIELD( m_vecScreenPos, FIELD_VECTOR ),
#else
@@ -127,7 +128,6 @@ CSpriteTrail::CSpriteTrail( void )
m_vecSkyboxOrigin.Init( 0, 0, 0 );
m_flSkyboxScale = 1.0f;
m_flEndWidth = -1.0f;
m_bDrawForMoveParent = true;
}
void CSpriteTrail::Spawn( void )
@@ -242,7 +242,6 @@ bool CSpriteTrail::IsInSkybox() const
}
#ifdef CLIENT_DLL
@@ -419,7 +418,7 @@ void CSpriteTrail::UpdateTrail( void )
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CSpriteTrail::DrawModel( int flags )
int CSpriteTrail::DrawModel( int flags, const RenderableInstance_t &instance )
{
VPROF_BUDGET( "CSpriteTrail::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
@@ -464,10 +463,9 @@ int CSpriteTrail::DrawModel( int flags )
float flLifePerc = (pPoint->m_flDieTime - gpGlobals->curtime) / m_flLifeTime;
flLifePerc = clamp( flLifePerc, 0.0f, 1.0f );
color24 c = GetRenderColor();
BeamSeg_t curSeg;
curSeg.m_vColor.x = (float) m_clrRender->r / 255.0f;
curSeg.m_vColor.y = (float) m_clrRender->g / 255.0f;
curSeg.m_vColor.z = (float) m_clrRender->b / 255.0f;
curSeg.m_color.r = c.r; curSeg.m_color.g = c.g; curSeg.m_color.b = c.b;
float flAlphaFade = flLifePerc;
if ( flTailAlphaDist > 0.0f )
@@ -487,7 +485,7 @@ int CSpriteTrail::DrawModel( int flags )
}
}
}
curSeg.m_flAlpha = ( (float) GetRenderBrightness() / 255.0f ) * flAlphaFade;
curSeg.m_color.a = GetRenderBrightness() * flAlphaFade;
#if SCREEN_SPACE_TRAILS
curSeg.m_vPos = viewMatrix * pPoint->m_vecScreenPos;
@@ -586,77 +584,4 @@ CSpriteTrail *CSpriteTrail::SpriteTrailCreate( const char *pSpriteName, const Ve
return pSprite;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CSpriteTrail::ShouldTransmit( const CCheckTransmitInfo *pInfo )
{
CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt );
Assert( pRecipientEntity->IsPlayer() );
CBasePlayer *pRecipientPlayer = static_cast<CBasePlayer*>( pRecipientEntity );
if ( !m_bDrawForMoveParent )
{
if ( GetMoveParent() && !GetMoveParent()->IsPlayer() )
{
if ( GetMoveParent()->GetMoveParent() == pRecipientPlayer )
{
return FL_EDICT_DONTSEND;
}
}
else if ( GetMoveParent() == pRecipientPlayer )
{
return FL_EDICT_DONTSEND;
}
}
return BaseClass::ShouldTransmit( pInfo );
}
#endif //CLIENT_DLL == false
#if defined( CLIENT_DLL )
// It's okay to draw attached entities with these sprites.
const char* g_spriteWhiteList[] =
{
"effects/beam001_white.vmt",
"effects/beam001_red.vmt",
"effects/beam001_blu.vmt",
};
//-----------------------------------------------------------------------------
// Purpose: TF prevents drawing of any entity attached to players that aren't items in the inventory of the player.
// This is to prevent servers creating fake cosmetic items and attaching them to players.
//-----------------------------------------------------------------------------
bool CSpriteTrail::ValidateEntityAttachedToPlayer( bool &bShouldRetry )
{
bShouldRetry = false;
return true;
/*
#if defined( TF_CLIENT_DLL )
const char *pszModelName = modelinfo->GetModelName( GetModel() );
if ( pszModelName && pszModelName[0] )
{
// We attach sprites directly to players in some cases, such as phase trails on an evading scout
for ( int i=0; i<ARRAYSIZE( g_spriteWhiteList ); ++i )
{
if ( FStrEq( pszModelName, g_spriteWhiteList[i] ) )
return true;
}
}
return false;
#else
return false;
#endif
*/
}
#endif
+2 -10
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -53,11 +53,10 @@ public:
bool IsInSkybox() const;
void Spawn( void );
void Precache( void );
void SetTransmit( bool bTransmit = true ) { m_bDrawForMoveParent = bTransmit; }
#if defined( CLIENT_DLL )
// Client only code
virtual int DrawModel( int flags );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual const Vector &GetRenderOrigin( void );
virtual const QAngle &GetRenderAngles( void );
@@ -66,15 +65,9 @@ public:
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void GetRenderBounds( Vector& mins, Vector& maxs );
virtual void ClientThink();
virtual bool ValidateEntityAttachedToPlayer( bool &bShouldRetry );
#else
// Server only code
virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo );
static CSpriteTrail *SpriteTrailCreate( const char *pSpriteName, const Vector &origin, bool animate );
#endif
private:
@@ -113,7 +106,6 @@ private:
string_t m_iszSpriteName;
bool m_bAnimate;
bool m_bDrawForMoveParent;
};
#endif // SPRITETRAIL_H
+9 -6
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -41,7 +41,7 @@ public:
// save global achievement mgr state to separate file if there have been any changes, so in case of a crash
// the global state is consistent with last save game
pAchievementMgr->SaveGlobalStateIfDirty( pSave->IsAsync() );
pAchievementMgr->SaveGlobalStateIfDirty();
pSave->StartBlock( "Achievements" );
int iTotalAchievements = pAchievementMgr->GetAchievementCount();
@@ -49,7 +49,8 @@ public:
// count how many achievements should be saved.
for ( int i = 0; i < iTotalAchievements; i++ )
{
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i );
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i, SINGLE_PLAYER_SLOT );
if ( pAchievement->ShouldSaveWithGame() )
{
nSaveCount++;
@@ -60,7 +61,8 @@ public:
// Write out each achievement
for ( int i = 0; i < iTotalAchievements; i++ )
{
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i );
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i, SINGLE_PLAYER_SLOT );
if ( pAchievement->ShouldSaveWithGame() )
{
CBaseAchievement *pBaseAchievement = dynamic_cast< CBaseAchievement * >( pAchievement );
@@ -118,7 +120,8 @@ public:
// read achievement ID
int iAchievementID = pRestore->ReadShort();
// find the corresponding achievement object
CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievementID );
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievementID, SINGLE_PLAYER_SLOT );
Assert( pAchievement ); // It's a bug if we don't understand this achievement
if ( pAchievement )
{
@@ -154,4 +157,4 @@ ISaveRestoreBlockHandler *GetAchievementSaveRestoreBlockHandler()
}
#endif // GAME_DLL
#endif // GAME_DLL
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
File diff suppressed because it is too large Load Diff
+69 -109
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
@@ -9,158 +9,120 @@
#ifdef _WIN32
#pragma once
#endif
#include "matchmaking/imatchframework.h"
#include "baseachievement.h"
#include "GameEventListener.h"
#include "hl2orange.spa.h"
#include "iachievementmgr.h"
#include "utlmap.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
#define THINK_CLEAR -1
typedef void* AsyncHandle_t;
class CAchievementMgr : public CAutoGameSystemPerFrame, public CGameEventListener, public IAchievementMgr
class CAchievementMgr : public CAutoGameSystemPerFrame, public CGameEventListener, public IMatchEventsSink, public IAchievementMgr
{
public:
//=============================================================================
// HPE_BEGIN
// [dwenger] Steam Cloud Support
//=============================================================================
enum SteamCloudPersisting
{
SteamCloudPersist_Off = 0,
SteamCloudPersist_On,
};
CAchievementMgr( SteamCloudPersisting ePersistToSteamCloud = SteamCloudPersist_Off );
//=============================================================================
// HPE_END
//=============================================================================
CAchievementMgr();
virtual bool Init();
virtual void PostInit();
virtual void Shutdown();
virtual void LevelInitPreEntity();
virtual void LevelShutdownPreEntity();
virtual void InitializeAchievements();
virtual void InitializeAchievements( );
virtual void Update( float frametime );
#ifdef GAME_DLL
virtual void FrameUpdatePostEntityThink();
#endif
virtual bool IsPerFrame( void ) { return true; }
void OnMapEvent( const char *pchEventName, int nUserSlot );
void OnMapEvent( const char *pchEventName );
// Interfaces exported to other dlls for achievement list queries
IAchievement* GetAchievementByIndex( int index );
IAchievement* GetAchievementByIndex( int index, int nUserSlot );
IAchievement* GetAchievementByDisplayOrder( int orderIndex, int nUserSlot );
int GetAchievementCount();
CBaseAchievement *GetAchievementByID( int iAchievementID );
CUtlMap<int, CBaseAchievement *> &GetAchievements() { return m_mapAchievement; }
CBaseAchievement *GetAchievementByID( int iAchievementID, int nUserSlot );
CUtlMap<int, CBaseAchievement *> &GetAchievements( int nUserSlot ) { return m_mapAchievement[nUserSlot]; }
CBaseAchievement *GetAchievementByName( const char *pchName );
bool HasAchieved( const char *pchName );
CBaseAchievement *GetAchievementByName( const char *pchName, int nUserSlot );
void UploadUserData();
void DownloadUserData();
void SaveGlobalState( bool bAsync = false );
void LoadGlobalState();
void SaveGlobalStateIfDirty( bool bAsync = false );
void EnsureGlobalStateLoaded();
void AwardAchievement( int iAchievementID );
void UpdateAchievement( int iAchievementID, int nData );
void UploadUserData( int nUserSlot );
void UserConnected( int nUserSlot );
void UserDisconnected( int nUserSlot );
bool IsUserConnected( int nUserSlot ) { return m_bUserSlotActive[nUserSlot]; }
void ReadAchievementsFromTitleData( int iController, int iSlot );
void SaveGlobalState();
void SaveGlobalStateIfDirty();
bool HasAchieved( const char *pchName, int nUserSlot );
void AwardAchievement( int iAchievementID, int nUserSlot );
void UpdateAchievement( int iAchievementID, int nData, int nUserSlot );
void PreRestoreSavedGame();
void PostRestoreSavedGame();
void ResetAchievements();
void ResetAchievement( int iAchievementID );
void PrintAchievementStatus();
float GetLastClassChangeTime() { return m_flLastClassChangeTime; }
float GetTeamplayStartTime() { return m_flTeamplayStartTime; }
int GetMiniroundsCompleted() { return m_iMiniroundsCompleted; }
float GetLastClassChangeTime( int nUserSlot ) { return m_flLastClassChangeTime[nUserSlot]; }
float GetTeamplayStartTime( int nUserSlot ) { return m_flTeamplayStartTime[nUserSlot]; }
int GetMiniroundsCompleted( int nUserSlot ) { return m_iMiniroundsCompleted[nUserSlot]; }
const char *GetMapName() { return m_szMap; }
void OnAchievementEvent( int iAchievementID, int iCount = 1 );
void CheckMetaAchievements( void );
void SetDirty( bool bDirty )
{
if (bDirty)
{
m_bGlobalStateDirty = true;
m_bSteamDataDirty = true;
}
}
//=============================================================================
// HPE_END
//=============================================================================
void OnAchievementEvent( int iAchievementID, int nUserSlot );
void SetDirty( bool bDirty, int nUserSlot ) { m_bDirty[nUserSlot] = bDirty; }
bool CheckAchievementsEnabled();
bool LoggedIntoSteam()
{
#if !defined(NO_STEAM)
return ( steamapicontext->SteamUser() && steamapicontext->SteamUserStats() && steamapicontext->SteamUser()->BLoggedOn() );
#else
return false;
#endif
}
float GetTimeLastUpload() { return m_flTimeLastSaved; } // time we last uploaded to Steam
// IMatchEventsSink
virtual void OnEvent( KeyValues *pEvent );
#ifdef CLIENT_DLL
bool LoggedIntoSteam() { return ( steamapicontext->SteamUser() && steamapicontext->SteamUserStats() && steamapicontext->SteamUser()->BLoggedOn() ); }
#else
bool LoggedIntoSteam() { return false; }
#endif
float GetTimeLastUpload() { return m_flTimeLastUpload; } // time we last uploaded to Steam
bool WereCheatsEverOn( void ) { return m_bCheatsEverOn; }
#if !defined(NO_STEAM)
STEAM_CALLBACK( CAchievementMgr, Steam_OnUserStatsReceived, UserStatsReceived_t, m_CallbackUserStatsReceived );
STEAM_CALLBACK( CAchievementMgr, Steam_OnUserStatsStored, UserStatsStored_t, m_CallbackUserStatsStored );
#endif
void SetAchievementThink( CBaseAchievement *pAchievement, float flThinkTime );
const CUtlVector<int>& GetAchievedDuringCurrentGame( int nPlayerSlot );
void ResetAchievedDuringCurrentGame( int nPlayerSlot );
virtual void FireGameEvent( IGameEvent *event );
private:
void FireGameEvent( IGameEvent *event );
void OnKillEvent( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event );
void ResetAchievement_Internal( CBaseAchievement *pAchievement );
void UpdateStateFromSteam_Internal();
CUtlMap<int, CBaseAchievement *> m_mapAchievement; // map of all achievements
CUtlVector<CBaseAchievement *> m_vecAchievement; // vector of all achievements for accessing by index
CUtlVector<CBaseAchievement *> m_vecKillEventListeners; // vector of achievements that are listening for kill events
CUtlVector<CBaseAchievement *> m_vecMapEventListeners; // vector of achievements that are listening for map events
CUtlVector<CBaseAchievement *> m_vecComponentListeners; // vector of achievements that are listening for components that make up an achievement
CUtlMap<int, CAchievement_AchievedCount *> m_mapMetaAchievement; // map of CAchievement_AchievedCount
CUtlMap<int, CBaseAchievement *> m_mapAchievement[MAX_SPLITSCREEN_PLAYERS]; // map of all achievements
CUtlVector<CBaseAchievement *> m_vecAchievement[MAX_SPLITSCREEN_PLAYERS]; // vector of all achievements for accessing by index
CUtlVector<CBaseAchievement *> m_vecKillEventListeners[MAX_SPLITSCREEN_PLAYERS]; // vector of achievements that are listening for kill events
CUtlVector<CBaseAchievement *> m_vecMapEventListeners[MAX_SPLITSCREEN_PLAYERS]; // vector of achievements that are listening for map events
CUtlVector<CBaseAchievement *> m_vecComponentListeners[MAX_SPLITSCREEN_PLAYERS]; // vector of achievements that are listening for components that make up an achievement
CUtlVector<CBaseAchievement *> m_vecAchievementInOrder[MAX_SPLITSCREEN_PLAYERS]; // vector of all achievements for accessing by display order
struct achievementthink_t
{
float m_flThinkTime;
CBaseAchievement *pAchievement;
};
CUtlVector<achievementthink_t> m_vecThinkListeners; // vector of achievements that are actively thinking
float m_flLevelInitTime;
float m_flLastClassChangeTime; // Time when player last changed class
float m_flTeamplayStartTime; // Time when player joined a non-spectating team. Not updated if she switches game teams; cleared if she joins spectator
float m_iMiniroundsCompleted; // # of minirounds played since game start (for maps that have minirounds)
char m_szMap[MAX_PATH]; // file base of map name, cached since we access it frequently in this form
bool m_bGlobalStateDirty; // do we have interesting state changes that needs to be saved?
bool m_bSteamDataDirty; // do we have changes to upload to Steamworks?
bool m_bGlobalStateLoaded; // have we loaded global state
float m_flLevelInitTime[MAX_SPLITSCREEN_PLAYERS];
float m_flLastClassChangeTime[MAX_SPLITSCREEN_PLAYERS]; // Time when player last changed class
float m_flTeamplayStartTime[MAX_SPLITSCREEN_PLAYERS]; // Time when player joined a non-spectating team. Not updated if she switches game teams; cleared if she joins spectator
float m_iMiniroundsCompleted[MAX_SPLITSCREEN_PLAYERS]; // # of minirounds played since game start (for maps that have minirounds)
char m_szMap[MAX_PATH]; // file base of map name, cached since we access it frequently in this form
bool m_bDirty[MAX_SPLITSCREEN_PLAYERS]; // do we have interesting state that needs to be saved
bool m_bUserSlotActive[MAX_SPLITSCREEN_PLAYERS];
bool m_bCheatsEverOn; // have cheats ever been turned on in this level
float m_flTimeLastSaved; // last time we uploaded to Steam
float m_flTimeLastUpload; // last time we uploaded to Steam
float m_flWaitingForStoreStatsCallback;
bool m_bCallStoreStatsAfterCallback;
//=============================================================================
// HPE_BEGIN
// [dwenger] Steam Cloud Support
//=============================================================================
#ifdef _X360
struct PendingAchievementInfo_t {
int nAchievementID; // Achievement we're waiting to check the status of
int nUserSlot; // Which user is being awarded the achievement
AsyncHandle_t pOverlappedResult; // Result we'll check again
};
bool m_bPersistToSteamCloud; // true = persist data to steam cloud
CUtlVector<PendingAchievementInfo_t> m_pendingAchievementState;
#endif
//=============================================================================
// HPE_END
//=============================================================================
CUtlVector<int> m_AchievementsAwarded;
CUtlVector<int> m_AchievementsAwarded[MAX_SPLITSCREEN_PLAYERS];
CUtlVector<int> m_AchievementsAwardedDuringCurrentGame[MAX_SPLITSCREEN_PLAYERS];
void ClearAchievementData( int nUserSlot );
};
// helper functions
@@ -173,9 +135,7 @@ int CalcPlayerCount();
int CalcTeammateCount();
#endif // CLIENT
class IMatchmaking;
extern ConVar cc_achievement_debug;
extern IMatchmaking *matchmaking;
#ifdef CLIENT_DLL
void MsgFunc_AchievementEvent( bf_read &msg );
@@ -1,50 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef ACHIEVEMENTSANDSTATSINTERFACE_H
#define ACHIEVEMENTSANDSTATSINTERFACE_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/Panel.h"
#include "vgui_controls/Panel.h"
#include "vgui_controls/PHandle.h"
#include "vgui_controls/MenuItem.h"
#include "vgui_controls/MessageDialog.h"
#include "vgui/ISurface.h"
class AchievementsAndStatsInterface
{
public:
AchievementsAndStatsInterface() { }
virtual void CreatePanel( vgui::Panel* pParent ) {}
virtual void DisplayPanel() {}
virtual void ReleasePanel() {}
virtual int GetAchievementsPanelMinWidth( void ) const { return 0; }
protected:
//-----------------------------------------------------------------------------
// Purpose: Positions a dialog on screen.
//-----------------------------------------------------------------------------
void PositionDialog(vgui::PHandle dlg)
{
if (!dlg.Get())
return;
int x, y, ww, wt, wide, tall;
vgui::surface()->GetWorkspaceBounds( x, y, ww, wt );
dlg->GetSize(wide, tall);
// Center it, keeping requested size
dlg->SetPos(x + ((ww - wide) / 2), y + ((wt - tall) / 2));
}
};
#endif // ACHIEVEMENTSANDSTATSINTERFACE_H
+9 -5
View File
@@ -1,17 +1,17 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#ifdef GAME_DLL
// this gets compiled in for HL2 + Ep(X) only
#if ( defined( HL2_DLL ) || defined( HL2_EPISODIC ) ) && ( !defined ( PORTAL ) )
#if ( defined( HL2_DLL ) || defined( HL2_EPISODIC ) ) && ( !defined ( INFESTED_DLL ) )
#include "matchmaking/imatchframework.h"
#include "baseachievement.h"
#include "prop_combine_ball.h"
#include "combine_mine.h"
@@ -19,6 +19,10 @@
#include "basehlcombatweapon_shared.h"
#include "ammodef.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
class CAchievementHLXKillWithPhysicsObjects : public CBaseAchievement
{
void Init()
@@ -248,6 +252,6 @@ int CalcPlayerAttacks( bool bBulletOnly )
return iTotalAttacks;
}
#endif // ( defined( HL2_DLL ) || defined( HL2_EPISODIC ) ) && ( !defined ( PORTAL ) )
#endif // ( defined( HL2_DLL ) || defined( HL2_EPISODIC ) )
#endif // GAME_DLL
#endif // GAME_DLL
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -44,7 +44,9 @@ class CActivityRemapCache
{
public:
CActivityRemapCache() = default;
CActivityRemapCache()
{
}
CActivityRemapCache( const CActivityRemapCache& src )
{
+72 -1065
View File
File diff suppressed because it is too large Load Diff
+38
View File
@@ -0,0 +1,38 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#include "cbase.h"
#include "ai_criteria.h"
#ifdef GAME_DLL
#include "ai_speech.h"
#endif
#include <keyvalues.h>
#include "engine/ienginesound.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
BEGIN_SIMPLE_DATADESC( AI_ResponseParams )
DEFINE_FIELD( flags, FIELD_SHORT ),
DEFINE_FIELD( odds, FIELD_SHORT ),
DEFINE_FIELD( soundlevel, FIELD_CHARACTER ),
DEFINE_FIELD( delay, FIELD_INTEGER ), // These are compressed down to two float16s, so treat as an INT for saverestore
DEFINE_FIELD( respeakdelay, FIELD_INTEGER ), //
END_DATADESC()
BEGIN_SIMPLE_DATADESC( AI_Response )
DEFINE_FIELD( m_Type, FIELD_CHARACTER ),
DEFINE_ARRAY( m_szResponseName, FIELD_CHARACTER, AI_Response::MAX_RESPONSE_NAME ),
DEFINE_ARRAY( m_szMatchingRule, FIELD_CHARACTER, AI_Response::MAX_RULE_NAME ),
// DEFINE_FIELD( m_pCriteria, FIELD_??? ), // Don't need to save this probably
DEFINE_EMBEDDED( m_Params ),
END_DATADESC()
+41
View File
@@ -0,0 +1,41 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef AI_CRITERIA_H
#define AI_CRITERIA_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlrbtree.h"
#include "tier1/utlsymbol.h"
#include "tier2/interval.h"
#include "mathlib/compressed_vector.h"
#include "../../public/responserules/response_types.h"
using ResponseRules::ResponseType_t;
extern const char *SplitContext( const char *raw, char *key, int keylen, char *value, int valuelen, float *duration, const char *entireContext );
#ifndef AI_CriteriaSet
#define AI_CriteriaSet ResponseRules::CriteriaSet
#endif
typedef ResponseRules::ResponseParams AI_ResponseParams ;
typedef ResponseRules::CRR_Response AI_Response;
/*
// An AI response that is dynamically new'ed up and returned from SpeakFindResponse.
class AI_ResponseReturnValue : AI_Response
{
};
*/
#endif // AI_CRITERIA_H
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
+949
View File
@@ -0,0 +1,949 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "soundemittersystem/isoundemittersystembase.h"
#include "ai_responsesystem.h"
#include "igamesystem.h"
#include "ai_criteria.h"
#include <keyvalues.h>
#include "filesystem.h"
#include "utldict.h"
#ifdef GAME_DLL
#include "ai_speech.h"
#endif
#include "tier0/icommandline.h"
#include <ctype.h>
#include "isaverestore.h"
#include "utlbuffer.h"
#include "stringpool.h"
#include "fmtstr.h"
#include "multiplay_gamerules.h"
#include "characterset.h"
#include "responserules/response_host_interface.h"
#include "../../responserules/runtime/response_types_internal.h"
#include "scenefilecache/ISceneFileCache.h"
#ifdef GAME_DLL
#include "sceneentity.h"
#endif
#include "networkstringtabledefs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace ResponseRules;
extern ConVar rr_debugresponses; // ( "rr_debugresponses", "0", FCVAR_NONE, "Show verbose matching output (1 for simple, 2 for rule scoring, 3 for noisy). If set to 4, it will only show response success/failure for npc_selected NPCs." );
extern ConVar rr_debugrule; // ( "rr_debugrule", "", FCVAR_NONE, "If set to the name of the rule, that rule's score will be shown whenever a concept is passed into the response rules system.");
extern ConVar rr_dumpresponses; // ( "rr_dumpresponses", "0", FCVAR_NONE, "Dump all response_rules.txt and rules (requires restart)" );
extern ConVar rr_debugresponseconcept; // ( "rr_debugresponseconcept", "", FCVAR_NONE, "If set, rr_debugresponses will print only responses testing for the specified concept" );
extern ISceneFileCache *scenefilecache;
extern INetworkStringTable *g_pStringTableClientSideChoreoScenes;
static characterset_t g_BreakSetIncludingColons;
// Simple class to initialize breakset
class CBreakInit
{
public:
CBreakInit()
{
CharacterSetBuild( &g_BreakSetIncludingColons, "{}()':" );
}
} g_BreakInit;
inline char rr_tolower( char c )
{
if ( c >= 'A' && c <= 'Z' )
return c - 'A' + 'a';
return c;
}
// BUG BUG: Note that this function doesn't check for data overruns!!!
// Also, this function lowercases the token as it parses!!!
inline const char *RR_Parse(const char *data, char *token )
{
unsigned char c;
int len;
characterset_t *breaks = &g_BreakSetIncludingColons;
len = 0;
token[0] = 0;
if (!data)
return NULL;
// skip whitespace
skipwhite:
while ( (c = *data) <= ' ')
{
if (c == 0)
return NULL; // end of file;
data++;
}
// skip // comments
if (c=='/' && data[1] == '/')
{
while (*data && *data != '\n')
data++;
goto skipwhite;
}
// handle quoted strings specially
if (c == '\"')
{
data++;
while (1)
{
c = rr_tolower( *data++ );
if (c=='\"' || !c)
{
token[len] = 0;
return data;
}
token[len] = c;
len++;
}
}
// parse single characters
if ( IN_CHARACTERSET( *breaks, c ) )
{
token[len] = c;
len++;
token[len] = 0;
return data+1;
}
// parse a regular word
do
{
token[len] = rr_tolower( c );
data++;
len++;
c = rr_tolower( *data );
if ( IN_CHARACTERSET( *breaks, c ) )
break;
} while (c>32);
token[len] = 0;
return data;
}
namespace ResponseRules
{
extern const char *ResponseCopyString( const char *in );
}
// Host functions required by the ResponseRules::IEngineEmulator interface
class CResponseRulesToEngineInterface : public ResponseRules::IEngineEmulator
{
/// Given an input text buffer data pointer, parses a single token into the variable token and returns the new
/// reading position
virtual const char *ParseFile( const char *data, char *token, int maxlen )
{
NOTE_UNUSED( maxlen );
return RR_Parse( data, token );
}
/// Return a pointer to an IFileSystem we can use to read and process scripts.
virtual IFileSystem *GetFilesystem()
{
return filesystem;
}
/// Return a pointer to an instance of an IUniformRandomStream
virtual IUniformRandomStream *GetRandomStream()
{
return random;
}
/// Return a pointer to a tier0 ICommandLine
virtual ICommandLine *GetCommandLine()
{
return CommandLine();
}
/// Emulates the server's UTIL_LoadFileForMe
virtual byte *LoadFileForMe( const char *filename, int *pLength )
{
return UTIL_LoadFileForMe( filename, pLength );
}
/// Emulates the server's UTIL_FreeFile
virtual void FreeFile( byte *buffer )
{
return UTIL_FreeFile( buffer );
}
};
CResponseRulesToEngineInterface g_ResponseRulesEngineWrapper;
IEngineEmulator *IEngineEmulator::s_pSingleton = &g_ResponseRulesEngineWrapper;
BEGIN_SIMPLE_DATADESC( ParserResponse )
// DEFINE_FIELD( type, FIELD_INTEGER ),
// DEFINE_ARRAY( value, FIELD_CHARACTER ),
// DEFINE_FIELD( weight, FIELD_FLOAT ),
DEFINE_FIELD( depletioncount, FIELD_CHARACTER ),
// DEFINE_FIELD( first, FIELD_BOOLEAN ),
// DEFINE_FIELD( last, FIELD_BOOLEAN ),
END_DATADESC()
BEGIN_SIMPLE_DATADESC( ResponseGroup )
// DEFINE_FIELD( group, FIELD_UTLVECTOR ),
// DEFINE_FIELD( rp, FIELD_EMBEDDED ),
// DEFINE_FIELD( m_bDepleteBeforeRepeat, FIELD_BOOLEAN ),
DEFINE_FIELD( m_nDepletionCount, FIELD_CHARACTER ),
// DEFINE_FIELD( m_bHasFirst, FIELD_BOOLEAN ),
// DEFINE_FIELD( m_bHasLast, FIELD_BOOLEAN ),
// DEFINE_FIELD( m_bSequential, FIELD_BOOLEAN ),
// DEFINE_FIELD( m_bNoRepeat, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ),
DEFINE_FIELD( m_nCurrentIndex, FIELD_CHARACTER ),
END_DATADESC()
/// Add some game-specific code to the basic response system
/// (eg, the scene precacher, which requires the client and server
/// to work)
class CGameResponseSystem : public CResponseSystem
{
public:
CGameResponseSystem();
virtual void Precache();
virtual void PrecacheResponses( bool bEnable )
{
m_bPrecache = bEnable;
}
bool ShouldPrecache() { return m_bPrecache; }
protected:
bool m_bPrecache;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CGameResponseSystem::CGameResponseSystem() : m_bPrecache(true)
{};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CScenePrecacheSystem : public CAutoGameSystem
{
public:
CScenePrecacheSystem() : CAutoGameSystem( "CScenePrecacheSystem" ), m_RepeatCounts( 0, 0, DefLessFunc( int ) )
{
}
// Level init, shutdown
virtual void LevelShutdownPreEntity()
{
m_RepeatCounts.Purge();
}
bool ShouldPrecache( char const *pszScene )
{
int hash = HashStringCaselessConventional( pszScene );
int slot = m_RepeatCounts.Find( hash );
if ( slot != m_RepeatCounts.InvalidIndex() )
{
m_RepeatCounts[ slot ]++;
return false;
}
m_RepeatCounts.Insert( hash, 0 );
return true;
}
private:
CUtlMap< int, int > m_RepeatCounts;
};
static CScenePrecacheSystem g_ScenePrecacheSystem;
//-----------------------------------------------------------------------------
// Purpose: Used for precaching instanced scenes
// Input : *pszScene -
//-----------------------------------------------------------------------------
void PrecacheInstancedScene( char const *pszScene )
{
static int nMakingReslists = -1;
if ( !g_ScenePrecacheSystem.ShouldPrecache( pszScene ) )
return;
if ( nMakingReslists == -1 )
{
nMakingReslists = CommandLine()->FindParm( "-makereslists" ) > 0 ? 1 : 0;
}
if ( nMakingReslists == 1 )
{
// Just stat the file to add to reslist
g_pFullFileSystem->Size( pszScene );
}
// verify existence, cache is pre-populated, should be there
SceneCachedData_t sceneData;
if ( !scenefilecache->GetSceneCachedData( pszScene, &sceneData ) )
{
// Scenes are sloppy and don't always exist.
// A scene that is not in the pre-built cache image, but on disk, is a true error.
if ( IsX360() && ( g_pFullFileSystem->GetDVDMode() != DVDMODE_STRICT ) && g_pFullFileSystem->FileExists( pszScene, "GAME" ) )
{
Warning( "PrecacheInstancedScene: Missing scene '%s' from scene image cache.\nRebuild scene image cache!\n", pszScene );
}
}
else
{
for ( int i = 0; i < sceneData.numSounds; ++i )
{
short stringId = scenefilecache->GetSceneCachedSound( sceneData.sceneId, i );
CBaseEntity::PrecacheScriptSound( scenefilecache->GetSceneString( stringId ) );
}
}
g_pStringTableClientSideChoreoScenes->AddString( CBaseEntity::IsServer(), pszScene );
}
static void TouchFile( char const *pchFileName )
{
IEngineEmulator::Get()->GetFilesystem()->Size( pchFileName );
}
void CGameResponseSystem::Precache()
{
bool bTouchFiles = CommandLine()->FindParm( "-makereslists" ) != 0;
// enumerate and mark all the scripts so we know they're referenced
for ( int i = 0; i < (int)m_Responses.Count(); i++ )
{
ResponseGroup &group = m_Responses[i];
for ( int j = 0; j < group.group.Count(); j++)
{
ParserResponse &response = group.group[j];
switch ( response.type )
{
default:
break;
case RESPONSE_SCENE:
{
// fixup $gender references
char file[_MAX_PATH];
Q_strncpy( file, response.value, sizeof(file) );
char *gender = strstr( file, "$gender" );
if ( gender )
{
// replace with male & female
const char *postGender = gender + strlen("$gender");
*gender = 0;
char genderFile[_MAX_PATH];
// male
Q_snprintf( genderFile, sizeof(genderFile), "%smale%s", file, postGender);
PrecacheInstancedScene( genderFile );
if ( bTouchFiles )
{
TouchFile( genderFile );
}
Q_snprintf( genderFile, sizeof(genderFile), "%sfemale%s", file, postGender);
PrecacheInstancedScene( genderFile );
if ( bTouchFiles )
{
TouchFile( genderFile );
}
}
else
{
PrecacheInstancedScene( file );
if ( bTouchFiles )
{
TouchFile( file );
}
}
}
break;
case RESPONSE_SPEAK:
{
CBaseEntity::PrecacheScriptSound( response.value );
}
break;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: A special purpose response system associated with a custom entity
//-----------------------------------------------------------------------------
class CInstancedResponseSystem : public CGameResponseSystem
{
typedef CGameResponseSystem BaseClass;
public:
CInstancedResponseSystem( const char *scriptfile ) :
m_pszScriptFile( 0 )
{
Assert( scriptfile );
int len = Q_strlen( scriptfile ) + 1;
m_pszScriptFile = new char[ len ];
Assert( m_pszScriptFile );
Q_strncpy( m_pszScriptFile, scriptfile, len );
}
~CInstancedResponseSystem()
{
delete[] m_pszScriptFile;
}
virtual const char *GetScriptFile( void )
{
Assert( m_pszScriptFile );
return m_pszScriptFile;
}
// CAutoGameSystem
virtual bool Init()
{
const char *basescript = GetScriptFile();
LoadRuleSet( basescript );
return true;
}
virtual void LevelInitPostEntity()
{
ResetResponseGroups();
}
virtual void Release()
{
Clear();
delete this;
}
private:
char *m_pszScriptFile;
};
//-----------------------------------------------------------------------------
// Purpose: The default response system for expressive AIs
//-----------------------------------------------------------------------------
class CDefaultResponseSystem : public CGameResponseSystem, public CAutoGameSystem
{
typedef CAutoGameSystem BaseClass;
public:
CDefaultResponseSystem() : CAutoGameSystem( "CDefaultResponseSystem" )
{
}
virtual const char *GetScriptFile( void )
{
return "scripts/talker/response_rules.txt";
}
// CAutoServerSystem
virtual bool Init();
virtual void Shutdown();
virtual void LevelInitPostEntity()
{
}
virtual void Release()
{
Assert( 0 );
}
void AddInstancedResponseSystem( const char *scriptfile, CInstancedResponseSystem *sys )
{
m_InstancedSystems.Insert( scriptfile, sys );
}
CInstancedResponseSystem *FindResponseSystem( const char *scriptfile )
{
int idx = m_InstancedSystems.Find( scriptfile );
if ( idx == m_InstancedSystems.InvalidIndex() )
return NULL;
return m_InstancedSystems[ idx ];
}
IResponseSystem *PrecacheCustomResponseSystem( const char *scriptfile )
{
COM_TimestampedLog( "PrecacheCustomResponseSystem %s - Start", scriptfile );
CInstancedResponseSystem *sys = ( CInstancedResponseSystem * )FindResponseSystem( scriptfile );
if ( !sys )
{
sys = new CInstancedResponseSystem( scriptfile );
if ( !sys )
{
Error( "Failed to load response system data from %s", scriptfile );
}
if ( !sys->Init() )
{
Error( "CInstancedResponseSystem: Failed to init response system from %s!", scriptfile );
}
AddInstancedResponseSystem( scriptfile, sys );
}
sys->Precache();
COM_TimestampedLog( "PrecacheCustomResponseSystem %s - Finish", scriptfile );
return ( IResponseSystem * )sys;
}
IResponseSystem *BuildCustomResponseSystemGivenCriteria( const char *pszBaseFile, const char *pszCustomName, AI_CriteriaSet &criteriaSet, float flCriteriaScore );
void DestroyCustomResponseSystems();
virtual void LevelInitPreEntity()
{
// This will precache the default system
// All user installed systems are init'd by PrecacheCustomResponseSystem which will call sys->Precache() on the ones being used
// FIXME: This is SLOW the first time you run the engine (can take 3 - 10 seconds!!!)
if ( ShouldPrecache() )
{
Precache();
}
ResetResponseGroups();
}
void ReloadAllResponseSystems()
{
Clear();
Init();
int c = m_InstancedSystems.Count();
for ( int i = c - 1 ; i >= 0; i-- )
{
CInstancedResponseSystem *sys = m_InstancedSystems[ i ];
if ( !IsCustomManagable() )
{
sys->Clear();
sys->Init();
}
else
{
// Custom reponse rules will manage/reload themselves - remove them.
m_InstancedSystems.RemoveAt( i );
}
}
// precache sounds in case we added new ones
Precache();
}
private:
void ClearInstanced()
{
int c = m_InstancedSystems.Count();
for ( int i = c - 1 ; i >= 0; i-- )
{
CInstancedResponseSystem *sys = m_InstancedSystems[ i ];
sys->Release();
}
m_InstancedSystems.RemoveAll();
}
CUtlDict< CInstancedResponseSystem *, int > m_InstancedSystems;
friend void CC_RR_DumpHashInfo( const CCommand &args );
};
IResponseSystem *CDefaultResponseSystem::BuildCustomResponseSystemGivenCriteria( const char *pszBaseFile, const char *pszCustomName, AI_CriteriaSet &criteriaSet, float flCriteriaScore )
{
// Create a instanced response system.
CInstancedResponseSystem *pCustomSystem = new CInstancedResponseSystem( pszCustomName );
if ( !pCustomSystem )
{
Error( "BuildCustomResponseSystemGivenCriterea: Failed to create custom response system %s!", pszCustomName );
}
pCustomSystem->Clear();
// Copy the relevant rules and data.
/*
int nRuleCount = m_Rules.Count();
for ( int iRule = 0; iRule < nRuleCount; ++iRule )
*/
for ( ResponseRulePartition::tIndex iIdx = m_RulePartitions.First() ;
m_RulePartitions.IsValid(iIdx) ;
iIdx = m_RulePartitions.Next( iIdx ) )
{
Rule *pRule = &m_RulePartitions[iIdx];
if ( pRule )
{
float flScore = 0.0f;
int nCriteriaCount = pRule->m_Criteria.Count();
for ( int iCriteria = 0; iCriteria < nCriteriaCount; ++iCriteria )
{
int iRuleCriteria = pRule->m_Criteria[iCriteria];
flScore += LookForCriteria( criteriaSet, iRuleCriteria );
if ( flScore >= flCriteriaScore )
{
CopyRuleFrom( pRule, iIdx, pCustomSystem );
break;
}
}
}
}
// Set as a custom response system.
m_bCustomManagable = true;
AddInstancedResponseSystem( pszCustomName, pCustomSystem );
// pCustomSystem->DumpDictionary( pszCustomName );
return pCustomSystem;
}
void CDefaultResponseSystem::DestroyCustomResponseSystems()
{
ClearInstanced();
}
static CDefaultResponseSystem defaultresponsesytem;
IResponseSystem *g_pResponseSystem = &defaultresponsesytem;
CON_COMMAND( rr_reloadresponsesystems, "Reload all response system scripts." )
{
#ifdef GAME_DLL
if ( !UTIL_IsCommandIssuedByServerAdmin() )
return;
#endif
defaultresponsesytem.ReloadAllResponseSystems();
}
static short RESPONSESYSTEM_SAVE_RESTORE_VERSION = 1;
// note: this won't save/restore settings from instanced response systems. Could add that with a CDefSaveRestoreOps implementation if needed
//
class CDefaultResponseSystemSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
{
public:
const char *GetBlockName()
{
return "ResponseSystem";
}
void WriteSaveHeaders( ISave *pSave )
{
pSave->WriteShort( &RESPONSESYSTEM_SAVE_RESTORE_VERSION );
}
void ReadRestoreHeaders( IRestore *pRestore )
{
// No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
short version;
pRestore->ReadShort( &version );
m_fDoLoad = ( version == RESPONSESYSTEM_SAVE_RESTORE_VERSION );
}
void Save( ISave *pSave )
{
CDefaultResponseSystem& rs = defaultresponsesytem;
int count = rs.m_Responses.Count();
pSave->WriteInt( &count );
for ( int i = 0; i < count; ++i )
{
pSave->StartBlock( "ResponseGroup" );
pSave->WriteString( rs.m_Responses.GetElementName( i ) );
const ResponseGroup *group = &rs.m_Responses[ i ];
pSave->WriteAll( group );
short groupCount = group->group.Count();
pSave->WriteShort( &groupCount );
for ( int j = 0; j < groupCount; ++j )
{
const ParserResponse *response = &group->group[ j ];
pSave->StartBlock( "Response" );
pSave->WriteString( response->value );
pSave->WriteAll( response );
pSave->EndBlock();
}
pSave->EndBlock();
}
}
void Restore( IRestore *pRestore, bool createPlayers )
{
if ( !m_fDoLoad )
return;
CDefaultResponseSystem& rs = defaultresponsesytem;
int count = pRestore->ReadInt();
for ( int i = 0; i < count; ++i )
{
char szResponseGroupBlockName[SIZE_BLOCK_NAME_BUF];
pRestore->StartBlock( szResponseGroupBlockName );
if ( !Q_stricmp( szResponseGroupBlockName, "ResponseGroup" ) )
{
char groupname[ 256 ];
pRestore->ReadString( groupname, sizeof( groupname ), 0 );
// Try and find it
int idx = rs.m_Responses.Find( groupname );
if ( idx != rs.m_Responses.InvalidIndex() )
{
ResponseGroup *group = &rs.m_Responses[ idx ];
pRestore->ReadAll( group );
short groupCount = pRestore->ReadShort();
for ( int j = 0; j < groupCount; ++j )
{
char szResponseBlockName[SIZE_BLOCK_NAME_BUF];
char responsename[ 256 ];
pRestore->StartBlock( szResponseBlockName );
if ( !Q_stricmp( szResponseBlockName, "Response" ) )
{
pRestore->ReadString( responsename, sizeof( responsename ), 0 );
// Find it by name
int ri;
for ( ri = 0; ri < group->group.Count(); ++ri )
{
ParserResponse *response = &group->group[ ri ];
if ( !Q_stricmp( response->value, responsename ) )
{
break;
}
}
if ( ri < group->group.Count() )
{
ParserResponse *response = &group->group[ ri ];
pRestore->ReadAll( response );
}
}
pRestore->EndBlock();
}
}
}
pRestore->EndBlock();
}
}
private:
bool m_fDoLoad;
} g_DefaultResponseSystemSaveRestoreBlockHandler;
ISaveRestoreBlockHandler *GetDefaultResponseSystemSaveRestoreBlockHandler()
{
return &g_DefaultResponseSystemSaveRestoreBlockHandler;
}
//-----------------------------------------------------------------------------
// CResponseSystemSaveRestoreOps
//
// Purpose: Handles save and load for instanced response systems...
//
// BUGBUG: This will save the same response system to file multiple times for "shared" response systems and
// therefore it'll restore the same data onto the same pointer N times on reload (probably benign for now, but we could
// write code to save/restore the instanced ones by filename in the block handler above maybe?
//-----------------------------------------------------------------------------
class CResponseSystemSaveRestoreOps : public CDefSaveRestoreOps
{
public:
virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
{
CResponseSystem *pRS = *(CResponseSystem **)fieldInfo.pField;
if ( !pRS || pRS == &defaultresponsesytem )
return;
int count = pRS->m_Responses.Count();
pSave->WriteInt( &count );
for ( int i = 0; i < count; ++i )
{
pSave->StartBlock( "ResponseGroup" );
pSave->WriteString( pRS->m_Responses.GetElementName( i ) );
const ResponseGroup *group = &pRS->m_Responses[ i ];
pSave->WriteAll( group );
short groupCount = group->group.Count();
pSave->WriteShort( &groupCount );
for ( int j = 0; j < groupCount; ++j )
{
const ParserResponse *response = &group->group[ j ];
pSave->StartBlock( "Response" );
pSave->WriteString( response->value );
pSave->WriteAll( response );
pSave->EndBlock();
}
pSave->EndBlock();
}
}
virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore )
{
CResponseSystem *pRS = *(CResponseSystem **)fieldInfo.pField;
if ( !pRS || pRS == &defaultresponsesytem )
return;
int count = pRestore->ReadInt();
for ( int i = 0; i < count; ++i )
{
char szResponseGroupBlockName[SIZE_BLOCK_NAME_BUF];
pRestore->StartBlock( szResponseGroupBlockName );
if ( !Q_stricmp( szResponseGroupBlockName, "ResponseGroup" ) )
{
char groupname[ 256 ];
pRestore->ReadString( groupname, sizeof( groupname ), 0 );
// Try and find it
int idx = pRS->m_Responses.Find( groupname );
if ( idx != pRS->m_Responses.InvalidIndex() )
{
ResponseGroup *group = &pRS->m_Responses[ idx ];
pRestore->ReadAll( group );
short groupCount = pRestore->ReadShort();
for ( int j = 0; j < groupCount; ++j )
{
char szResponseBlockName[SIZE_BLOCK_NAME_BUF];
char responsename[ 256 ];
pRestore->StartBlock( szResponseBlockName );
if ( !Q_stricmp( szResponseBlockName, "Response" ) )
{
pRestore->ReadString( responsename, sizeof( responsename ), 0 );
// Find it by name
int ri;
for ( ri = 0; ri < group->group.Count(); ++ri )
{
ParserResponse *response = &group->group[ ri ];
if ( !Q_stricmp( response->value, responsename ) )
{
break;
}
}
if ( ri < group->group.Count() )
{
ParserResponse *response = &group->group[ ri ];
pRestore->ReadAll( response );
}
}
pRestore->EndBlock();
}
}
}
pRestore->EndBlock();
}
}
} g_ResponseSystemSaveRestoreOps;
ISaveRestoreOps *responseSystemSaveRestoreOps = &g_ResponseSystemSaveRestoreOps;
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CDefaultResponseSystem::Init()
{
/*
Warning( "sizeof( Response ) == %d\n", sizeof( Response ) );
Warning( "sizeof( ResponseGroup ) == %d\n", sizeof( ResponseGroup ) );
Warning( "sizeof( Criteria ) == %d\n", sizeof( Criteria ) );
Warning( "sizeof( AI_ResponseParams ) == %d\n", sizeof( AI_ResponseParams ) );
*/
const char *basescript = GetScriptFile();
LoadRuleSet( basescript );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDefaultResponseSystem::Shutdown()
{
// Wipe instanced versions
ClearInstanced();
// Clear outselves
Clear();
// IServerSystem chain
BaseClass::Shutdown();
}
//-----------------------------------------------------------------------------
// Purpose: Instance a custom response system
// Input : *scriptfile -
// Output : IResponseSystem
//-----------------------------------------------------------------------------
IResponseSystem *PrecacheCustomResponseSystem( const char *scriptfile )
{
return defaultresponsesytem.PrecacheCustomResponseSystem( scriptfile );
}
//-----------------------------------------------------------------------------
// Purpose: Instance a custom response system
// Input : *scriptfile -
// set -
// Output : IResponseSystem
//-----------------------------------------------------------------------------
IResponseSystem *BuildCustomResponseSystemGivenCriteria( const char *pszBaseFile, const char *pszCustomName, AI_CriteriaSet &criteriaSet, float flCriteriaScore )
{
return defaultresponsesytem.BuildCustomResponseSystemGivenCriteria( pszBaseFile, pszCustomName, criteriaSet, flCriteriaScore );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void DestroyCustomResponseSystems()
{
defaultresponsesytem.DestroyCustomResponseSystems();
}
+29
View File
@@ -0,0 +1,29 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef AI_RESPONSESYSTEM_H
#define AI_RESPONSESYSTEM_H
#include "utlvector.h"
#ifdef _WIN32
#pragma once
#endif
#include "ai_criteria.h"
#include "../../public/responserules/response_types.h"
// using ResponseRules::IResponseFilter;
// using ResponseRules::IResponseSystem;
ResponseRules::IResponseSystem *PrecacheCustomResponseSystem( const char *scriptfile );
ResponseRules::IResponseSystem *BuildCustomResponseSystemGivenCriteria( const char *pszBaseFile, const char *pszCustomName, AI_CriteriaSet &criteriaSet, float flCriteriaScore );
void DestroyCustomResponseSystems();
class ISaveRestoreBlockHandler *GetDefaultResponseSystemSaveRestoreBlockHandler();
class ISaveRestoreOps *GetResponseSystemSaveRestoreOps();
#endif // AI_RESPONSESYSTEM_H
+28
View File
@@ -0,0 +1,28 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "ai_speechconcept.h"
#ifdef GAME_DLL
#include "game.h"
#include "ai_basenpc.h"
#include "sceneentity.h"
#endif
#include "engine/ienginesound.h"
#include "keyvalues.h"
#include "ai_criteria.h"
#include "isaverestore.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
// empty
+45
View File
@@ -0,0 +1,45 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Class data for an AI Concept, an atom of response-driven dialog.
//
// $NoKeywords: $
//=============================================================================//
#ifndef AI_SPEECHCONCEPT_H
#define AI_SPEECHCONCEPT_H
#if defined( _WIN32 )
#pragma once
#endif
#include "../../public/responserules/response_types.h"
class CAI_Concept : public ResponseRules::CRR_Concept
{
public:
CAI_Concept() {};
// construct concept from a string.
CAI_Concept(const char *fromString) : CRR_Concept(fromString) {} ;
// get/set BS
inline EHANDLE GetSpeaker() const { return m_hSpeaker; }
inline void SetSpeaker(EHANDLE val) { m_hSpeaker = val; }
/*
inline EHANDLE GetTarget() const { return m_hTarget; }
inline void SetTarget(EHANDLE val) { m_hTarget = val; }
inline EHANDLE GetTopic() const { return m_hTopic; }
inline void SetTopic(EHANDLE val) { m_hTopic = val; }
*/
protected:
EHANDLE m_hSpeaker;
/*
EHANDLE m_hTarget;
EHANDLE m_hTopic;
*/
};
#endif
+20 -3
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Base combat character with no AI
//
@@ -100,7 +100,7 @@ int CAmmoDef::NPCDamage(int nAmmoIndex)
// Input :
// Output :
//-----------------------------------------------------------------------------
int CAmmoDef::MaxCarry(int nAmmoIndex)
int CAmmoDef::MaxCarry(int nAmmoIndex, const CBaseCombatCharacter *owner)
{
if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex )
return 0;
@@ -108,7 +108,7 @@ int CAmmoDef::MaxCarry(int nAmmoIndex)
if ( m_AmmoType[nAmmoIndex].pMaxCarry == USE_CVAR )
{
if ( m_AmmoType[nAmmoIndex].pMaxCarryCVar )
return m_AmmoType[nAmmoIndex].pMaxCarryCVar->GetFloat();
return m_AmmoType[nAmmoIndex].pMaxCarryCVar->GetInt();
return 0;
}
@@ -118,6 +118,23 @@ int CAmmoDef::MaxCarry(int nAmmoIndex)
}
}
bool CAmmoDef::CanCarryInfiniteAmmo(int nAmmoIndex)
{
if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex )
return false;
int maxCarry = m_AmmoType[nAmmoIndex].pMaxCarry;
if ( maxCarry == USE_CVAR )
{
if ( m_AmmoType[nAmmoIndex].pMaxCarryCVar )
{
maxCarry = m_AmmoType[nAmmoIndex].pMaxCarryCVar->GetInt();
}
}
return maxCarry == INFINITE_AMMO ? true : false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
+4 -2
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Holds defintion for game ammo types
//
@@ -75,7 +75,8 @@ public:
int Index(const char *psz);
int PlrDamage(int nAmmoIndex);
int NPCDamage(int nAmmoIndex);
int MaxCarry(int nAmmoIndex);
int MaxCarry(int nAmmoIndex, const CBaseCombatCharacter *owner);
bool CanCarryInfiniteAmmo(int nAmmoIndex);
int DamageType(int nAmmoIndex);
int TracerType(int nAmmoIndex);
float DamageForce(int nAmmoIndex);
@@ -85,6 +86,7 @@ public:
void AddAmmoType(char const* name, int damageType, int tracerType, int plr_dmg, int npc_dmg, int carry, float physicsForceImpulse, int nFlags, int minSplashSize = 4, int maxSplashSize = 8 );
void AddAmmoType(char const* name, int damageType, int tracerType, char const* plr_cvar, char const* npc_var, char const* carry_cvar, float physicsForceImpulse, int nFlags, int minSplashSize = 4, int maxSplashSize = 8 );
int NumAmmoTypes() { return m_nAmmoIndex; }
CAmmoDef(void);
virtual ~CAmmoDef( void );
+190 -56
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -62,14 +62,18 @@ void SetEventIndexForSequence( mstudioseqdesc_t &seqdesc )
if ( &seqdesc == NULL )
return;
seqdesc.flags |= STUDIO_EVENT;
if ( seqdesc.numevents == 0 )
return;
#ifndef CLIENT_DLL
seqdesc.flags |= STUDIO_EVENT;
#else
seqdesc.flags |= STUDIO_EVENT_CLIENT;
#endif
for ( int index = 0; index < (int)seqdesc.numevents; index++ )
{
mstudioevent_t *pevent = seqdesc.pEvent( index );
mstudioevent_t *pevent = (mstudioevent_for_client_server_t*)seqdesc.pEvent( index );
if ( !pevent )
continue;
@@ -82,25 +86,29 @@ void SetEventIndexForSequence( mstudioseqdesc_t &seqdesc )
if ( iEventIndex == -1 )
{
pevent->event = EventList_RegisterPrivateEvent( pEventName );
pevent->event_newsystem = EventList_RegisterPrivateEvent( pEventName );
}
else
{
pevent->event = iEventIndex;
pevent->event_newsystem = iEventIndex;
pevent->type |= EventList_GetEventType( iEventIndex );
}
}
}
}
mstudioevent_t *GetEventIndexForSequence( mstudioseqdesc_t &seqdesc )
mstudioevent_for_client_server_t *GetEventIndexForSequence( mstudioseqdesc_t &seqdesc )
{
if (!(seqdesc.flags & STUDIO_EVENT))
#ifndef CLIENT_DLL
if ( !(seqdesc.flags & STUDIO_EVENT) )
#else
if ( !(seqdesc.flags & STUDIO_EVENT_CLIENT) )
#endif
{
SetEventIndexForSequence( seqdesc );
}
return seqdesc.pEvent( 0 );
return (mstudioevent_for_client_server_t*)seqdesc.pEvent( 0 );
}
@@ -229,6 +237,11 @@ bool IsInPrediction()
int SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence )
{
VPROF( "SelectWeightedSequence" );
#ifdef CLIENT_DLL
VPROF_INCREMENT_COUNTER( "Client SelectWeightedSequence", 1 );
#else // ifdef GAME_DLL
VPROF_INCREMENT_COUNTER( "Server SelectWeightedSequence", 1 );
#endif
if (! pstudiohdr)
return 0;
@@ -238,38 +251,13 @@ int SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequenc
VerifySequenceIndex( pstudiohdr );
#if STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW
int weighttotal = 0;
int seq = ACTIVITY_NOT_AVAILABLE;
int weight = 0;
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
int numSeq = pstudiohdr->GetNumSeq();
if ( numSeq == 1 )
{
int curActivity = GetSequenceActivity( pstudiohdr, i, &weight );
if (curActivity == activity)
{
if ( curSequence == i && weight < 0 )
{
seq = i;
break;
}
weighttotal += iabs(weight);
int randomValue;
if ( IsInPrediction() )
randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1, i );
else
randomValue = RandomInt( 0, weighttotal - 1 );
if (!weighttotal || randomValue < iabs(weight))
seq = i;
}
return ( GetSequenceActivity( pstudiohdr, 0, NULL ) == activity ) ? 0 : ACTIVITY_NOT_AVAILABLE;
}
return seq;
#else
return pstudiohdr->SelectWeightedSequence( activity, curSequence );
#endif
}
@@ -279,6 +267,26 @@ int SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequenc
// sequence having a number of spaces corresponding to its weight.
int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence )
{
// is the current sequence appropriate?
if (curSequence >= 0)
{
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( curSequence );
if (seqdesc.activity == activity && seqdesc.actweight < 0)
return curSequence;
}
if ( !pstudiohdr->SequencesAvailable() )
{
return ACTIVITY_NOT_AVAILABLE;
}
if ( pstudiohdr->GetNumSeq() == 1 )
{
AssertMsg( 0, "Expected single sequence case to be handled in ::SelectWeightedSequence()" );
return ACTIVITY_NOT_AVAILABLE;
}
if (!ValidateAgainst(pstudiohdr))
{
AssertMsg1(false, "CStudioHdr %s has changed its vmodel pointer without reinitializing its activity mapping! Now performing emergency reinitialization.", pstudiohdr->pszName());
@@ -290,15 +298,6 @@ int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequence( CStudioHdr *
if (!m_pSequenceTuples)
return ACTIVITY_NOT_AVAILABLE;
// is the current sequence appropriate?
if (curSequence >= 0)
{
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( curSequence );
if (seqdesc.activity == activity && seqdesc.actweight < 0)
return curSequence;
}
// get the data for the given activity
HashValueType dummy( activity, 0, 0, 0 );
UtlHashHandle_t handle = m_ActToSeqHash.Find(dummy);
@@ -308,18 +307,36 @@ int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequence( CStudioHdr *
}
const HashValueType * __restrict actData = &m_ActToSeqHash[handle];
AssertMsg2( actData->totalWeight > 0, "Activity %s has total weight of %d!",
activity, actData->totalWeight );
int weighttotal = actData->totalWeight;
// generate a random number from 0 to the total weight
int randomValue;
if ( IsInPrediction() )
// failsafe if the weight is 0: assume the artist screwed up and that the first sequence
// for this activity should be returned.
int randomValue = 0;
if ( actData->totalWeight <= 0 )
{
randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1 );
Warning( "Activity %s has %d sequences with a total weight of %d!", ActivityList_NameForIndex(activity), actData->count, actData->totalWeight );
return (m_pSequenceTuples + actData->startingIdx)->seqnum;
}
else if ( actData->totalWeight == 1 )
{
randomValue = 0;
}
else
{
randomValue = RandomInt( 0, weighttotal - 1 );
// generate a random number from 0 to the total weight
if ( IsInPrediction() )
{
randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1 );
}
else
{
randomValue = RandomInt( 0, weighttotal - 1 );
}
}
// chug through the entries in the list (they are sequential therefore cache-coherent)
// until we run out of random juice
SequenceTuple * __restrict sequenceInfo = m_pSequenceTuples + actData->startingIdx;
@@ -339,6 +356,77 @@ int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequence( CStudioHdr *
}
int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequenceFromModifiers( CStudioHdr *pstudiohdr, int activity, CUtlSymbol *pActivityModifiers, int iModifierCount )
{
if ( !pstudiohdr->SequencesAvailable() )
{
return ACTIVITY_NOT_AVAILABLE;
}
VerifySequenceIndex( pstudiohdr );
if ( pstudiohdr->GetNumSeq() == 1 )
{
return ( ::GetSequenceActivity( pstudiohdr, 0, NULL ) == activity ) ? 0 : ACTIVITY_NOT_AVAILABLE;
}
if (!ValidateAgainst(pstudiohdr))
{
AssertMsg1(false, "CStudioHdr %s has changed its vmodel pointer without reinitializing its activity mapping! Now performing emergency reinitialization.", pstudiohdr->pszName());
ExecuteOnce(DebuggerBreakIfDebugging());
Reinitialize(pstudiohdr);
}
// a null m_pSequenceTuples just means that this studio header has no activities.
if (!m_pSequenceTuples)
return ACTIVITY_NOT_AVAILABLE;
// get the data for the given activity
HashValueType dummy( activity, 0, 0, 0 );
UtlHashHandle_t handle = m_ActToSeqHash.Find(dummy);
if (!m_ActToSeqHash.IsValidHandle(handle))
{
return ACTIVITY_NOT_AVAILABLE;
}
const HashValueType * __restrict actData = &m_ActToSeqHash[handle];
// go through each sequence and give it a score
int top_score = -1;
CUtlVector<int> topScoring( actData->count, actData->count );
for ( int i = 0; i < actData->count; i++ )
{
SequenceTuple * __restrict sequenceInfo = m_pSequenceTuples + actData->startingIdx + i;
int score = 0;
// count matching activity modifiers
for ( int m = 0; m < iModifierCount; m++ )
{
int num_modifiers = sequenceInfo->iNumActivityModifiers;
for ( int k = 0; k < num_modifiers; k++ )
{
if ( sequenceInfo->pActivityModifiers[ k ] == pActivityModifiers[ m ] )
{
score++;
break;
}
}
}
if ( score > top_score )
{
topScoring.RemoveAll();
topScoring.AddToTail( sequenceInfo->seqnum );
top_score = score;
}
}
// randomly pick between the highest scoring sequences ( NOTE: this method of selecting a sequence ignores activity weights )
if ( IsInPrediction() )
{
return topScoring[ SharedRandomInt( "SelectWeightedSequence", 0, topScoring.Count() - 1 ) ];
}
return topScoring[ RandomInt( 0, topScoring.Count() - 1 ) ];
}
#endif
@@ -461,7 +549,7 @@ void GetSequenceLinearMotion( CStudioHdr *pstudiohdr, int iSequence, const float
if ( pstudiohdr->GetNumSeq() > 0 )
{
static int msgCount = 0;
while ( ++msgCount <= 10 )
while ( ++msgCount < 10 )
{
Msg( "Bad sequence (%i out of %i max) in GetSequenceLinearMotion() for model '%s'!\n", iSequence, pstudiohdr->GetNumSeq(), pstudiohdr->pszName() );
}
@@ -473,6 +561,36 @@ void GetSequenceLinearMotion( CStudioHdr *pstudiohdr, int iSequence, const float
QAngle vecAngles;
Studio_SeqMovement( pstudiohdr, iSequence, 0, 1.0, poseParameter, (*pVec), vecAngles );
}
float GetSequenceLinearMotionAndDuration( CStudioHdr *pstudiohdr, int iSequence, const float poseParameter[], Vector *pVec )
{
pVec->Init();
if ( !pstudiohdr )
{
Msg( "Bad pstudiohdr in GetSequenceLinearMotion()!\n" );
return 0.0f;
}
if ( !pstudiohdr->SequencesAvailable() )
return 0.0f;
if ( iSequence < 0 || iSequence >= pstudiohdr->GetNumSeq() )
{
// Don't spam on bogus model
if ( pstudiohdr->GetNumSeq() > 0 )
{
static int msgCount = 0;
while ( ++msgCount < 10 )
{
Msg( "Bad sequence (%i out of %i max) in GetSequenceLinearMotion() for model '%s'!\n", iSequence, pstudiohdr->GetNumSeq(), pstudiohdr->pszName() );
}
}
return 0.0f;
}
return Studio_SeqMovementAndDuration( pstudiohdr, iSequence, 0, 1.0, poseParameter, (*pVec) );
}
#endif
const char *GetSequenceName( CStudioHdr *pstudiohdr, int iSequence )
@@ -546,7 +664,7 @@ bool HasAnimationEventOfType( CStudioHdr *pstudiohdr, int sequence, int type )
int index;
for ( index = 0; index < (int)seqdesc.numevents; index++ )
{
if ( pevent[ index ].event == type )
if ( pevent[ index ].Event() == type )
{
return true;
}
@@ -574,7 +692,7 @@ int GetAnimationEvent( CStudioHdr *pstudiohdr, int sequence, animevent_t *pNPCEv
if ( !(pevent[index].type & AE_TYPE_SERVER) )
continue;
}
else if ( pevent[index].event >= EVENT_CLIENT ) //Adrian - Support the old event system
else if ( pevent[index].Event_OldSystem() >= EVENT_CLIENT ) //Adrian - Support the old event system
continue;
bool bOverlapEvent = false;
@@ -601,9 +719,9 @@ int GetAnimationEvent( CStudioHdr *pstudiohdr, int sequence, animevent_t *pNPCEv
#else
pNPCEvent->eventtime = 0.0f;
#endif
pNPCEvent->event = pevent[index].event;
pNPCEvent->options = pevent[index].pszOptions();
pNPCEvent->type = pevent[index].type;
pNPCEvent->Event( pevent[index].Event() );
pNPCEvent->options = pevent[index].pszOptions();
return index + 1;
}
}
@@ -847,6 +965,21 @@ const char *GetBodygroupName( CStudioHdr *pstudiohdr, int iGroup )
return pbodypart->pszName();
}
const char *GetBodygroupPartName( CStudioHdr *pstudiohdr, int iGroup, int iPart )
{
if ( !pstudiohdr)
return "";
if (iGroup >= pstudiohdr->numbodyparts())
return "";
mstudiobodyparts_t *pbodypart = pstudiohdr->pBodypart( iGroup );
if ( iPart < 0 && iPart >= pbodypart->nummodels )
return "";
return pbodypart->pModel( iPart )->name;
}
int FindBodygroupByName( CStudioHdr *pstudiohdr, const char *name )
{
if ( !pstudiohdr )
@@ -894,6 +1027,7 @@ int GetSequenceActivity( CStudioHdr *pstudiohdr, int sequence, int *pweight )
return 0;
}
Assert(sequence >= 0 && sequence < pstudiohdr->GetNumSeq());
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence );
if (!(seqdesc.flags & STUDIO_ACTIVITY))
+9 -2
View File
@@ -1,13 +1,18 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
//===========================================================================//
#ifndef ANIMATION_H
#define ANIMATION_H
#ifdef _WIN32
#pragma once
#endif
#define ACTIVITY_NOT_AVAILABLE -1
struct animevent_t;
@@ -25,6 +30,7 @@ int SelectHeaviestSequence( CStudioHdr *pstudiohdr, int activity );
void SetEventIndexForSequence( mstudioseqdesc_t &seqdesc );
void BuildAllAnimationEventIndexes( CStudioHdr *pstudiohdr );
void ResetEventIndexes( CStudioHdr *pstudiohdr );
float GetSequenceLinearMotionAndDuration( CStudioHdr *pstudiohdr, int iSequence, const float poseParameter[], Vector *pVec );
void GetEyePosition( CStudioHdr *pstudiohdr, Vector &vecEyePosition );
@@ -49,6 +55,7 @@ int GetBodygroup( CStudioHdr *pstudiohdr, int body, int iGroup );
const char *GetBodygroupName( CStudioHdr *pstudiohdr, int iGroup );
int FindBodygroupByName( CStudioHdr *pstudiohdr, const char *name );
const char *GetBodygroupPartName( CStudioHdr *pstudiohdr, int iGroup, int iPart );
int GetBodygroupCount( CStudioHdr *pstudiohdr, int iGroup );
int GetNumBodyGroups( CStudioHdr *pstudiohdr );
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
+87 -53
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -20,12 +20,18 @@
ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (client) animation state for the specified entity (-1 for none)." );
ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." );
ConVar showanimstate_activities( "cl_showanimstate_activities", "1", FCVAR_CHEAT, "Show activities in the (client) animation state display." );
#else
#include "player.h"
ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (server) animation state for the specified entity (-1 for none)." );
ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." );
ConVar showanimstate_activities( "sv_showanimstate_activities", "1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show activities in the (server) animation state display." );
#endif
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
// Below this many degrees, slow down turning rate linearly
#define FADE_TURN_DEGREES 45.0f
@@ -65,7 +71,7 @@ CBasePlayerAnimState::CBasePlayerAnimState()
m_flEyePitch = 0.0f;
m_bCurrentFeetYawInitialized = false;
m_flCurrentTorsoYaw = 0.0f;
m_nTurningInPlace = TURN_NONE;
m_flCurrentTorsoYaw = TURN_NONE;
m_flMaxGroundSpeed = 0.0f;
m_flStoredCycle = 0.0f;
@@ -268,10 +274,8 @@ void CBasePlayerAnimState::ComputeMainSequence()
// Export to our outer class..
int animDesired = SelectWeightedSequence( TranslateActivity(idealActivity) );
#if !defined( HL1_CLIENT_DLL ) && !defined ( HL1_DLL )
if ( pPlayer->GetSequenceActivity( pPlayer->GetSequence() ) == pPlayer->GetSequenceActivity( animDesired ) )
if ( !ShouldResetMainSequence( pPlayer->GetSequence(), animDesired ) )
return;
#endif
if ( animDesired < 0 )
animDesired = 0;
@@ -279,19 +283,27 @@ void CBasePlayerAnimState::ComputeMainSequence()
pPlayer->ResetSequence( animDesired );
#ifdef CLIENT_DLL
// If we went from idle to walk, reset the interpolation history.
// Kind of hacky putting this here.. it might belong outside the base class.
if ( (oldActivity == ACT_CROUCHIDLE || oldActivity == ACT_IDLE) &&
(idealActivity == ACT_WALK || idealActivity == ACT_RUN_CROUCH) )
if ( ShouldResetGroundSpeed( oldActivity, idealActivity ) )
{
ResetGroundSpeed();
}
#endif
}
bool CBasePlayerAnimState::ShouldResetMainSequence( int iCurrentSequence, int iNewSequence )
{
if ( !GetOuter() )
return false;
return GetOuter()->GetSequenceActivity( iCurrentSequence ) == GetOuter()->GetSequenceActivity( iNewSequence );
}
bool CBasePlayerAnimState::ShouldResetGroundSpeed( Activity oldActivity, Activity idealActivity )
{
// If we went from idle to walk, reset the interpolation history.
return ( (oldActivity == ACT_CROUCHIDLE || oldActivity == ACT_IDLE) &&
(idealActivity == ACT_WALK || idealActivity == ACT_RUN_CROUCH) );
}
void CBasePlayerAnimState::UpdateAimSequenceLayers(
float flCycle,
@@ -333,9 +345,9 @@ void CBasePlayerAnimState::UpdateAimSequenceLayers(
CAnimationLayer *pSource0 = &pTransitioner->m_animationQueue[0];
*pDest0 = *pSource0;
pDest0->m_flWeight = 1;
pDest1->m_flWeight = 0;
pDest0->m_nOrder = iFirstLayer;
pDest0->SetWeight( 1 );
pDest1->SetWeight( 0 );
pDest0->SetOrder( iFirstLayer );
#ifndef CLIENT_DLL
pDest0->m_fFlags |= ANIM_LAYER_ACTIVE;
@@ -349,11 +361,11 @@ void CBasePlayerAnimState::UpdateAimSequenceLayers(
*pDest0 = *pSource0;
*pDest1 = *pSource1;
Assert( pDest0->m_flWeight >= 0.0f && pDest0->m_flWeight <= 1.0f );
pDest1->m_flWeight = 1 - pDest0->m_flWeight; // This layer just mirrors the other layer's weight (one fades in while the other fades out).
Assert( pDest0->GetWeight() >= 0.0f && pDest0->GetWeight() <= 1.0f );
pDest1->SetWeight( 1 - pDest0->GetWeight() ); // This layer just mirrors the other layer's weight (one fades in while the other fades out).
pDest0->m_nOrder = iFirstLayer;
pDest1->m_nOrder = iFirstLayer+1;
pDest0->SetOrder( iFirstLayer );
pDest1->SetOrder( iFirstLayer+1 );
#ifndef CLIENT_DLL
pDest0->m_fFlags |= ANIM_LAYER_ACTIVE;
@@ -361,13 +373,14 @@ void CBasePlayerAnimState::UpdateAimSequenceLayers(
#endif
}
pDest0->m_flWeight *= flWeightScale * flAimSequenceWeight;
pDest0->m_flWeight = clamp( (float)pDest0->m_flWeight, 0.0f, 1.0f );
pDest0->SetWeight( pDest0->GetWeight() * flWeightScale * flAimSequenceWeight );
pDest0->SetWeight( clamp( (float)pDest0->GetWeight(), 0.0f, 1.0f ) );
pDest1->m_flWeight *= flWeightScale * flAimSequenceWeight;
pDest1->m_flWeight = clamp( (float)pDest1->m_flWeight, 0.0f, 1.0f );
pDest1->SetWeight( pDest1->GetWeight() * flWeightScale * flAimSequenceWeight );
pDest1->SetWeight( clamp( (float)pDest1->GetWeight(), 0.0f, 1.0f ) );
pDest0->m_flCycle = pDest1->m_flCycle = flCycle;
pDest0->SetCycle( flCycle );
pDest1->SetCycle( flCycle );
}
@@ -380,18 +393,19 @@ void CBasePlayerAnimState::OptimizeLayerWeights( int iFirstLayer, int nLayers )
for ( i=1; i < nLayers; i++ )
{
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i );
if ( pLayer->IsActive() && pLayer->m_flWeight > 0.0f )
if ( pLayer->IsActive() && pLayer->GetWeight() > 0.0f )
{
totalWeight += pLayer->m_flWeight;
totalWeight += pLayer->GetWeight();
}
}
// Set the idle layer's weight to be 1 minus the sum of other layer weights
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer );
if ( pLayer->IsActive() && pLayer->m_flWeight > 0.0f )
if ( pLayer->IsActive() && pLayer->GetWeight() > 0.0f )
{
pLayer->m_flWeight = 1.0f - totalWeight;
pLayer->m_flWeight = MAX( (float)pLayer->m_flWeight, 0.0f);
float flWeight = 1.0f - totalWeight;
flWeight = MAX( flWeight, 0.0f );
pLayer->SetWeight( flWeight );
}
// This part is just an optimization. Since we have the walk/run animations weighted on top of
@@ -403,7 +417,7 @@ void CBasePlayerAnimState::OptimizeLayerWeights( int iFirstLayer, int nLayers )
for ( i=0; i < nLayers; i++ )
{
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i );
if ( pLayer->IsActive() && pLayer->m_flWeight > 0.99 )
if ( pLayer->IsActive() && pLayer->GetWeight() > 0.99 )
iLastOne = i;
}
@@ -413,7 +427,7 @@ void CBasePlayerAnimState::OptimizeLayerWeights( int iFirstLayer, int nLayers )
{
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i );
#ifdef CLIENT_DLL
pLayer->m_nOrder = CBaseAnimatingOverlay::MAX_OVERLAYS;
pLayer->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
#else
pLayer->m_nOrder.Set( CBaseAnimatingOverlay::MAX_OVERLAYS );
pLayer->m_fFlags = 0;
@@ -521,7 +535,7 @@ float CBasePlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving )
{
// Note this gets set back to 1.0 if sequence changes due to ResetSequenceInfo below
flReturnValue = speed / flGroundSpeed;
flReturnValue = clamp( flReturnValue, 0.01f, 10.f ); // don't go nuts here.
flReturnValue = clamp( flReturnValue, 0.01, 10 ); // don't go nuts here.
}
*bIsMoving = true;
}
@@ -674,35 +688,37 @@ void CBasePlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr )
// This makes the 8-way blend act like a 9-way blend by blending to
// an idle sequence as he slows down.
#if defined(CLIENT_DLL)
#ifndef INFESTED_DLL
bool bIsMoving;
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( MAIN_IDLE_SEQUENCE_LAYER );
pLayer->m_flWeight = 1 - CalcMovementPlaybackRate( &bIsMoving );
pLayer->SetWeight( 1 - CalcMovementPlaybackRate( &bIsMoving ) );
if ( !bIsMoving )
{
pLayer->m_flWeight = 1;
pLayer->SetWeight( 1 );
}
if ( ShouldChangeSequences() )
{
// Whenever this layer stops blending, we can choose a new idle sequence to blend to, so he
// doesn't always use the same idle.
if ( pLayer->m_flWeight < 0.02f || m_iCurrent8WayIdleSequence == -1 )
if ( pLayer->GetWeight() < 0.02f || m_iCurrent8WayIdleSequence == -1 )
{
m_iCurrent8WayIdleSequence = m_pOuter->SelectWeightedSequence( ACT_IDLE );
m_iCurrent8WayCrouchIdleSequence = m_pOuter->SelectWeightedSequence( ACT_CROUCHIDLE );
}
if ( m_eCurrentMainSequenceActivity == ACT_CROUCHIDLE || m_eCurrentMainSequenceActivity == ACT_RUN_CROUCH )
pLayer->m_nSequence = m_iCurrent8WayCrouchIdleSequence;
pLayer->SetSequence( m_iCurrent8WayCrouchIdleSequence );
else
pLayer->m_nSequence = m_iCurrent8WayIdleSequence;
pLayer->SetSequence( m_iCurrent8WayIdleSequence );
}
pLayer->m_flPlaybackRate = 1;
pLayer->m_flCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, pLayer->m_nSequence ) * gpGlobals->frametime;
pLayer->m_flCycle = fmod( pLayer->m_flCycle, 1 );
pLayer->m_nOrder = MAIN_IDLE_SEQUENCE_LAYER;
pLayer->SetPlaybackRate( 1 );
pLayer->SetCycle( pLayer->GetCycle() + m_pOuter->GetSequenceCycleRate( pStudioHdr, pLayer->GetSequence() ) * gpGlobals->frametime );
pLayer->SetCycle( fmod( pLayer->GetCycle(), 1 ) );
pLayer->SetOrder( MAIN_IDLE_SEQUENCE_LAYER );
#endif
#endif
}
}
@@ -721,7 +737,7 @@ void CBasePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr )
{
flPitch -= 360.0f;
}
flPitch = clamp( flPitch, -90.f, 90.f );
flPitch = clamp( flPitch, -90, 90 );
// See if we have a blender for pitch
int pitch = GetOuter()->LookupPoseParameter( pStudioHdr, "body_pitch" );
@@ -762,7 +778,21 @@ int CBasePlayerAnimState::ConvergeAngles( float goal,float maxrate, float maxgap
if ( anglediffabs > maxgap )
{
// gap is too big, jump
maxmove = (anglediffabs - maxgap);
//maxmove = (anglediffabs - maxgap);
float flTooFar = MIN( anglediffabs - maxgap, maxmove * 5 );
if ( anglediff > 0 )
{
current += flTooFar;
}
else
{
current -= flTooFar;
}
current = AngleNormalize( current );
anglediff = goal - current;
anglediff = AngleNormalize( anglediff );
anglediffabs = fabs( anglediff );
Msg( "jumped = %f\n", flTooFar );
}
if ( anglediffabs < maxmove )
@@ -853,7 +883,7 @@ void CBasePlayerAnimState::ComputePoseParam_BodyYaw()
if ( m_flCurrentFeetYaw != m_flGoalFeetYaw )
{
ConvergeAngles( m_flGoalFeetYaw, mp_feetyawrate.GetFloat(), m_AnimConfig.m_flMaxBodyYawDegrees,
ConvergeAngles( m_flGoalFeetYaw, GetFeetYawRate(), m_AnimConfig.m_flMaxBodyYawDegrees,
gpGlobals->frametime, m_flCurrentFeetYaw );
m_flLastTurnTime = gpGlobals->curtime;
@@ -1001,8 +1031,8 @@ void CBasePlayerAnimState::DebugShowAnimState( int iStartLine )
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( MAIN_IDLE_SEQUENCE_LAYER );
AnimStatePrintf( iLine++, "idle: %s, weight: %.2f\n",
GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ),
(float)pLayer->m_flWeight );
GetSequenceName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ),
(float)pLayer->GetWeight() );
}
for ( int i=0; i < m_pOuter->GetNumAnimOverlays()-1; i++ )
@@ -1010,20 +1040,20 @@ void CBasePlayerAnimState::DebugShowAnimState( int iStartLine )
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( AIMSEQUENCE_LAYER + i );
#ifdef CLIENT_DLL
AnimStatePrintf( iLine++, "%s(%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)",
!pLayer->IsActive() ? "-- ": (pLayer->m_nSequence == 0 ? "-- " : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ) ),
!pLayer->IsActive() ? 0 : (int)pLayer->m_nSequence,
!pLayer->IsActive() ? 0 : (float)pLayer->m_flWeight,
!pLayer->IsActive() ? 0 : (float)pLayer->m_flCycle,
!pLayer->IsActive() ? 0 : (int)pLayer->m_nOrder,
!pLayer->IsActive() ? "-- ": (pLayer->GetSequence() == 0 ? "-- " : (showanimstate_activities.GetBool()) ? GetSequenceActivityName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ) : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ) ),
!pLayer->IsActive() ? 0 : (int)pLayer->GetSequence(),
!pLayer->IsActive() ? 0 : (float)pLayer->GetWeight(),
!pLayer->IsActive() ? 0 : (float)pLayer->GetCycle(),
!pLayer->IsActive() ? 0 : (int)pLayer->GetOrder(),
i
);
#else
AnimStatePrintf( iLine++, "%s(%d), flags (%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)",
!pLayer->IsActive() ? "-- " : ( pLayer->m_nSequence == 0 ? "-- " : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ) ),
!pLayer->IsActive() ? 0 : (int)pLayer->m_nSequence,
!pLayer->IsActive() ? "-- " : ( pLayer->GetSequence() == 0 ? "-- " : (showanimstate_activities.GetBool()) ? GetSequenceActivityName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ) : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ) ),
!pLayer->IsActive() ? 0 : (int)pLayer->GetSequence(),
!pLayer->IsActive() ? 0 : (int)pLayer->m_fFlags,// Doesn't exist on client
!pLayer->IsActive() ? 0 : (float)pLayer->m_flWeight,
!pLayer->IsActive() ? 0 : (float)pLayer->m_flCycle,
!pLayer->IsActive() ? 0 : (float)pLayer->GetWeight(),
!pLayer->IsActive() ? 0 : (float)pLayer->GetCycle(),
!pLayer->IsActive() ? 0 : (int)pLayer->m_nOrder,
i
);
@@ -1077,3 +1107,7 @@ int CBasePlayerAnimState::SelectWeightedSequence( Activity activity )
return GetOuter()->SelectWeightedSequence( activity );
}
float CBasePlayerAnimState::GetFeetYawRate( void )
{
return mp_feetyawrate.GetFloat();
}
+14 -11
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -13,7 +13,7 @@
#include "iplayeranimstate.h"
#include "studio.h"
#include "sequence_Transitioner.h"
#include "sequence_transitioner.h"
#ifdef CLIENT_DLL
class C_BaseAnimatingOverlay;
@@ -141,8 +141,8 @@ public:
void DebugShowAnimStateFull( int iStartLine );
virtual void DebugShowAnimState( int iStartLine );
void AnimStatePrintf( int iLine, PRINTF_FORMAT_STRING const char *pMsg, ... );
void AnimStateLog( PRINTF_FORMAT_STRING const char *pMsg, ... );
void AnimStatePrintf( int iLine, const char *pMsg, ... );
void AnimStateLog( const char *pMsg, ... );
// Calculate the playback rate for movement layer
virtual float CalcMovementPlaybackRate( bool *bIsMoving );
@@ -162,13 +162,15 @@ public:
void RestartMainSequence();
virtual float GetFeetYawRate( void );
// Helpers for the derived classes to use.
protected:
// Sets up the string you specify, looks for that sequence and returns the index.
// Complains in the console and returns 0 if it can't find it.
virtual int CalcSequenceIndex( PRINTF_FORMAT_STRING const char *pBaseName, ... );
virtual int CalcSequenceIndex( const char *pBaseName, ... );
Activity GetCurrentMainSequenceActivity() const;
@@ -180,18 +182,21 @@ protected:
float GetEyeYaw() const { return m_flEyeYaw; }
void SetOuterPoseParameter( int iParam, float flValue );
protected:
CModAnimConfig m_AnimConfig;
CBaseAnimatingOverlay *m_pOuter;
protected:
int ConvergeAngles( float goal,float maxrate, float maxgap, float dt, float& current );
virtual int ConvergeAngles( float goal,float maxrate, float maxgap, float dt, float& current );
virtual void ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr );
virtual void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr );
virtual void ComputePoseParam_BodyYaw();
virtual void ResetGroundSpeed( void );
virtual bool ShouldResetGroundSpeed( Activity oldActivity, Activity idealActivity );
protected:
// The player's eye yaw and pitch angles.
@@ -219,6 +224,8 @@ protected:
QAngle m_angRender;
Vector2D m_vLastMovePose;
private:
// Update the prone state machine.
@@ -229,11 +236,9 @@ private:
Activity BodyYawTranslateActivity( Activity activity );
void SetOuterPoseParameter( int iParam, float flValue );
void EstimateYaw();
virtual bool ShouldResetMainSequence( int iCurrentSequence, int iNewSequence );
void ComputeMainSequence();
void ComputeAimSequence();
@@ -258,8 +263,6 @@ private:
float m_flGaitYaw;
float m_flStoredCycle;
Vector2D m_vLastMovePose;
void UpdateAimSequenceLayers(
float flCycle,
int iFirstLayer,
+194 -162
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
@@ -9,23 +9,22 @@
#include "icommandline.h"
#ifdef CLIENT_DLL
#include "tier3/tier3.h"
#include "vgui/ILocalize.h"
#include "vgui/ilocalize.h"
#include "achievement_notification_panel.h"
#include "fmtstr.h"
#include "gamestats.h"
#include "cdll_client_int.h"
#endif // CLIENT_DLL
//=============================================================================
// HPE_BEGIN
// [dwenger] Necessary for sorting achievements by award time
//=============================================================================
#ifdef INFESTED_DLL
#include "asw_gamerules.h"
#endif
#include <vgui/ISystem.h>
#include "vgui_controls/Controls.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
int g_nAchivementBitchCount = 0;
//=============================================================================
// HPE_END
//=============================================================================
CBaseAchievementHelper *CBaseAchievementHelper::s_pFirst = NULL;
@@ -65,14 +64,8 @@ CBaseAchievement::CBaseAchievement()
m_iCount = 0;
m_iProgressShown = 0;
m_bAchieved = false;
m_uUnlockTime = 0;
m_pAchievementMgr = NULL;
m_bShowOnHUD = false;
m_pszStat = NULL;
}
CBaseAchievement::~CBaseAchievement()
{
m_nUserSlot = 0;
}
//-----------------------------------------------------------------------------
@@ -91,9 +84,16 @@ void CBaseAchievement::SetFlags( int iFlags )
//-----------------------------------------------------------------------------
void CBaseAchievement::FireGameEvent( IGameEvent *event )
{
// perform common filtering to make it simpler to write achievements
#ifdef CLIENT_DLL
ACTIVE_SPLITSCREEN_PLAYER_GUARD( m_nUserSlot );
#endif
//
// Perform common filtering to make it simpler to write achievements
//
if ( !IsActive() )
{
return;
}
// if the achievement only applies to a specific map, and it's not the current map, skip it
if ( m_pMapNameFilter && ( 0 != Q_strcmp( m_pAchievementMgr->GetMapName(), m_pMapNameFilter ) ) )
@@ -188,42 +188,47 @@ void CBaseAchievement::Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pA
return;
// default implementation is just to increase count when filter criteria pass
// Msg( "Base achievement incremented on kill event.\n" );
IncrementCount();
}
//-----------------------------------------------------------------------------
// Purpose: called when an event that counts toward an achievement occurs
//-----------------------------------------------------------------------------
void CBaseAchievement::IncrementCount( int iOptIncrement )
void CBaseAchievement::IncrementCount()
{
if ( !IsAchieved() && LocalPlayerCanEarn() )
#ifdef INFESTED_DLL
#ifndef _DEBUG
// No incrementing if they cheated!
if ( ASWGameRules() && ASWGameRules()->m_bCheated )
{
if ( !AlwaysEnabled() && !m_pAchievementMgr->CheckAchievementsEnabled() )
if ( g_nAchivementBitchCount++ < 10 )
{
Msg( "Achievements disabled, ignoring achievement progress for %s\n", GetName() );
DevMsg( "Achievements can't be earned if SV_CHEATS was used in this mission!\n", GetName() );
}
return;
}
#endif
#endif
if ( !IsAchieved() )
{
if ( !m_pAchievementMgr->CheckAchievementsEnabled() )
{
#ifndef _DEBUG
if ( g_nAchivementBitchCount++ < 10 )
{
DevMsg( "Achievements disabled, ignoring achievement progress for %s\n", GetName() );
}
#endif
return;
}
// on client, where the count is kept, increment count
if ( iOptIncrement > 0 )
{
// user specified that we want to increase by more than one.
m_iCount += iOptIncrement;
if ( m_iCount > m_iGoal )
{
m_iCount = m_iGoal;
}
}
else
{
m_iCount++;
}
m_iCount++;
// if this achievement gets saved w/global state, flag our global state as dirty
if ( GetFlags() & ACH_SAVE_GLOBAL )
{
m_pAchievementMgr->SetDirty( true );
m_pAchievementMgr->SetDirty( true, m_nUserSlot );
}
if ( cc_achievement_debug.GetInt() )
@@ -231,22 +236,48 @@ void CBaseAchievement::IncrementCount( int iOptIncrement )
Msg( "Achievement count increased for %s: %d/%d\n", GetName(), m_iCount, m_iGoal );
}
#ifndef DISABLE_STEAM
#if !defined( NO_STEAM )
// if this achievement's progress should be stored in Steam, set the steam stat for it
if ( StoreProgressInSteam() && steamapicontext->SteamUserStats() )
{
// Set the Steam stat with the same name as the achievement. Only cached locally until we upload it.
char pszProgressName[1024];
Q_snprintf( pszProgressName, 1024, "%s_STAT", GetStat() );
Q_snprintf( pszProgressName, 1024, "%s_STAT", GetName() );
bool bRet = steamapicontext->SteamUserStats()->SetStat( pszProgressName, m_iCount );
if ( !bRet )
{
DevMsg( "ISteamUserStats::GetStat failed to set progress value in Steam for achievement %s\n", pszProgressName );
}
m_pAchievementMgr->SetDirty( true );
if ( HasComponents() )
{
Q_snprintf( pszProgressName, 1024, "%s_COMP", GetName() );
int32 bits = (int32) GetComponentBits();
bool bRet = steamapicontext->SteamUserStats()->SetStat( pszProgressName, bits );
if ( !bRet )
{
DevMsg( "ISteamUserStats::GetStat failed to set component value in Steam for achievement %s\n", pszProgressName );
}
}
// Upload user data to commit the change to Steam so if the client crashes, progress isn't lost.
// Only upload if we haven't uploaded recently, to keep us from spamming Steam with uploads. If we don't
// upload now, it will get uploaded no later than level shutdown.
#ifdef INFESTED_DLL
if ( ( m_pAchievementMgr->GetTimeLastUpload() == 0 ) || ( Plat_FloatTime() - m_pAchievementMgr->GetTimeLastUpload() > 60 * 15 )
|| ( ASWGameRules() && ASWGameRules()->GetGameState() != ASW_GS_INGAME && ( Plat_FloatTime() - m_pAchievementMgr->GetTimeLastUpload() > 0 ) ) ) // allow achievements to update each second if in the briefing/debrief
{
m_pAchievementMgr->UploadUserData( m_nUserSlot );
}
#else
if ( ( m_pAchievementMgr->GetTimeLastUpload() == 0 ) || ( Plat_FloatTime() - m_pAchievementMgr->GetTimeLastUpload() > 60 * 15 ) )
{
m_pAchievementMgr->UploadUserData( m_nUserSlot );
}
#endif
}
#endif
// if we've hit goal, award the achievement
if ( m_iGoal > 0 )
{
@@ -255,38 +286,29 @@ void CBaseAchievement::IncrementCount( int iOptIncrement )
AwardAchievement();
}
else
{
{
HandleProgressUpdate();
}
}
}
}
void CBaseAchievement::SetShowOnHUD( bool bShow )
{
if ( m_bShowOnHUD != bShow )
{
m_pAchievementMgr->SetDirty( true );
}
m_bShowOnHUD = bShow;
}
void CBaseAchievement::HandleProgressUpdate()
{
// which notification is this
int iProgress = -1;
if( m_iProgressMsgIncrement > 0 ) iProgress = m_iCount / m_iProgressMsgIncrement;
// if we haven't already shown this progress step, show it
if ( iProgress > m_iProgressShown || m_iCount == 1 )
// if we've hit the right # of progress steps to show a progress notification, show it
if ( ( m_iProgressMsgIncrement > 0 ) && m_iCount >= m_iProgressMsgMinimum && ( 0 == ( m_iCount % m_iProgressMsgIncrement ) ) )
{
ShowProgressNotification();
// remember progress step shown so we don't show it again if the player loads an earlier save game
// and gets past this point again
m_iProgressShown = iProgress;
m_pAchievementMgr->SetDirty( true );
// which notification is this
int iProgress = m_iCount / m_iProgressMsgIncrement;
// if we haven't already shown this progress step, show it
if ( iProgress > m_iProgressShown )
{
ShowProgressNotification();
// remember progress step shown so we don't show it again if the player loads an earlier save game
// and gets past this point again
m_iProgressShown = iProgress;
m_pAchievementMgr->SetDirty( true, m_nUserSlot );
}
}
}
@@ -320,22 +342,6 @@ void CBaseAchievement::CalcProgressMsgIncrement()
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseAchievement::SetNextThink( float flThinkTime )
{
m_pAchievementMgr->SetAchievementThink( this, flThinkTime );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseAchievement::ClearThink( void )
{
m_pAchievementMgr->SetAchievementThink( this, THINK_CLEAR );
}
//-----------------------------------------------------------------------------
// Purpose: see if we should award an achievement based on what just happened
//-----------------------------------------------------------------------------
@@ -377,12 +383,25 @@ void CBaseAchievement::OnMapEvent( const char *pEventName )
//-----------------------------------------------------------------------------
void CBaseAchievement::AwardAchievement()
{
#ifdef INFESTED_DLL
#ifndef _DEBUG
// No awarding if they cheated!
if ( ASWGameRules() && ASWGameRules()->m_bCheated )
{
if ( g_nAchivementBitchCount++ < 10 )
{
DevMsg( "Achievements can't be earned if SV_CHEATS was used in this mission!\n", GetName() );
}
return;
}
#endif
#endif
Assert( !IsAchieved() );
if ( IsAchieved() )
return;
ShowProgressNotification();
m_pAchievementMgr->AwardAchievement( m_iAchievementID );
m_pAchievementMgr->AwardAchievement( m_iAchievementID, m_nUserSlot );
}
//-----------------------------------------------------------------------------
@@ -407,6 +426,20 @@ void CBaseAchievement::OnComponentEvent( const char *pchComponentName )
//-----------------------------------------------------------------------------
void CBaseAchievement::EnsureComponentBitSetAndEvaluate( int iBitNumber )
{
#ifdef INFESTED_DLL
#ifndef _DEBUG
// No incrementing if they cheated!
if ( ASWGameRules() && ASWGameRules()->m_bCheated )
{
if ( g_nAchivementBitchCount++ < 10 )
{
DevMsg( "Achievements can't be earned if SV_CHEATS was used in this mission!\n", GetName() );
}
return;
}
#endif
#endif
Assert( iBitNumber < 64 ); // this is bit #, not a bit mask
if ( IsAchieved() )
@@ -418,7 +451,7 @@ void CBaseAchievement::EnsureComponentBitSetAndEvaluate( int iBitNumber )
// see if we already have gotten this component
if ( 0 == ( iBitMask & m_iComponentBits ) )
{
if ( !AlwaysEnabled() && !m_pAchievementMgr->CheckAchievementsEnabled() )
if ( !m_pAchievementMgr->CheckAchievementsEnabled() )
{
Msg( "Achievements disabled, ignoring achievement component for %s\n", GetName() );
return;
@@ -426,10 +459,51 @@ void CBaseAchievement::EnsureComponentBitSetAndEvaluate( int iBitNumber )
// new component, set the bit and increment the count
SetComponentBits( m_iComponentBits | iBitMask );
if ( m_iCount != m_iGoal )
#if !defined( NO_STEAM )
// if this achievement's progress should be stored in Steam, set the steam stat for it
if ( StoreProgressInSteam() && steamapicontext->SteamUserStats() )
{
// Set the Steam stat with the same name as the achievement. Only cached locally until we upload it.
char pszProgressName[1024];
Q_snprintf( pszProgressName, 1024, "%s_STAT", GetName() );
bool bRet = steamapicontext->SteamUserStats()->SetStat( pszProgressName, m_iCount );
if ( !bRet )
{
DevMsg( "ISteamUserStats::GetStat failed to set progress value in Steam for achievement %s\n", pszProgressName );
}
if ( HasComponents() )
{
Q_snprintf( pszProgressName, 1024, "%s_COMP", GetName() );
int32 bits = (int32) GetComponentBits();
bool bRet = steamapicontext->SteamUserStats()->SetStat( pszProgressName, bits );
if ( !bRet )
{
DevMsg( "ISteamUserStats::GetStat failed to set component value in Steam for achievement %s\n", pszProgressName );
}
}
// Upload user data to commit the change to Steam so if the client crashes, progress isn't lost.
// Only upload if we haven't uploaded recently, to keep us from spamming Steam with uploads. If we don't
// upload now, it will get uploaded no later than level shutdown.
if ( ( m_pAchievementMgr->GetTimeLastUpload() == 0 ) || ( Plat_FloatTime() - m_pAchievementMgr->GetTimeLastUpload() > 60 * 15 ) )
{
m_pAchievementMgr->UploadUserData( m_nUserSlot );
}
}
#endif
Assert( m_iCount <= m_iGoal );
if ( m_iCount == m_iGoal )
{
// all components found, award the achievement (and save state)
AwardAchievement();
}
else
{
// save our state at the next good opportunity
m_pAchievementMgr->SetDirty( true );
m_pAchievementMgr->SetDirty( true, m_nUserSlot );
if ( cc_achievement_debug.GetInt() )
{
@@ -437,7 +511,7 @@ void CBaseAchievement::EnsureComponentBitSetAndEvaluate( int iBitNumber )
}
ShowProgressNotification();
}
}
}
else
{
@@ -446,15 +520,6 @@ void CBaseAchievement::EnsureComponentBitSetAndEvaluate( int iBitNumber )
Msg( "Component %d for achievement %s found, but already had that component\n", iBitNumber, GetName() );
}
}
// Check to see if we've achieved our goal even if the bit is already set
// (this fixes some older achievements that are stuck in the 9/9 state and could never be evaluated)
Assert( m_iCount <= m_iGoal );
if ( m_iCount == m_iGoal )
{
// all components found, award the achievement (and save state)
AwardAchievement();
}
}
//-----------------------------------------------------------------------------
@@ -507,17 +572,9 @@ void CBaseAchievement::SetComponentBits( uint64 iComponentBits )
Assert( m_iFlags & ACH_HAS_COMPONENTS );
// set the bit field
m_iComponentBits = iComponentBits;
// count how many bits are set and save that as the count
int iNumBitsSet = 0;
while ( iComponentBits > 0 )
{
if ( iComponentBits & 1 )
{
iNumBitsSet++;
}
iComponentBits >>= 1;
}
m_iCount = iNumBitsSet;
m_iCount = UTIL_CountNumBitsSet( iComponentBits );
}
//-----------------------------------------------------------------------------
@@ -535,8 +592,8 @@ bool CBaseAchievement::ShouldSaveWithGame()
//-----------------------------------------------------------------------------
bool CBaseAchievement::ShouldSaveGlobal()
{
// save if we should get saved globally and have a non-zero count, or if we have been achieved, or if the player has pinned this achievement to the HUD
return ( ( ( m_iFlags & ACH_SAVE_GLOBAL ) > 0 && ( GetCount() > 0 ) ) || IsAchieved() || ( m_iProgressShown > 0 ) || ShouldShowOnHUD() );
// save if we should get saved globally and have a non-zero count, or if we have been achieved
return ( ( ( m_iFlags & ACH_SAVE_GLOBAL ) > 0 && ( GetCount() > 0 ) ) || IsAchieved() || ( m_iProgressShown > 0 ) );
}
//-----------------------------------------------------------------------------
@@ -555,64 +612,19 @@ bool CBaseAchievement::IsActive()
return true;
}
//=============================================================================
// HPE_BEGIN:
// [pfreese] Moved serialization from AchievementMgr to here so that derived
// classes can persist additional data
//=============================================================================
//-----------------------------------------------------------------------------
// Purpose: Serialize our data to the KeyValues node
// Purpose: Clears achievement data
//-----------------------------------------------------------------------------
void CBaseAchievement::GetSettings( KeyValues *pNodeOut )
void CBaseAchievement::ClearAchievementData()
{
pNodeOut->SetInt( "value", IsAchieved() ? 1 : 0 );
if ( HasComponents() )
SetCount( 0 );
if ( this->HasComponents() )
{
pNodeOut->SetUint64( "data", m_iComponentBits );
this->SetComponentBits( 0 );
}
else
{
if ( !IsAchieved() )
{
pNodeOut->SetInt( "data", m_iCount );
}
}
pNodeOut->SetInt( "hud", ShouldShowOnHUD() ? 1 : 0 );
pNodeOut->SetInt( "msg", m_iProgressShown );
SetAchieved( false );
}
//-----------------------------------------------------------------------------
// Purpose: Unserialize our data from the KeyValues node
//-----------------------------------------------------------------------------
void CBaseAchievement::ApplySettings( KeyValues *pNodeIn )
{
// set the count
if ( pNodeIn->GetInt( "value" ) > 0 )
{
m_iCount = m_iGoal;
m_bAchieved = true;
}
else if ( !HasComponents() )
{
m_iCount = pNodeIn->GetInt( "data" );
}
// if this achievement has components, set the component bits
if ( HasComponents() )
{
int64 iComponentBits = pNodeIn->GetUint64( "data" );
SetComponentBits( iComponentBits );
}
SetShowOnHUD( !!pNodeIn->GetInt( "hud" ) );
m_iProgressShown = pNodeIn->GetInt( "msg" );
}
//=============================================================================
// HPE_END
//=============================================================================
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
@@ -738,8 +750,28 @@ void CAchievement_AchievedCount::Init()
// Count how many achievements have been earned in our range
void CAchievement_AchievedCount::OnSteamUserStatsStored( void )
{
// DO NO CALL. REPLACED BY CHECKMETAACHIEVEMENTS!
Assert( 0 );
int iAllAchievements = m_pAchievementMgr->GetAchievementCount();
int iAchieved = 0;
for ( int i=0; i<iAllAchievements; ++i )
{
IAchievement* pCurAchievement = (IAchievement*)m_pAchievementMgr->GetAchievementByIndex( i, STEAM_PLAYER_SLOT );
Assert ( pCurAchievement );
int iAchievementID = pCurAchievement->GetAchievementID();
if ( iAchievementID < m_iLowRange || iAchievementID > m_iHighRange )
continue;
if ( pCurAchievement->IsAchieved() )
{
iAchieved++;
}
}
if ( iAchieved >= m_iNumRequired )
{
IncrementCount();
}
}
void CAchievement_AchievedCount::SetAchievementsRequired( int iNumRequired, int iLowRange, int iHighRange )
+17 -53
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
@@ -11,7 +11,7 @@
#endif
#include "GameEventListener.h"
#include "hl2orange.spa.h"
//#include "hl2orange.spa.h"
#include "iachievementmgr.h"
class CAchievementMgr;
@@ -25,7 +25,6 @@ class CBaseAchievement : public CGameEventListener, public IAchievement
DECLARE_CLASS_NOBASE( CBaseAchievement );
public:
CBaseAchievement();
virtual ~CBaseAchievement();
virtual void Init() {}
virtual void ListenForEvents() {};
virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event );
@@ -34,7 +33,6 @@ public:
void SetAchievementID( int iAchievementID ) { m_iAchievementID = iAchievementID; }
void SetName( const char *pszName ) { m_pszName = pszName; }
const char *GetName() { return m_pszName; }
const char *GetStat() { return m_pszStat?m_pszStat:GetName(); }
void SetFlags( int iFlags );
int GetFlags() { return m_iFlags; }
void SetGoal( int iGoal ) { m_iGoal = iGoal; }
@@ -60,25 +58,7 @@ public:
int GetProgressShown() { return m_iProgressShown; }
virtual bool IsAchieved() { return m_bAchieved; }
virtual bool IsActive();
virtual bool LocalPlayerCanEarn( void ) { return true; }
void SetAchieved( bool bAchieved ) { m_bAchieved = bAchieved; }
virtual bool IsMetaAchievement() { return false; }
virtual bool AlwaysListen() { return false; }
virtual bool AlwaysEnabled() { return false; }
//=============================================================================
// HPE_BEGIN:
// [pfreese] Notification method for derived classes
//=============================================================================
virtual void OnAchieved() {}
uint32 GetUnlockTime() const { return m_uUnlockTime; }
void SetUnlockTime( uint32 unlockTime ) { m_uUnlockTime = unlockTime; }
//=============================================================================
// HPE_END
//=============================================================================
uint64 GetComponentBits() { return m_iComponentBits; }
void SetComponentBits( uint64 iComponentBits );
void OnComponentEvent( const char *pchComponentName );
@@ -88,25 +68,14 @@ public:
virtual void PrintAdditionalStatus() {} // for debugging, achievements may report additional status in achievement_status concmd
virtual void OnSteamUserStatsStored() {}
virtual void UpdateAchievement( int nData ) {}
virtual bool ShouldShowOnHUD() { return m_bShowOnHUD; }
virtual void SetShowOnHUD( bool bShow );
virtual void SetUserSlot( int nUserSlot ) { m_nUserSlot = nUserSlot; }
virtual void ClearAchievementData();
virtual const char *GetIconPath() { return NULL; }
void SetDisplayOrder( int iDisplayOrder ) { m_iDisplayOrder = iDisplayOrder; }
int GetDisplayOrder( ) { return m_iDisplayOrder; }
//=============================================================================
// HPE_BEGIN:
// [pfreese] Serialization methods
//=============================================================================
virtual void GetSettings( KeyValues* pNodeOut ); // serialize
virtual void ApplySettings( /* const */ KeyValues* pNodeIn ); // unserialize
//=============================================================================
// HPE_END
//=============================================================================
virtual void Think( void ) { return; }
const char *GetMapNameFilter( void ){ return m_pMapNameFilter; }
CAchievementMgr *GetAchievementMgr( void ){ return m_pAchievementMgr; }
virtual void ReadProgress( IPlayerLocal *pPlayer ) {}
virtual bool WriteProgress( IPlayerLocal *pPlayer ) { return false; }
protected:
virtual void FireGameEvent( IGameEvent *event );
@@ -117,18 +86,14 @@ protected:
void SetInflictorEntityNameFilter( const char *pEntityName );
void SetMapNameFilter( const char *pMapName );
void SetComponentPrefix( const char *pPrefix );
void IncrementCount( int iOptIncrement = 0 );
void IncrementCount();
void EvaluateNewAchievement();
void AwardAchievement();
void ShowProgressNotification();
void HandleProgressUpdate();
virtual void CalcProgressMsgIncrement();
void SetNextThink( float flThinkTime );
void ClearThink( void );
void SetStat( const char* pStatName ) { m_pszStat = pStatName; }
const char *m_pszName; // name of this achievement
const char *m_pszStat; // stat this achievement uses
int m_iAchievementID; // ID of this achievement
int m_iFlags; // ACH_* flags for this achievement
int m_iGoal; // goal # of steps to award this achievement
@@ -149,12 +114,12 @@ protected:
const char *m_pszComponentPrefix;
int m_iComponentPrefixLen;
bool m_bAchieved; // is this achievement achieved
uint32 m_uUnlockTime; // time_t that this achievement was unlocked (0 if before Steamworks unlock time support)
int m_iCount; // # of steps satisfied toward this achievement (only valid if not achieved)
int m_iProgressShown; // # of progress msgs we've shown
uint64 m_iComponentBits; // bitfield of components achieved
CAchievementMgr *m_pAchievementMgr; // our achievement manager
bool m_bShowOnHUD; // if set, the player wants this achievement pinned to the HUD
int m_nUserSlot;
int m_iDisplayOrder; // Order in which the achievement is displayed in the UI
friend class CAchievementMgr;
public:
@@ -207,11 +172,6 @@ class CAchievement_AchievedCount : public CBaseAchievement
public:
void Init();
virtual void OnSteamUserStatsStored( void );
virtual bool IsMetaAchievement() { return true; }
int GetLowRange() { return m_iLowRange; }
int GetHighRange() { return m_iHighRange; }
int GetNumRequired() { return m_iNumRequired; }
protected:
void SetAchievementsRequired( int iNumRequired, int iLowRange, int iHighRange );
@@ -241,7 +201,7 @@ public:
static CBaseAchievementHelper *s_pFirst;
};
#define DECLARE_ACHIEVEMENT_( className, achievementID, achievementName, gameDirFilter, iPointValue, bHidden ) \
#define DECLARE_ACHIEVEMENT_( className, achievementID, achievementName, gameDirFilter, iPointValue, bHidden, iDisplayOrder ) \
static CBaseAchievement *Create_##className( void ) \
{ \
CBaseAchievement *pAchievement = new className( ); \
@@ -249,6 +209,7 @@ static CBaseAchievement *Create_##className( void ) \
pAchievement->SetName( achievementName ); \
pAchievement->SetPointValue( iPointValue ); \
pAchievement->SetHideUntilAchieved( bHidden ); \
pAchievement->SetDisplayOrder( iDisplayOrder ); \
if ( gameDirFilter ) pAchievement->SetGameDirFilter( gameDirFilter ); \
return pAchievement; \
}; \
@@ -257,6 +218,9 @@ static CBaseAchievementHelper g_##className##_Helper( Create_##className );
#define DECLARE_ACHIEVEMENT( className, achievementID, achievementName, iPointValue ) \
DECLARE_ACHIEVEMENT_( className, achievementID, achievementName, NULL, iPointValue, false )
#define DECLARE_ACHIEVEMENT_ORDER( className, achievementID, achievementName, iPointValue, iDisplayOrder ) \
DECLARE_ACHIEVEMENT_( className, achievementID, achievementName, NULL, iPointValue, false, iDisplayOrder )
#define DECLARE_MAP_EVENT_ACHIEVEMENT_( achievementID, achievementName, gameDirFilter, iPointValue, bHidden ) \
class CAchievement##achievementID : public CMapAchievement {}; \
DECLARE_ACHIEVEMENT_( CAchievement##achievementID, achievementID, achievementName, gameDirFilter, iPointValue, bHidden ) \
+69 -130
View File
@@ -1,17 +1,19 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
//===========================================================================//
#include "cbase.h"
#include "ammodef.h"
#include "tier0/vprof.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Switches to the best weapon that is also better than the given weapon.
// Input : pCurrent - The current weapon used by the player.
@@ -33,7 +35,7 @@ bool CBaseCombatCharacter::SwitchToNextBestWeapon(CBaseCombatWeapon *pCurrent)
//-----------------------------------------------------------------------------
// Purpose: Switches to the given weapon (providing it has ammo)
// Input :
// Output : true is switch succeeded
// Output : true is switch suceeded
//-----------------------------------------------------------------------------
bool CBaseCombatCharacter::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex /*=0*/ )
{
@@ -43,7 +45,7 @@ bool CBaseCombatCharacter::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmo
// Already have it out?
if ( m_hActiveWeapon.Get() == pWeapon )
{
if ( !m_hActiveWeapon->IsWeaponVisible() || m_hActiveWeapon->IsHolstered() )
if ( !m_hActiveWeapon->IsWeaponVisible() )
return m_hActiveWeapon->Deploy( );
return false;
}
@@ -60,7 +62,6 @@ bool CBaseCombatCharacter::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmo
}
m_hActiveWeapon = pWeapon;
return pWeapon->Deploy( );
}
@@ -106,6 +107,16 @@ CBaseCombatWeapon *CBaseCombatCharacter::GetActiveWeapon() const
return m_hActiveWeapon;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : i -
//-----------------------------------------------------------------------------
CBaseCombatWeapon *CBaseCombatCharacter::GetWeapon( int i ) const
{
Assert( (i >= 0) && (i < MAX_WEAPONS) );
return m_hMyWeapons[i].Get();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : iCount -
@@ -116,8 +127,11 @@ void CBaseCombatCharacter::RemoveAmmo( int iCount, int iAmmoIndex )
if (iCount <= 0)
return;
if ( iAmmoIndex < 0 )
return;
// Infinite ammo?
if ( GetAmmoDef()->MaxCarry( iAmmoIndex ) == INFINITE_AMMO )
if ( GetAmmoDef()->CanCarryInfiniteAmmo( iAmmoIndex ) )
return;
// Ammo pickup sound
@@ -161,7 +175,7 @@ int CBaseCombatCharacter::GetAmmoCount( int iAmmoIndex ) const
return 0;
// Infinite ammo?
if ( GetAmmoDef()->MaxCarry( iAmmoIndex ) == INFINITE_AMMO )
if ( GetAmmoDef()->CanCarryInfiniteAmmo( iAmmoIndex ) )
return 999;
return m_iAmmo[ iAmmoIndex ];
@@ -180,19 +194,38 @@ int CBaseCombatCharacter::GetAmmoCount( char *szName ) const
//-----------------------------------------------------------------------------
CBaseCombatWeapon* CBaseCombatCharacter::Weapon_OwnsThisType( const char *pszWeapon, int iSubType ) const
{
// Check for duplicates
for (int i=0;i<MAX_WEAPONS;i++)
for ( int i = 0; i < MAX_WEAPONS; i++ )
{
if ( m_hMyWeapons[i].Get() && FClassnameIs( m_hMyWeapons[i], pszWeapon ) )
{
// Make sure it matches the subtype
if ( m_hMyWeapons[i]->GetSubType() == iSubType )
{
return m_hMyWeapons[i];
}
}
}
return NULL;
}
int CBaseCombatCharacter::Weapon_GetSlot( const char *pszWeapon, int iSubType ) const
{
for ( int i = 0; i < MAX_WEAPONS; i++ )
{
if ( m_hMyWeapons[i].Get() && FClassnameIs( m_hMyWeapons[i], pszWeapon ) )
{
// Make sure it matches the subtype
if ( m_hMyWeapons[i]->GetSubType() == iSubType )
{
return i;
}
}
}
return -1;
}
int CBaseCombatCharacter::BloodColor()
{
@@ -210,9 +243,9 @@ void CBaseCombatCharacter::SetBloodColor( int nBloodColor )
//-----------------------------------------------------------------------------
/**
The main visibility check. Checks all the entity specific reasons that could
make IsVisible fail. Then checks points in space to get environmental reasons.
This is LOS, plus invisibility and fog and smoke and such.
The main visibility check. Checks all the entity specific reasons that could
make IsVisible fail. Then checks points in space to get environmental reasons.
This is LOS, plus invisibility and fog and smoke and such.
*/
enum VisCacheResult_t
@@ -327,7 +360,7 @@ VisCacheResult_t CCombatCharVisCache::HasVisibility( int iCache ) const
{
if ( iCache == VIS_CACHE_INVALID )
return VISCACHE_UNKNOWN;
m_nTestCount++;
bool bReverse = ( iCache < 0 );
@@ -373,6 +406,10 @@ void CCombatCharVisCache::RegisterVisibility( int iCache, bool bEntity1CanSeeEnt
static CCombatCharVisCache s_CombatCharVisCache;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBaseCombatCharacter::IsAbleToSee( const CBaseEntity *pEntity, FieldOfViewCheckType checkFOV )
{
CBaseCombatCharacter *pBCC = const_cast<CBaseEntity *>( pEntity )->MyCombatCharacterPointer();
@@ -396,32 +433,14 @@ bool CBaseCombatCharacter::IsAbleToSee( const CBaseEntity *pEntity, FieldOfViewC
if ( !ComputeLOS( vecEyePosition, vecTargetPosition ) )
return false;
#if defined(GAME_DLL) && defined(TERROR)
if ( flDistToOther > NavObscureRange.GetFloat() )
{
const float flMaxDistance = 100.0f;
TerrorNavArea *pTargetArea = static_cast< TerrorNavArea* >( TheNavMesh->GetNearestNavArea( vecTargetPosition, false, flMaxDistance ) );
if ( !pTargetArea || pTargetArea->HasSpawnAttributes( TerrorNavArea::SPAWN_OBSCURED ) )
return false;
if ( ComputeTargetIsInDarkness( vecEyePosition, pTargetArea, vecTargetPosition ) )
return false;
}
#endif
return ( checkFOV != USE_FOV || IsInFieldOfView( vecTargetPosition ) );
}
static void ComputeSeeTestPosition( Vector *pEyePosition, CBaseCombatCharacter *pBCC )
{
#if defined(GAME_DLL) && defined(TERROR)
if ( pBCC->IsPlayer() )
{
CTerrorPlayer *pPlayer = ToTerrorPlayer( pBCC );
*pEyePosition = !pPlayer->IsDead() ? pPlayer->EyePosition() : pPlayer->GetDeathPosition();
}
else
#endif
{
*pEyePosition = pBCC->EyePosition();
}
@@ -443,16 +462,7 @@ bool CBaseCombatCharacter::IsAbleToSee( CBaseCombatCharacter *pBCC, FieldOfViewC
if ( IsHiddenByFog( flDistToOther ) )
return false;
#ifdef TERROR
// Check this every time also, it's cheap; check to see if the enemy is in an obscured area.
bool bIsInNavObscureRange = ( flDistToOther > NavObscureRange.GetFloat() );
if ( bIsInNavObscureRange )
{
TerrorNavArea *pOtherNavArea = static_cast< TerrorNavArea* >( pBCC->GetLastKnownArea() );
if ( !pOtherNavArea || pOtherNavArea->HasSpawnAttributes( TerrorNavArea::SPAWN_OBSCURED ) )
return false;
}
#endif // TERROR
#endif
// Check if we have a cached-off visibility
@@ -465,19 +475,9 @@ bool CBaseCombatCharacter::IsAbleToSee( CBaseCombatCharacter *pBCC, FieldOfViewC
bool bThisCanSeeOther = false, bOtherCanSeeThis = false;
if ( ComputeLOS( vecEyePosition, vecOtherEyePosition ) )
{
#if defined(GAME_DLL) && defined(TERROR)
if ( !bIsInNavObscureRange )
{
bThisCanSeeOther = true, bOtherCanSeeThis = true;
}
else
{
bThisCanSeeOther = !ComputeTargetIsInDarkness( vecEyePosition, pBCC->GetLastKnownArea(), vecOtherEyePosition );
bOtherCanSeeThis = !ComputeTargetIsInDarkness( vecOtherEyePosition, GetLastKnownArea(), vecEyePosition );
}
#else
bThisCanSeeOther = true, bOtherCanSeeThis = true;
#endif
}
s_CombatCharVisCache.RegisterVisibility( iCache, bThisCanSeeOther, bOtherCanSeeThis );
@@ -529,45 +529,13 @@ bool CBaseCombatCharacter::ComputeLOS( const Vector &vecEyePosition, const Vecto
return ( result.fraction == 1.0f );
}
#if defined(GAME_DLL) && defined(TERROR)
bool CBaseCombatCharacter::ComputeTargetIsInDarkness( const Vector &vecEyePosition, CNavArea *pTargetNavArea, const Vector &vecTargetPos ) const
{
if ( GetTeamNumber() != TEAM_SURVIVOR )
return false;
// Check light info
const float flMinLightIntensity = 0.1f;
if ( !pTargetNavArea || ( pTargetNavArea->GetLightIntensity() >= flMinLightIntensity ) )
return false;
CTraceFilterNoNPCsOrPlayer lightingFilter( this, COLLISION_GROUP_NONE );
Vector vecSightDirection;
VectorSubtract( vecTargetPos, vecEyePosition, vecSightDirection );
VectorNormalize( vecSightDirection );
trace_t result;
UTIL_TraceLine( vecTargetPos, vecTargetPos + vecSightDirection * 32768.0f, MASK_L4D_VISION, &lightingFilter, &result );
if ( ( result.fraction < 1.0f ) && ( ( result.surface.flags & SURF_SKY ) == 0 ) )
{
const float flMaxDistance = 100.0f;
TerrorNavArea *pFarArea = (TerrorNavArea *)TheNavMesh->GetNearestNavArea( result.endpos, false, flMaxDistance );
// Target is in darkness, the wall behind him is too, and we are too far away
if ( pFarArea && pFarArea->GetLightIntensity() < flMinLightIntensity )
return true;
}
return false;
}
#endif
//-----------------------------------------------------------------------------
/**
Return true if our view direction is pointing at the given target,
within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
Return true if our view direction is pointing at the given target,
within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
*/
bool CBaseCombatCharacter::IsLookingTowards( const CBaseEntity *target, float cosTolerance ) const
{
@@ -577,8 +545,8 @@ bool CBaseCombatCharacter::IsLookingTowards( const CBaseEntity *target, float co
//-----------------------------------------------------------------------------
/**
Return true if our view direction is pointing at the given target,
within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
Return true if our view direction is pointing at the given target,
within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
*/
bool CBaseCombatCharacter::IsLookingTowards( const Vector &target, float cosTolerance ) const
{
@@ -594,13 +562,13 @@ bool CBaseCombatCharacter::IsLookingTowards( const Vector &target, float cosTole
//-----------------------------------------------------------------------------
/**
Returns true if we are looking towards something within a tolerence determined
by our field of view
Returns true if we are looking towards something within a tolerence determined
by our field of view
*/
bool CBaseCombatCharacter::IsInFieldOfView( CBaseEntity *entity ) const
{
CBasePlayer *pPlayer = ToBasePlayer( const_cast< CBaseCombatCharacter* >( this ) );
float flTolerance = pPlayer ? cos( (float)pPlayer->GetFOV() * 0.5f ) : BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE;
float flTolerance = pPlayer ? cos( DEG2RAD( pPlayer->GetFOV() * 0.5f ) ) : BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE;
Vector vecForward;
Vector vecEyePosition = EyePosition();
@@ -627,22 +595,22 @@ bool CBaseCombatCharacter::IsInFieldOfView( CBaseEntity *entity ) const
//-----------------------------------------------------------------------------
/**
Returns true if we are looking towards something within a tolerence determined
by our field of view
Returns true if we are looking towards something within a tolerence determined
by our field of view
*/
bool CBaseCombatCharacter::IsInFieldOfView( const Vector &pos ) const
{
CBasePlayer *pPlayer = ToBasePlayer( const_cast< CBaseCombatCharacter* >( this ) );
if ( pPlayer )
return IsLookingTowards( pos, cos( (float)pPlayer->GetFOV() * 0.5f ) );
return IsLookingTowards( pos, cos( DEG2RAD( pPlayer->GetFOV() * 0.5f ) ) );
return IsLookingTowards( pos );
}
//-----------------------------------------------------------------------------
/**
Strictly checks Line of Sight only.
Strictly checks Line of Sight only.
*/
bool CBaseCombatCharacter::IsLineOfSightClear( CBaseEntity *entity, LineOfSightCheckType checkType ) const
@@ -659,7 +627,7 @@ bool CBaseCombatCharacter::IsLineOfSightClear( CBaseEntity *entity, LineOfSightC
//-----------------------------------------------------------------------------
/**
Strictly checks Line of Sight only.
Strictly checks Line of Sight only.
*/
static bool TraceFilterNoCombatCharacters( IHandleEntity *pServerEntity, int contentsMask )
{
@@ -684,18 +652,13 @@ bool CBaseCombatCharacter::IsLineOfSightClear( const Vector &pos, LineOfSightChe
{
// use the query cache unless it causes problems
#if defined(GAME_DLL) && defined(TERROR)
return IsLineOfSightBetweenTwoEntitiesClear( const_cast<CBaseCombatCharacter *>(this), EOFFSET_MODE_EYEPOSITION,
entityToIgnore, EOFFSET_MODE_WORLDSPACE_CENTER,
entityToIgnore, COLLISION_GROUP_NONE,
MASK_L4D_VISION, TraceFilterNoCombatCharacters, 1.0 );
#else
trace_t trace;
CTraceFilterNoCombatCharacters traceFilter( entityToIgnore, COLLISION_GROUP_NONE );
UTIL_TraceLine( EyePosition(), pos, MASK_OPAQUE | CONTENTS_IGNORE_NODRAW_OPAQUE | CONTENTS_MONSTER, &traceFilter, &trace );
return trace.fraction == 1.0f;
#endif
}
else
{
@@ -706,27 +669,3 @@ bool CBaseCombatCharacter::IsLineOfSightClear( const Vector &pos, LineOfSightChe
return trace.fraction == 1.0f;
}
}
/*
//---------------------------------------------------------------------------------------------------------------------------
surfacedata_t * CBaseCombatCharacter::GetGroundSurface( void ) const
{
Vector start( vec3_origin );
Vector end( 0, 0, -64 );
Vector vecMins, vecMaxs;
CollisionProp()->WorldSpaceAABB( &vecMins, &vecMaxs );
Ray_t ray;
ray.Init( start, end, vecMins, vecMaxs );
trace_t trace;
UTIL_TraceRay( ray, MASK_SOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &trace );
if ( trace.fraction == 1.0f )
return NULL; // no ground
return physprops->GetSurfaceData( trace.surface.surfaceProps );
}
*/
+238 -380
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -11,18 +11,8 @@
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "physics_saverestore.h"
#include "datacache/imdlcache.h"
#include "activitylist.h"
// NVNT start extra includes
#include "haptics/haptic_utils.h"
#ifdef CLIENT_DLL
#include "prediction.h"
#endif
// NVNT end extra includes
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
#include "tf_shareddefs.h"
#endif
#include "tier0/vprof.h"
#include "collisionutils.h"
#if !defined( CLIENT_DLL )
@@ -32,10 +22,6 @@
#include "fmtstr.h"
#include "gameweaponmanager.h"
#ifdef HL2MP
#include "hl2mp_gamerules.h"
#endif
#endif
// memdbgon must be the last include file in a .cpp file!!!
@@ -51,16 +37,7 @@
extern bool UTIL_ItemCanBeTouchedByPlayer( CBaseEntity *pItem, CBasePlayer *pPlayer );
#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL )
#ifdef _DEBUG
ConVar tf_weapon_criticals_force_random( "tf_weapon_criticals_force_random", "0", FCVAR_REPLICATED | FCVAR_CHEAT );
#endif // _DEBUG
ConVar tf_weapon_criticals_bucket_cap( "tf_weapon_criticals_bucket_cap", "1000.0", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar tf_weapon_criticals_bucket_bottom( "tf_weapon_criticals_bucket_bottom", "-250.0", FCVAR_REPLICATED | FCVAR_CHEAT );
ConVar tf_weapon_criticals_bucket_default( "tf_weapon_criticals_bucket_default", "300.0", FCVAR_REPLICATED | FCVAR_CHEAT );
#endif // TF
CBaseCombatWeapon::CBaseCombatWeapon() : BASECOMBATWEAPON_DERIVED_FROM()
CBaseCombatWeapon::CBaseCombatWeapon()
{
// Constructor must call this
// CONSTRUCT_PREDICTABLE( CBaseCombatWeapon );
@@ -76,9 +53,6 @@ CBaseCombatWeapon::CBaseCombatWeapon() : BASECOMBATWEAPON_DERIVED_FROM()
// Defaults to zero
m_nViewModelIndex = 0;
m_bFlipViewModel = false;
m_iSubType = 0;
#if defined( CLIENT_DLL )
m_iState = m_iOldState = WEAPON_NOT_CARRIED;
m_iClip1 = -1;
@@ -94,15 +68,7 @@ CBaseCombatWeapon::CBaseCombatWeapon() : BASECOMBATWEAPON_DERIVED_FROM()
m_hWeaponFileInfo = GetInvalidWeaponInfoHandle();
#if defined( TF_DLL )
UseClientSideAnimation();
#endif
#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL )
m_flCritTokenBucket = tf_weapon_criticals_bucket_default.GetFloat();
m_nCritChecks = 1;
m_nCritSeedRequests = 0;
#endif // TF
}
//-----------------------------------------------------------------------------
@@ -137,12 +103,13 @@ void CBaseCombatWeapon::Activate( void )
#endif
}
void CBaseCombatWeapon::GiveDefaultAmmo( void )
{
// If I use clips, set my clips to the default
if ( UsesClipsForAmmo1() )
{
m_iClip1 = AutoFiresFullClip() ? 0 : GetDefaultClip1();
m_iClip1 = GetDefaultClip1();
}
else
{
@@ -167,8 +134,6 @@ void CBaseCombatWeapon::Spawn( void )
{
Precache();
BaseClass::Spawn();
SetSolid( SOLID_BBOX );
m_flNextEmptySoundTime = 0.0f;
@@ -176,17 +141,21 @@ void CBaseCombatWeapon::Spawn( void )
RemoveEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
m_iState = WEAPON_NOT_CARRIED;
SetGlobalFadeScale( 0.0f );
// Assume
m_nViewModelIndex = 0;
GiveDefaultAmmo();
if ( GetWorldModel() )
{
SetModel( GetWorldModel() );
}
SetModel( GetWorldModel() );
#if !defined( CLIENT_DLL )
if ( GetWpnData().szAIAddOn[ 0 ] != '\0' )
{
SetAIAddOn( AllocPooledString( GetWpnData().szAIAddOn ) );
}
if( IsX360() )
{
AddEffects( EF_ITEM_BLINK );
@@ -235,6 +204,7 @@ void CBaseCombatWeapon::Precache( void )
Assert( Q_strlen( GetClassname() ) > 0 );
// Msg( "Client got %s\n", GetClassname() );
#endif
m_iPrimaryAmmoType = m_iSecondaryAmmoType = -1;
// Add this weapon to the weapon registry, and get our index into it
@@ -249,16 +219,7 @@ void CBaseCombatWeapon::Precache( void )
{
Msg("ERROR: Weapon (%s) using undefined primary ammo type (%s)\n",GetClassname(), GetWpnData().szAmmo1);
}
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
// Ammo override
int iModUseMetalOverride = 0;
CALL_ATTRIB_HOOK_INT( iModUseMetalOverride, mod_use_metal_ammo_type );
if ( iModUseMetalOverride )
{
m_iPrimaryAmmoType = (int)TF_AMMO_METAL;
}
#endif
}
}
if ( GetWpnData().szAmmo2[0] )
{
m_iSecondaryAmmoType = GetAmmoDef()->Index( GetWpnData().szAmmo2 );
@@ -299,8 +260,18 @@ void CBaseCombatWeapon::Precache( void )
Warning( "Error reading weapon data file for: %s\n", GetClassname() );
// Remove( ); //don't remove, this gets released soon!
}
const char *pszTracerName = GetTracerType();
if ( pszTracerName )
{
PrecacheEffect( pszTracerName );
}
PrecacheEffect( "ParticleTracer" );
PrecacheParticleSystem( "weapon_tracers" );
}
//-----------------------------------------------------------------------------
// Purpose: Get my data in the file weapon info array
//-----------------------------------------------------------------------------
@@ -347,13 +318,6 @@ const char *CBaseCombatWeapon::GetPrintName( void ) const
//-----------------------------------------------------------------------------
int CBaseCombatWeapon::GetMaxClip1( void ) const
{
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
int iModMaxClipOverride = 0;
CALL_ATTRIB_HOOK_INT( iModMaxClipOverride, mod_max_primary_clip_override );
if ( iModMaxClipOverride != 0 )
return iModMaxClipOverride;
#endif
return GetWpnData().iMaxClip1;
}
@@ -554,20 +518,6 @@ CBaseCombatCharacter *CBaseCombatWeapon::GetOwner() const
//-----------------------------------------------------------------------------
void CBaseCombatWeapon::SetOwner( CBaseCombatCharacter *owner )
{
if ( !owner )
{
#ifndef CLIENT_DLL
// Make sure the weapon updates its state when it's removed from the player
// We have to force an active state change, because it's being dropped and won't call UpdateClientData()
int iOldState = m_iState;
m_iState = WEAPON_NOT_CARRIED;
OnActiveStateChanged( iOldState );
#endif
// make sure we clear out our HideThink if we have one pending
SetContextThink( NULL, 0, HIDEWEAPON_THINK_CONTEXT );
}
m_hOwner = owner;
#ifndef CLIENT_DLL
@@ -658,7 +608,6 @@ float CBaseCombatWeapon::GetWeaponIdleTime( void )
void CBaseCombatWeapon::Drop( const Vector &vecVelocity )
{
#if !defined( CLIENT_DLL )
// Once somebody drops a gun, it's fair game for removal when/if
// a game_weapon_manager does a cleanup on surplus weapons in the
// world.
@@ -754,10 +703,6 @@ void CBaseCombatWeapon::OnPickedUp( CBaseCombatCharacter *pNewOwner )
m_OnNPCPickup.FireOutput(pNewOwner, this);
}
#ifdef HL2MP
HL2MPRules()->RemoveLevelDesignerPlacedObject( this );
#endif
// Someone picked me up, so make it so that I can't be removed.
SetRemoveable( false );
#endif
@@ -780,6 +725,10 @@ void CBaseCombatWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &t
}
const char *pszTracerName = GetTracerType();
if ( !pszTracerName )
{
pszTracerName = "weapon_tracers";
}
Vector vNewSrc = vecTracerSrc;
int iEntIndex = pOwner->entindex();
@@ -787,25 +736,22 @@ void CBaseCombatWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &t
if ( g_pGameRules->IsMultiplayer() )
{
iEntIndex = entindex();
#ifdef CLIENT_DLL
C_BasePlayer *player = ToBasePlayer( pOwner );
if ( C_BasePlayer::IsLocalPlayer( player ) )
{
CBaseEntity *vm = player->GetViewModel();
if ( vm )
{
iEntIndex = vm->entindex();
}
}
#endif
}
int iAttachment = GetTracerAttachment();
switch ( iTracerType )
{
case TRACER_LINE:
UTIL_Tracer( vNewSrc, tr.endpos, iEntIndex, iAttachment, 0.0f, true, pszTracerName );
break;
case TRACER_LINE_AND_WHIZ:
UTIL_Tracer( vNewSrc, tr.endpos, iEntIndex, iAttachment, 0.0f, true, pszTracerName );
break;
}
}
void CBaseCombatWeapon::GiveTo( CBaseEntity *pOther )
{
DefaultTouch( pOther );
UTIL_ParticleTracer( pszTracerName, vNewSrc, tr.endpos, iEntIndex, iAttachment, true );
}
//-----------------------------------------------------------------------------
@@ -1008,10 +954,7 @@ void CBaseCombatWeapon::Equip( CBaseCombatCharacter *pOwner )
void CBaseCombatWeapon::SetActivity( Activity act, float duration )
{
//Adrian: Oh man...
#if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL ))
SetModel( GetWorldModel() );
#endif
int sequence = SelectWeightedSequence( act );
@@ -1019,10 +962,7 @@ void CBaseCombatWeapon::SetActivity( Activity act, float duration )
if ( sequence == ACTIVITY_NOT_AVAILABLE )
sequence = SelectWeightedSequence( ACT_VM_IDLE );
//Adrian: Oh man again...
#if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL ))
SetModel( GetViewModel() );
#endif
if ( sequence != ACTIVITY_NOT_AVAILABLE )
{
@@ -1035,7 +975,8 @@ void CBaseCombatWeapon::SetActivity( Activity act, float duration )
{
// FIXME: does this even make sense in non-shoot animations?
m_flPlaybackRate = SequenceDuration( sequence ) / duration;
m_flPlaybackRate = MIN( m_flPlaybackRate, 12.0); // FIXME; magic number!, network encoding range
m_flPlaybackRate = fpmin( m_flPlaybackRate, 12.0); // FIXME; magic number!, network encoding range
Assert( IsFinite( m_flPlaybackRate ) );
}
else
{
@@ -1053,14 +994,7 @@ int CBaseCombatWeapon::UpdateClientData( CBasePlayer *pPlayer )
if ( pPlayer->GetActiveWeapon() == this )
{
if ( pPlayer->m_fOnTarget )
{
iNewState = WEAPON_IS_ONTARGET;
}
else
{
iNewState = WEAPON_IS_ACTIVE;
}
iNewState = WEAPON_IS_ACTIVE;
}
else
{
@@ -1069,9 +1003,7 @@ int CBaseCombatWeapon::UpdateClientData( CBasePlayer *pPlayer )
if ( m_iState != iNewState )
{
int iOldState = m_iState;
m_iState = iNewState;
OnActiveStateChanged( iOldState );
}
return 1;
}
@@ -1105,7 +1037,7 @@ void CBaseCombatWeapon::SendViewModelAnim( int nSequence )
if ( pOwner == NULL )
return;
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex, false );
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex );
if ( vm == NULL )
return;
@@ -1167,7 +1099,7 @@ void CBaseCombatWeapon::SetViewModel()
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL )
return;
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex, false );
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex );
if ( vm == NULL )
return;
Assert( vm->ViewModelIndex() == m_nViewModelIndex );
@@ -1180,18 +1112,10 @@ void CBaseCombatWeapon::SetViewModel()
//-----------------------------------------------------------------------------
bool CBaseCombatWeapon::SendWeaponAnim( int iActivity )
{
#ifdef USES_ECON_ITEMS
#ifdef USES_PERSISTENT_ITEMS
iActivity = TranslateViewmodelHandActivity( (Activity)iActivity );
#endif
// NVNT notify the haptics system of this weapons new activity
#ifdef WIN32
#ifdef CLIENT_DLL
if ( prediction->InPrediction() && prediction->IsFirstTimePredicted() )
#endif
#ifndef _X360
HapticSendWeaponAnim(this,iActivity);
#endif
#endif
//For now, just set the ideal activity and be done with it
return SetIdealActivity( (Activity) iActivity );
}
@@ -1331,7 +1255,13 @@ bool CBaseCombatWeapon::IsWeaponVisible( void )
{
vm = pOwner->GetViewModel( m_nViewModelIndex );
if ( vm )
{
#ifdef CLIENT_DLL
return !vm->IsDormant() && !vm->IsEffectActive(EF_NODRAW);
#else
return ( !vm->IsEffectActive(EF_NODRAW) );
#endif
}
}
return false;
@@ -1361,7 +1291,7 @@ bool CBaseCombatWeapon::ReloadOrSwitchWeapons( void )
else
{
// Weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
if ( UsesClipsForAmmo1() && !AutoFiresFullClip() &&
if ( UsesClipsForAmmo1() &&
(m_iClip1 == 0) &&
(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) == false &&
m_flNextPrimaryAttack < gpGlobals->curtime &&
@@ -1369,7 +1299,9 @@ bool CBaseCombatWeapon::ReloadOrSwitchWeapons( void )
{
// if we're successfully reloading, we're done
if ( Reload() )
{
return true;
}
}
}
@@ -1417,8 +1349,6 @@ bool CBaseCombatWeapon::DefaultDeploy( char *szViewModel, char *szWeaponModel, i
m_bReloadHudHintDisplayed = false;
m_flHudHintPollTime = gpGlobals->curtime + 5.0f;
WeaponSound( DEPLOY );
SetWeaponVisible( true );
/*
@@ -1456,7 +1386,6 @@ bool CBaseCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo )
// cancel any reload in progress.
m_bInReload = false;
m_bFiringWholeClip = false;
// kill any think functions
SetThink(NULL);
@@ -1542,66 +1471,6 @@ void CBaseCombatWeapon::HideThink( void )
}
}
bool CBaseCombatWeapon::CanReload( void )
{
if ( AutoFiresFullClip() && m_bFiringWholeClip )
{
return false;
}
return true;
}
#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL )
//-----------------------------------------------------------------------------
// Purpose: Anti-hack
//-----------------------------------------------------------------------------
void CBaseCombatWeapon::AddToCritBucket( float flAmount )
{
float flCap = tf_weapon_criticals_bucket_cap.GetFloat();
// Regulate crit frequency to reduce client-side seed hacking
if ( m_flCritTokenBucket < flCap )
{
// Treat raw damage as the resource by which we add or subtract from the bucket
m_flCritTokenBucket += flAmount;
m_flCritTokenBucket = Min( m_flCritTokenBucket, flCap );
}
}
//-----------------------------------------------------------------------------
// Purpose: Anti-hack
//-----------------------------------------------------------------------------
bool CBaseCombatWeapon::IsAllowedToWithdrawFromCritBucket( float flDamage )
{
// Note: If we're in this block of code, the assumption is that the
// seed said we should grant a random crit. If allowed, the cost
// will be deducted here.
// Track each seed request - in cases where a player is hacking, we'll
// see a silly ratio.
m_nCritSeedRequests++;
// Adjust token cost based on the ratio of requests vs granted, except
// melee, which crits much more than ranged (as high as 60% chance)
float flMult = ( IsMeleeWeapon() ) ? 0.5f : RemapValClamped( ( (float)m_nCritSeedRequests / (float)m_nCritChecks ), 0.1f, 1.f, 1.f, 3.f );
// Would this take us below our limit?
float flCost = ( flDamage * TF_DAMAGE_CRIT_MULTIPLIER ) * flMult;
if ( flCost > m_flCritTokenBucket )
return false;
// Withdraw
RemoveFromCritBucket( flCost );
float flBottom = tf_weapon_criticals_bucket_bottom.GetFloat();
if ( m_flCritTokenBucket < flBottom )
m_flCritTokenBucket = flBottom;
return true;
}
#endif // TF_DLL
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@@ -1653,8 +1522,6 @@ void CBaseCombatWeapon::ItemPostFrame( void )
if (!pOwner)
return;
UpdateAutoFire();
//Track the duration of the fire
//FIXME: Check for IN_ATTACK2 as well?
//FIXME: What if we're calling ItemBusyFrame?
@@ -1695,7 +1562,7 @@ void CBaseCombatWeapon::ItemPostFrame( void )
if( !IsX360() || !ClassMatches("weapon_crossbow") )
#endif
{
bFired = ShouldBlockPrimaryFire();
bFired = true;
}
SecondaryAttack();
@@ -1743,22 +1610,13 @@ void CBaseCombatWeapon::ItemPostFrame( void )
}
PrimaryAttack();
if ( AutoFiresFullClip() )
{
m_bFiringWholeClip = true;
}
#ifdef CLIENT_DLL
pOwner->SetFiredWeapon( true );
#endif
}
}
// -----------------------
// Reload pressed / Clip Empty
// -----------------------
if ( ( pOwner->m_nButtons & IN_RELOAD ) && UsesClipsForAmmo1() && !m_bInReload )
if ( (pOwner->m_nButtons & IN_RELOAD) && UsesClipsForAmmo1() && !m_bInReload )
{
// reload when reload is pressed, or if no buttons are down and weapon is empty.
Reload();
@@ -1768,10 +1626,10 @@ void CBaseCombatWeapon::ItemPostFrame( void )
// -----------------------
// No buttons down
// -----------------------
if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (CanReload() && pOwner->m_nButtons & IN_RELOAD)))
if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)))
{
// no fire buttons down or reloading
if ( !ReloadOrSwitchWeapons() && ( m_bInReload == false ) )
if ( ( m_bInReload == false ) && !ReloadOrSwitchWeapons() )
{
WeaponIdle();
}
@@ -1802,7 +1660,6 @@ void CBaseCombatWeapon::HandleFireOnEmpty()
//-----------------------------------------------------------------------------
void CBaseCombatWeapon::ItemBusyFrame( void )
{
UpdateAutoFire();
}
//-----------------------------------------------------------------------------
@@ -2015,27 +1872,6 @@ bool CBaseCombatWeapon::DefaultReload( int iClipSize1, int iClipSize2, int iActi
return true;
}
bool CBaseCombatWeapon::ReloadsSingly( void ) const
{
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
float fHasReload = 1.0f;
CALL_ATTRIB_HOOK_FLOAT( fHasReload, mod_no_reload_display_only );
if ( fHasReload != 1.0f )
{
return false;
}
int iWeaponMod = 0;
CALL_ATTRIB_HOOK_INT( iWeaponMod, set_scattergun_no_reload_single );
if ( iWeaponMod == 1 )
{
return false;
}
#endif // TF_DLL || TF_CLIENT_DLL
return m_bReloadsSingly;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@@ -2187,54 +2023,6 @@ void CBaseCombatWeapon::AbortReload( void )
m_bInReload = false;
}
void CBaseCombatWeapon::UpdateAutoFire( void )
{
if ( !AutoFiresFullClip() )
return;
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( !pOwner )
return;
if ( m_iClip1 == 0 )
{
// Ready to reload again
m_bFiringWholeClip = false;
}
if ( m_bFiringWholeClip )
{
// If it's firing the clip don't let them repress attack to reload
pOwner->m_nButtons &= ~IN_ATTACK;
}
// Don't use the regular reload key
if ( pOwner->m_nButtons & IN_RELOAD )
{
pOwner->m_nButtons &= ~IN_RELOAD;
}
// Try to fire if there's ammo in the clip and we're not holding the button
bool bReleaseClip = m_iClip1 > 0 && !( pOwner->m_nButtons & IN_ATTACK );
if ( !bReleaseClip )
{
if ( CanReload() && ( pOwner->m_nButtons & IN_ATTACK ) )
{
// Convert the attack key into the reload key
pOwner->m_nButtons |= IN_RELOAD;
}
// Don't allow attack button if we're not attacking
pOwner->m_nButtons &= ~IN_ATTACK;
}
else
{
// Fake the attack key
pOwner->m_nButtons |= IN_ATTACK;
}
}
//-----------------------------------------------------------------------------
// Purpose: Primary fire button attack
//-----------------------------------------------------------------------------
@@ -2303,7 +2091,7 @@ void CBaseCombatWeapon::PrimaryAttack( void )
info.m_vecSpread = pPlayer->GetAttackSpread( this );
#else
//!!!HACKHACK - what does the client want this function for?
info.m_vecSpread = GetActiveWeapon()->GetBulletSpread();
info.m_vecSpread = pPlayer->GetActiveWeapon()->GetBulletSpread();
#endif // CLIENT_DLL
pPlayer->FireBullets( info );
@@ -2318,6 +2106,82 @@ void CBaseCombatWeapon::PrimaryAttack( void )
AddViewKick();
}
void CBaseCombatWeapon::BaseForceFire( CBaseCombatCharacter *pOperator, CBaseEntity *pTarget )
{
// Ensure we have enough rounds in the clip
m_iClip1++;
// If my clip is empty (and I use clips) start reload
if ( UsesClipsForAmmo1() && !m_iClip1 )
{
Reload();
return;
}
pOperator->DoMuzzleFlash();
SendWeaponAnim( GetPrimaryAttackActivity() );
// player "shoot" animation
//pOperator->SetAnimation( PLAYER_ATTACK1 );
FireBulletsInfo_t info;
QAngle angShootDir;
GetAttachment( LookupAttachment( "muzzle" ), info.m_vecSrc, angShootDir );
if ( pTarget )
{
info.m_vecDirShooting = pTarget->WorldSpaceCenter() - info.m_vecSrc;
VectorNormalize( info.m_vecDirShooting );
}
else
{
AngleVectors( angShootDir, &info.m_vecDirShooting );
}
// To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems,
// especially if the weapon we're firing has a really fast rate of fire.
info.m_iShots = 0;
float fireRate = GetFireRate();
while ( m_flNextPrimaryAttack <= gpGlobals->curtime )
{
// MUST call sound before removing a round from the clip of a CMachineGun
WeaponSound(SINGLE, m_flNextPrimaryAttack);
m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate;
info.m_iShots++;
if ( !fireRate )
break;
}
// Make sure we don't fire more than the amount in the clip
if ( UsesClipsForAmmo1() )
{
info.m_iShots = MIN( info.m_iShots, m_iClip1 );
m_iClip1 -= info.m_iShots;
}
else
{
info.m_iShots = MIN( info.m_iShots, pOperator->GetAmmoCount( m_iPrimaryAmmoType ) );
pOperator->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType );
}
info.m_flDistance = MAX_TRACE_LENGTH;
info.m_iAmmoType = m_iPrimaryAmmoType;
info.m_iTracerFreq = 2;
#if !defined( CLIENT_DLL )
// Fire the bullets
info.m_vecSpread = pOperator->GetAttackSpread( this );
#else
//!!!HACKHACK - what does the client want this function for?
info.m_vecSpread = GetBulletSpread();
#endif // CLIENT_DLL
pOperator->FireBullets( info );
}
//-----------------------------------------------------------------------------
// Purpose: Called every frame to check if the weapon is going through transition animations
//-----------------------------------------------------------------------------
@@ -2340,7 +2204,7 @@ void CBaseCombatWeapon::MaintainIdealActivity( void )
}
//-----------------------------------------------------------------------------
// Purpose: Sets the ideal activity for the weapon to be in, allowing for transitional animations inbetween
// Purpose: Sets the ideal activity for the weapon to be in, allowing for transitional animations in between
// Input : ideal - activity to end up at, ideally
//-----------------------------------------------------------------------------
bool CBaseCombatWeapon::SetIdealActivity( Activity ideal )
@@ -2439,81 +2303,79 @@ Activity CBaseCombatWeapon::ActivityOverride( Activity baseAct, bool *pRequired
return baseAct;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CDmgAccumulator::CDmgAccumulator( void )
class CWeaponList : public CAutoGameSystem
{
#ifdef GAME_DLL
SetDefLessFunc( m_TargetsDmgInfo );
#endif // GAME_DLL
m_bActive = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CDmgAccumulator::~CDmgAccumulator()
{
// Did a weapon get deleted while aggregating CTakeDamageInfo events?
Assert( !m_bActive );
}
#ifdef GAME_DLL
//-----------------------------------------------------------------------------
// Collect trace attacks for weapons that fire multiple bullets per attack that also penetrate
//-----------------------------------------------------------------------------
void CDmgAccumulator::AccumulateMultiDamage( const CTakeDamageInfo &info, CBaseEntity *pEntity )
{
if ( !pEntity )
return;
Assert( m_bActive );
#if defined( GAME_DLL )
int iIndex = m_TargetsDmgInfo.Find( pEntity->entindex() );
if ( iIndex == m_TargetsDmgInfo.InvalidIndex() )
public:
CWeaponList( char const *name ) : CAutoGameSystem( name )
{
m_TargetsDmgInfo.Insert( pEntity->entindex(), info );
}
else
virtual void LevelShutdownPostEntity()
{
m_list.Purge();
}
void AddWeapon( CBaseCombatWeapon *pWeapon )
{
CTakeDamageInfo *pInfo = &m_TargetsDmgInfo[iIndex];
if ( pInfo )
m_list.AddToTail( pWeapon );
}
void RemoveWeapon( CBaseCombatWeapon *pWeapon )
{
m_list.FindAndRemove( pWeapon );
}
CUtlLinkedList< CBaseCombatWeapon * > m_list;
};
CWeaponList g_WeaponList( "CWeaponList" );
#ifndef CLIENT_DLL
void OnBaseCombatWeaponCreated( CBaseCombatWeapon *pWeapon )
{
g_WeaponList.AddWeapon( pWeapon );
}
void OnBaseCombatWeaponDestroyed( CBaseCombatWeapon *pWeapon )
{
g_WeaponList.RemoveWeapon( pWeapon );
}
#endif
#ifdef CLIENT_DLL
CUtlLinkedList< CBaseCombatWeapon * >& CBaseCombatWeapon::GetWeaponList( void )
{
return g_WeaponList.m_list;
}
#else
int CBaseCombatWeapon::GetAvailableWeaponsInBox( CBaseCombatWeapon **pList, int listMax, const Vector &mins, const Vector &maxs )
{
// linear search all weapons
int count = 0;
int index = g_WeaponList.m_list.Head();
while ( index != g_WeaponList.m_list.InvalidIndex() )
{
CBaseCombatWeapon *pWeapon = g_WeaponList.m_list[index];
// skip any held weapon
if ( !pWeapon->GetOwner() )
{
// Update
m_TargetsDmgInfo[iIndex].AddDamageType( info.GetDamageType() );
m_TargetsDmgInfo[iIndex].SetDamage( pInfo->GetDamage() + info.GetDamage() );
m_TargetsDmgInfo[iIndex].SetDamageForce( pInfo->GetDamageForce() + info.GetDamageForce() );
m_TargetsDmgInfo[iIndex].SetDamagePosition( info.GetDamagePosition() );
m_TargetsDmgInfo[iIndex].SetReportedPosition( info.GetReportedPosition() );
m_TargetsDmgInfo[iIndex].SetMaxDamage( MAX( pInfo->GetMaxDamage(), info.GetDamage() ) );
m_TargetsDmgInfo[iIndex].SetAmmoType( info.GetAmmoType() );
}
}
#endif // GAME_DLL
}
//-----------------------------------------------------------------------------
// Purpose: Send aggregate info
//-----------------------------------------------------------------------------
void CDmgAccumulator::Process( void )
{
FOR_EACH_MAP( m_TargetsDmgInfo, i )
{
CBaseEntity *pEntity = UTIL_EntityByIndex( m_TargetsDmgInfo.Key( i ) );
if ( pEntity )
{
AddMultiDamage( m_TargetsDmgInfo[i], pEntity );
// restrict to mins/maxs
if ( IsPointInBox( pWeapon->GetAbsOrigin(), mins, maxs ) )
{
if ( count < listMax )
{
pList[count] = pWeapon;
count++;
}
}
}
index = g_WeaponList.m_list.Next( index );
}
m_bActive = false;
m_TargetsDmgInfo.Purge();
return count;
}
#endif // GAME_DLL
#endif
#if defined( CLIENT_DLL )
@@ -2523,7 +2385,7 @@ BEGIN_PREDICTION_DATA( CBaseCombatWeapon )
// Networked
DEFINE_PRED_FIELD( m_hOwner, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
// DEFINE_FIELD( m_hWeaponFileInfo, FIELD_SHORT ),
DEFINE_PRED_FIELD( m_iState, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_iState, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_iViewModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
DEFINE_PRED_FIELD( m_iWorldModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
DEFINE_PRED_FIELD_TOL( m_flNextPrimaryAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ),
@@ -2539,10 +2401,8 @@ BEGIN_PREDICTION_DATA( CBaseCombatWeapon )
// Not networked
DEFINE_PRED_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_FIELD( m_bInReload, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bFireOnEmpty, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bFiringWholeClip, FIELD_BOOLEAN ),
DEFINE_FIELD( m_flNextEmptySoundTime, FIELD_FLOAT ),
DEFINE_FIELD( m_Activity, FIELD_INTEGER ),
DEFINE_FIELD( m_fFireDuration, FIELD_FLOAT ),
@@ -2704,29 +2564,6 @@ void* SendProxy_SendLocalWeaponDataTable( const SendProp *pProp, const void *pSt
return NULL;
}
REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendLocalWeaponDataTable );
//-----------------------------------------------------------------------------
// Purpose: Only send to non-local players
//-----------------------------------------------------------------------------
void* SendProxy_SendNonLocalWeaponDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID )
{
pRecipients->SetAllRecipients();
CBaseCombatWeapon *pWeapon = (CBaseCombatWeapon*)pVarData;
if ( pWeapon )
{
CBasePlayer *pPlayer = ToBasePlayer( pWeapon->GetOwner() );
if ( pPlayer )
{
pRecipients->ClearRecipient( pPlayer->GetClientIndex() );
return ( void * )pVarData;
}
}
return NULL;
}
REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendNonLocalWeaponDataTable );
#endif
#if PREDICTION_ERROR_CHECK_LEVEL > 1
@@ -2744,9 +2581,7 @@ BEGIN_NETWORK_TABLE_NOBASE( CBaseCombatWeapon, DT_LocalActiveWeaponData )
SendPropInt( SENDINFO( m_nNextThinkTick ) ),
SendPropTime( SENDINFO( m_flTimeWeaponIdle ) ),
#if defined( TF_DLL )
SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ),
#endif
#else
RecvPropTime( RECVINFO( m_flNextPrimaryAttack ) ),
@@ -2768,11 +2603,7 @@ BEGIN_NETWORK_TABLE_NOBASE( CBaseCombatWeapon, DT_LocalWeaponData )
SendPropInt( SENDINFO( m_nViewModelIndex ), VIEWMODEL_INDEX_BITS, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_bFlipViewModel ) ),
#if defined( TF_DLL )
SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ),
#endif
#else
RecvPropIntWithMinusOneFlag( RECVINFO(m_iClip1 )),
@@ -2782,8 +2613,6 @@ BEGIN_NETWORK_TABLE_NOBASE( CBaseCombatWeapon, DT_LocalWeaponData )
RecvPropInt( RECVINFO( m_nViewModelIndex ) ),
RecvPropBool( RECVINFO( m_bFlipViewModel ) ),
#endif
END_NETWORK_TABLE()
@@ -2793,7 +2622,7 @@ BEGIN_NETWORK_TABLE(CBaseCombatWeapon, DT_BaseCombatWeapon)
SendPropDataTable("LocalActiveWeaponData", 0, &REFERENCE_SEND_TABLE(DT_LocalActiveWeaponData), SendProxy_SendActiveLocalWeaponDataTable ),
SendPropModelIndex( SENDINFO(m_iViewModelIndex) ),
SendPropModelIndex( SENDINFO(m_iWorldModelIndex) ),
SendPropInt( SENDINFO(m_iState ), 8, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_iState ), 2, SPROP_UNSIGNED ),
SendPropEHandle( SENDINFO(m_hOwner) ),
#else
RecvPropDataTable("LocalWeaponData", 0, 0, &REFERENCE_RECV_TABLE(DT_LocalWeaponData)),
@@ -2804,3 +2633,32 @@ BEGIN_NETWORK_TABLE(CBaseCombatWeapon, DT_BaseCombatWeapon)
RecvPropEHandle( RECVINFO(m_hOwner ) ),
#endif
END_NETWORK_TABLE()
#if defined( CLIENT_DLL )
int Studio_FindAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName );
int CBaseCombatWeapon::LookupAttachment( const char *pAttachmentName )
{
int newIndex = GetWorldModelIndex();
if ( newIndex != m_nModelIndex )
{
const model_t *pWorldModel = modelinfo->GetModel( newIndex );
if ( pWorldModel )
{
MDLHandle_t hStudioHdr = modelinfo->GetCacheHandle( pWorldModel );
if ( MDLHANDLE_INVALID != hStudioHdr )
{
const studiohdr_t *pStudioHdr = mdlcache->GetStudioHdr( hStudioHdr );
if ( pStudioHdr )
{
CStudioHdr studioHdrContainer( pStudioHdr, mdlcache );
int iRet = Studio_FindAttachment( &studioHdrContainer, pAttachmentName ) + 1;
return iRet;
}
}
}
}
return BaseClass::LookupAttachment( pAttachmentName );
}
#endif
+92 -119
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
@@ -17,16 +17,15 @@
#include "weapon_parse.h"
#include "baseviewmodel_shared.h"
#include "weapon_proficiency.h"
#include "utlmap.h"
#if defined( CLIENT_DLL )
#define CBaseCombatWeapon C_BaseCombatWeapon
#endif
// Hacky
#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL )
#include "econ_entity.h"
#endif // TF_CLIENT_DLL || TF_DLL
#if defined ( USES_PERSISTENT_ITEMS )
#include "item_base.h"
#endif // USES_PERSISTENT_ITEMS
#if !defined( CLIENT_DLL )
extern void OnBaseCombatWeaponCreated( CBaseCombatWeapon * );
@@ -91,6 +90,9 @@ namespace vgui2
typedef unsigned long HFont;
}
#define MWHEEL_UP 1
#define MWHEEL_DOWN -1
// -----------------------------------------
// Vector cones
// -----------------------------------------
@@ -119,36 +121,12 @@ namespace vgui2
// Purpose: Base weapon class, shared on client and server
//-----------------------------------------------------------------------------
#if defined USES_ECON_ITEMS
#define BASECOMBATWEAPON_DERIVED_FROM CEconEntity
#if defined USES_PERSISTENT_ITEMS
#define BASECOMBATWEAPON_DERIVED_FROM CBaseAttributableItem
#else
#define BASECOMBATWEAPON_DERIVED_FROM CBaseAnimating
#endif
//-----------------------------------------------------------------------------
// Collect trace attacks for weapons that fire multiple projectiles per attack that also penetrate
//-----------------------------------------------------------------------------
class CDmgAccumulator
{
public:
CDmgAccumulator( void );
~CDmgAccumulator();
#ifdef GAME_DLL
virtual void Start( void ) { m_bActive = true; }
virtual void AccumulateMultiDamage( const CTakeDamageInfo &info, CBaseEntity *pEntity );
virtual void Process( void );
private:
CTakeDamageInfo m_updatedInfo;
CUtlMap< int, CTakeDamageInfo > m_TargetsDmgInfo;
#endif // GAME_DLL
private:
bool m_bActive;
};
//-----------------------------------------------------------------------------
// Purpose: Client side rep of CBaseTFCombatWeapon
//-----------------------------------------------------------------------------
@@ -163,6 +141,12 @@ public:
CBaseCombatWeapon();
virtual ~CBaseCombatWeapon();
// Get unique weapon ID
// FIXMEL4DTOMAINMERGE
// We might have to disable this code in main until we refactor all weapons to use this system, as it's a pretty good perf boost
virtual int GetWeaponID( void ) const { return 0; }
virtual bool IsBaseCombatWeapon( void ) const { return true; }
virtual CBaseCombatWeapon *MyCombatWeaponPointer( void ) { return this; }
@@ -192,7 +176,6 @@ public:
// Weapon Pickup For Player
virtual void SetPickupTouch( void );
virtual void DefaultTouch( CBaseEntity *pOther ); // default weapon touch
virtual void GiveTo( CBaseEntity *pOther );
// HUD Hints
virtual bool ShouldDisplayAltFireHUDHint();
@@ -233,10 +216,6 @@ public:
virtual void SetWeaponVisible( bool visible );
virtual bool IsWeaponVisible( void );
virtual bool ReloadOrSwitchWeapons( void );
virtual void OnActiveStateChanged( int iOldState ) { return; }
virtual bool HolsterOnDetach() { return false; }
virtual bool IsHolstered(){ return false; }
virtual void Detach() {}
// Weapon behaviour
virtual void ItemPreFrame( void ); // called each frame by the player PreThink
@@ -247,12 +226,8 @@ public:
virtual void HandleFireOnEmpty(); // Called when they have the attack button down
// but they are out of ammo. The default implementation
// either reloads, switches weapons, or plays an empty sound.
virtual bool ShouldBlockPrimaryFire() { return false; }
#ifdef CLIENT_DLL
virtual void CreateMove( float flInputSampleTime, CUserCmd *pCmd, const QAngle &vecOldViewAngles ) {}
virtual int CalcOverrideModelIndex() OVERRIDE;
#endif
virtual bool IsWeaponZoomed() { return false; } // Is this weapon in its 'zoomed in' mode?
@@ -263,15 +238,11 @@ public:
virtual void AbortReload( void );
virtual bool Reload( void );
bool DefaultReload( int iClipSize1, int iClipSize2, int iActivity );
bool ReloadsSingly( void ) const;
virtual bool AutoFiresFullClip( void ) { return false; }
virtual bool CanOverload( void ) { return false; }
virtual void UpdateAutoFire( void );
// Weapon firing
virtual void PrimaryAttack( void ); // do "+ATTACK"
virtual void SecondaryAttack( void ) { return; } // do "+ATTACK2"
virtual void BaseForceFire( CBaseCombatCharacter *pOperator, CBaseEntity *pTarget = NULL );
// Firing animations
virtual Activity GetPrimaryAttackActivity( void );
@@ -332,8 +303,6 @@ public:
//All weapons can be picked up by NPCs by default
virtual bool CanBePickedUpByNPCs( void ) { return true; }
virtual int GetSkinOverride() const { return -1; }
public:
// Weapon info accessors for data in the weapon's data file
@@ -359,13 +328,15 @@ public:
virtual bool UsesClipsForAmmo2( void ) const;
bool IsMeleeWeapon() const;
virtual void OnMouseWheel( int nDirection ) {}
// derive this function if you mod uses encrypted weapon info files
virtual const unsigned char *GetEncryptionKey( void );
virtual int GetPrimaryAmmoType( void ) const { return m_iPrimaryAmmoType; }
virtual int GetSecondaryAmmoType( void ) const { return m_iSecondaryAmmoType; }
virtual int Clip1() { return m_iClip1; }
virtual int Clip2() { return m_iClip2; }
int Clip1() const { return m_iClip1; }
int Clip2() const { return m_iClip2; }
// Ammo quantity queries for weapons that do not use clips. These are only
// used to determine how much ammo is in a weapon that does not have an owner.
@@ -391,7 +362,6 @@ public:
virtual void Activate( void );
virtual bool ShouldUseLargeViewModelVROverride() { return false; }
public:
// Server Only Methods
#if !defined( CLIENT_DLL )
@@ -431,7 +401,7 @@ public:
virtual void Operator_FrameUpdate( CBaseCombatCharacter *pOperator );
virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
virtual void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) { return; }
virtual void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary, CBaseEntity *pTarget = NULL ) { return; }
// NOTE: This should never be called when a character is operating the weapon. Animation events should be
// routed through the character, and then back into CharacterAnimEvent()
void HandleAnimEvent( animevent_t *pEvent );
@@ -441,21 +411,13 @@ public:
void InputHideWeapon( inputdata_t &inputdata );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual CDmgAccumulator *GetDmgAccumulator( void ) { return NULL; }
virtual void MakeWeaponNameFromEntity( CBaseEntity *pOther );
// Client only methods
#else
virtual void BoneMergeFastCullBloat( Vector &localMins, Vector &localMaxs, const Vector &thisEntityMins, const Vector &thisEntityMaxs ) const;
virtual bool OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options )
{
#if defined USES_ECON_ITEMS
return BaseClass::OnFireEvent( pViewModel, origin, angles, event, options );
#else
return false;
#endif
}
virtual bool OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options ) { return false; }
// Should this object cast shadows?
virtual ShadowType_t ShadowCastType();
@@ -463,8 +425,6 @@ public:
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void OnRestore();
virtual void RestartParticleEffect( void ) {}
virtual void Redraw(void);
virtual void ViewModelDrawn( CBaseViewModel *pViewModel );
// Get the position that bullets are seen coming out. Note: the returned values are different
@@ -475,16 +435,12 @@ public:
// Weapon state checking
virtual bool IsCarriedByLocalPlayer( void );
virtual bool ShouldDrawUsingViewModel( void );
virtual bool IsActiveByLocalPlayer( void );
bool IsBeingCarried() const;
// Is the carrier alive?
bool IsCarrierAlive() const;
// Returns the aiment render origin + angles
virtual int DrawModel( int flags );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual bool ShouldDraw( void );
virtual bool ShouldDrawPickup( void );
virtual void HandleInput( void ) { return; };
@@ -500,62 +456,90 @@ public:
virtual int GetWorldModelIndex( void );
virtual void GetToolRecordingState( KeyValues *msg );
void EnsureCorrectRenderingModel();
virtual void GetToolViewModelState( KeyValues *msg ) {} // this is just a stub for viewmodels to request recording of weapon-specific effects, etc
virtual void GetWeaponCrosshairScale( float &flScale ) { flScale = 1.f; }
#if !defined USES_ECON_ITEMS
#if !defined ( USES_PERSISTENT_ITEMS )
// Viewmodel overriding
virtual bool ViewModel_IsTransparent( void ) { return IsTransparent(); }
virtual bool ViewModel_IsUsingFBTexture( void ) { return UsesPowerOfTwoFrameBufferTexture(); }
virtual bool IsOverridingViewmodel( void ) { return false; };
virtual int DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags ) { return 0; };
virtual int DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags, const RenderableInstance_t &instance ) { return 0; };
bool WantsToOverrideViewmodelAttachments( void ) { return false; }
#endif
virtual IClientModelRenderable* GetClientModelRenderable();
static CUtlLinkedList< CBaseCombatWeapon * >& GetWeaponList( void );
virtual int LookupAttachment( const char *pAttachmentName );
#endif // End client-only methods
// Is the carrier alive?
bool IsCarrierAlive() const;
virtual bool CanLower( void ) { return false; }
virtual bool Ready( void ) { return false; }
virtual bool Lower( void ) { return false; }
virtual void HideThink( void );
virtual bool CanReload( void );
// FTYPEDESC_INSENDTABLE STUFF
private:
typedef CHandle< CBaseCombatCharacter > CBaseCombatCharacterHandle;
CNetworkVar( CBaseCombatCharacterHandle, m_hOwner ); // Player carrying this weapon
protected:
#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL )
// Regulate crit frequency to reduce client-side seed hacking
void AddToCritBucket( float flAmount );
void RemoveFromCritBucket( float flAmount ) { m_flCritTokenBucket -= flAmount; }
bool IsAllowedToWithdrawFromCritBucket( float flDamage );
float m_flCritTokenBucket;
int m_nCritChecks;
int m_nCritSeedRequests;
#endif // TF
public:
// Networked fields
CNetworkVar( int, m_nViewModelIndex );
// Weapon firing
CNetworkVar( float, m_flNextPrimaryAttack ); // soonest time ItemPostFrame will call PrimaryAttack
CNetworkVar( float, m_flNextSecondaryAttack ); // soonest time ItemPostFrame will call SecondaryAttack
CNetworkVar( float, m_flTimeWeaponIdle ); // soonest time ItemPostFrame will call WeaponIdle
// Weapon state
bool m_bInReload; // Are we in the middle of a reload;
bool m_bFireOnEmpty; // True when the gun is empty and the player is still holding down the attack key(s)
bool m_bFiringWholeClip; // Are we in the middle of firing the whole clip;
CNetworkVar( float, m_flNextSecondaryAttack ); // soonest time ItemPostFrame will call SecondaryAttack
// Weapon art
CNetworkVar( int, m_iViewModelIndex );
CNetworkVar( int, m_iWorldModelIndex );
public:
// Weapon data
CNetworkVar( int, m_iState ); // See WEAPON_* definition
CNetworkVar( int, m_iPrimaryAmmoType ); // "primary" ammo index into the ammo info array
CNetworkVar( int, m_iSecondaryAmmoType ); // "secondary" ammo index into the ammo info array
CNetworkVar( int, m_iClip1 ); // number of shots left in the primary weapon clip, -1 it not used
CNetworkVar( int, m_iClip2 ); // number of shots left in the secondary weapon clip, -1 it not used
public:
// Non-networked prediction fields
CNetworkVar( float, m_flTimeWeaponIdle ); // soonest time ItemPostFrame will call WeaponIdle
// Sounds
float m_flNextEmptySoundTime; // delay on empty sound playing
float m_fMinRange1; // What's the closest this weapon can be used?
float m_fMinRange2; // What's the closest this weapon can be used?
float m_fMaxRange1; // What's the furthest this weapon can be used?
float m_fMaxRange2; // What's the furthest this weapon can be used?
float m_fFireDuration; // The amount of time that the weapon has sustained firing
private:
Activity m_Activity;
int m_iPrimaryAmmoCount;
int m_iSecondaryAmmoCount;
public:
string_t m_iszName; // Classname of this weapon.
private:
bool m_bRemoveable;
public:
// Weapon state
CNetworkVar( bool, m_bInReload ); // Are we in the middle of a reload;
bool m_bFireOnEmpty; // True when the gun is empty and the player is still holding down the attack key(s)
bool m_bFiresUnderwater; // true if this weapon can fire underwater
bool m_bAltFiresUnderwater; // true if this weapon can fire underwater
bool m_bReloadsSingly; // Tryue if this weapon reloads 1 round at a time
// FTYPEDESC_INSENDTABLE STUFF (end)
public:
Activity GetIdealActivity( void ) { return m_IdealActivity; }
int GetIdealSequence( void ) { return m_nIdealSequence; }
@@ -563,43 +547,22 @@ public:
void MaintainIdealActivity( void );
private:
Activity m_Activity;
int m_nIdealSequence;
Activity m_IdealActivity;
bool m_bRemoveable;
int m_iPrimaryAmmoCount;
int m_iSecondaryAmmoCount;
public:
IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_nNextThinkTick );
int WeaponState() const { return m_iState; }
// Weapon data
CNetworkVar( int, m_iState ); // See WEAPON_* definition
string_t m_iszName; // Classname of this weapon.
CNetworkVar( int, m_iPrimaryAmmoType ); // "primary" ammo index into the ammo info array
CNetworkVar( int, m_iSecondaryAmmoType ); // "secondary" ammo index into the ammo info array
CNetworkVar( int, m_iClip1 ); // number of shots left in the primary weapon clip, -1 it not used
CNetworkVar( int, m_iClip2 ); // number of shots left in the secondary weapon clip, -1 it not used
bool m_bFiresUnderwater; // true if this weapon can fire underwater
bool m_bAltFiresUnderwater; // true if this weapon can fire underwater
float m_fMinRange1; // What's the closest this weapon can be used?
float m_fMinRange2; // What's the closest this weapon can be used?
float m_fMaxRange1; // What's the furthest this weapon can be used?
float m_fMaxRange2; // What's the furthest this weapon can be used?
bool m_bReloadsSingly; // True if this weapon reloads 1 round at a time
float m_fFireDuration; // The amount of time that the weapon has sustained firing
int m_iSubType;
float m_flUnlockTime;
EHANDLE m_hLocker; // Who locked this weapon.
CNetworkVar( bool, m_bFlipViewModel );
IPhysicsConstraint *GetConstraint() { return m_pConstraint; }
private:
@@ -617,7 +580,6 @@ private:
#if !defined( CLIENT_DLL )
// Outputs
protected:
COutputEvent m_OnPlayerUse; // Fired when the player uses the weapon.
COutputEvent m_OnPlayerPickup; // Fired when the player picks up the weapon.
COutputEvent m_OnNPCPickup; // Fired when an NPC picks up the weapon.
@@ -635,4 +597,15 @@ protected:
#endif // End Client .dll only
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline CBaseCombatWeapon *ToBaseCombatWeapon( CBaseEntity *pEntity )
{
if ( !pEntity )
return NULL;
return pEntity->MyCombatWeaponPointer();
}
#endif // COMBATWEAPON_SHARED_H
File diff suppressed because it is too large Load Diff
+53 -84
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -11,26 +11,27 @@
#pragma once
#endif
extern ConVar hl2_episodic;
// Simple shared header file for common base entities
// entity capabilities
// These are caps bits to indicate what an object's capabilities (currently used for +USE, save/restore and level transitions)
#define FCAP_MUST_SPAWN 0x00000001 // Spawn after restore
#define FCAP_ACROSS_TRANSITION 0x00000002 // should transfer between transitions
// UNDONE: This will ignore transition volumes (trigger_transition), but not the PVS!!!
#define FCAP_FORCE_TRANSITION 0x00000004 // ALWAYS goes across transitions
#define FCAP_NOTIFY_ON_TRANSITION 0x00000008 // Entity will receive Inside/Outside transition inputs when a transition occurs
#define FCAP_IMPULSE_USE 0x00000010 // can be used by the player
#define FCAP_CONTINUOUS_USE 0x00000020 // can be used by the player
#define FCAP_ONOFF_USE 0x00000040 // can be used by the player
#define FCAP_DIRECTIONAL_USE 0x00000080 // Player sends +/- 1 when using (currently only tracktrains)
// NOTE: (For portal 2 and paint) These +use related caps MUST be the first 6 bits!
#define FCAP_IMPULSE_USE 0x00000001 // can be used by the player
#define FCAP_CONTINUOUS_USE 0x00000002 // can be used by the player
#define FCAP_ONOFF_USE 0x00000004 // can be used by the player
#define FCAP_DIRECTIONAL_USE 0x00000008 // Player sends +/- 1 when using (currently only tracktrains)
// NOTE: Normally +USE only works in direct line of sight. Add these caps for additional searches
#define FCAP_USE_ONGROUND 0x00000100
#define FCAP_USE_IN_RADIUS 0x00000200
#define FCAP_USE_ONGROUND 0x00000010
#define FCAP_USE_IN_RADIUS 0x00000020
#define FCAP_MUST_SPAWN 0x00000040 // Spawn after restore
#define FCAP_ACROSS_TRANSITION 0x00000080 // should transfer between transitions
// UNDONE: This will ignore transition volumes (trigger_transition), but not the PVS!!!
#define FCAP_FORCE_TRANSITION 0x00000100 // ALWAYS goes across transitions
#define FCAP_NOTIFY_ON_TRANSITION 0x00000200 // Entity will receive Inside/Outside transition inputs when a transition occurs
#define FCAP_SAVE_NON_NETWORKABLE 0x00000400
#define FCAP_MASTER 0x10000000 // Can be used to "master" other entities (like multisource)
@@ -44,18 +45,6 @@ extern ConVar hl2_episodic;
// Maximum number of vphysics objects per entity
#define VPHYSICS_MAX_OBJECT_LIST_COUNT 1024
//-----------------------------------------------------------------------------
// For invalidate physics recursive
//-----------------------------------------------------------------------------
enum InvalidatePhysicsBits_t
{
POSITION_CHANGED = 0x1,
ANGLES_CHANGED = 0x2,
VELOCITY_CHANGED = 0x4,
ANIMATION_CHANGED = 0x8,
};
#if defined( CLIENT_DLL )
#include "c_baseentity.h"
#include "c_baseanimating.h"
@@ -68,6 +57,9 @@ enum InvalidatePhysicsBits_t
#endif
#include "vscript/ivscript.h"
#include "vscript_shared.h"
#if !defined( NO_ENTITY_PREDICTION )
// CBaseEntity inlines
inline bool CBaseEntity::IsPlayerSimulated( void ) const
@@ -77,7 +69,7 @@ inline bool CBaseEntity::IsPlayerSimulated( void ) const
inline CBasePlayer *CBaseEntity::GetSimulatingPlayer( void )
{
return m_hPlayerSimulationOwner;
return m_hPlayerSimulationOwner.Get();
}
#endif
@@ -247,64 +239,41 @@ inline bool CBaseEntity::IsEffectActive( int nEffects ) const
return (m_fEffects & nEffects) != 0;
}
inline HSCRIPT ToHScript( CBaseEntity *pEnt )
{
return ( pEnt ) ? pEnt->GetScriptInstance() : NULL;
}
template <> ScriptClassDesc_t *GetScriptDesc<CBaseEntity>( CBaseEntity * );
inline CBaseEntity *ToEnt( HSCRIPT hScript )
{
return ( hScript ) ? (CBaseEntity *)g_pScriptVM->GetInstanceValue( hScript, GetScriptDescForClass(CBaseEntity) ) : NULL;
}
// convenience functions for fishing out the vectors of this object
// equivalent to GetVectors(), but doesn't need an intermediate stack
// variable (which might cause an LHS anyway)
inline Vector CBaseEntity::Forward() const RESTRICT ///< get my forward (+x) vector
{
const matrix3x4_t &mat = EntityToWorldTransform();
return Vector( mat[0][0], mat[1][0], mat[2][0] );
}
inline Vector CBaseEntity::Left() const RESTRICT ///< get my left (+y) vector
{
const matrix3x4_t &mat = EntityToWorldTransform();
return Vector( mat[0][1], mat[1][1], mat[2][1] );
}
inline Vector CBaseEntity::Up() const RESTRICT ///< get my up (+z) vector
{
const matrix3x4_t &mat = EntityToWorldTransform();
return Vector( mat[0][2], mat[1][2], mat[2][2] );
}
// Shared EntityMessage between game and client .dlls
#define BASEENTITY_MSG_REMOVE_DECALS 1
extern float k_flMaxEntityPosCoord;
extern float k_flMaxEntityEulerAngle;
extern float k_flMaxEntitySpeed;
extern float k_flMaxEntitySpinRate;
inline bool IsEntityCoordinateReasonable ( const vec_t c )
{
float r = k_flMaxEntityPosCoord;
return c > -r && c < r;
}
inline bool IsEntityPositionReasonable( const Vector &v )
{
float r = k_flMaxEntityPosCoord;
return
v.x > -r && v.x < r &&
v.y > -r && v.y < r &&
v.z > -r && v.z < r;
}
// Returns:
// -1 - velocity is really, REALLY bad and probably should be rejected.
// 0 - velocity was suspicious and clamped.
// 1 - velocity was OK and not modified
extern int CheckEntityVelocity( Vector &v );
inline bool IsEntityQAngleReasonable( const QAngle &q )
{
float r = k_flMaxEntityEulerAngle;
return
q.x > -r && q.x < r &&
q.y > -r && q.y < r &&
q.z > -r && q.z < r;
}
// Angular velocity in exponential map form
inline bool IsEntityAngularVelocityReasonable( const Vector &q )
{
float r = k_flMaxEntitySpinRate;
return
q.x > -r && q.x < r &&
q.y > -r && q.y < r &&
q.z > -r && q.z < r;
}
// Angular velocity of each Euler angle.
inline bool IsEntityQAngleVelReasonable( const QAngle &q )
{
float r = k_flMaxEntitySpinRate;
return
q.x > -r && q.x < r &&
q.y > -r && q.y < r &&
q.z > -r && q.z < r;
}
extern bool CheckEmitReasonablePhysicsSpew();
#endif // BASEENTITY_SHARED_H
+12 -17
View File
@@ -1,9 +1,9 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
//===========================================================================//
#include "cbase.h"
#include "decals.h"
#include "basegrenade_shared.h"
@@ -14,16 +14,16 @@
#include "soundent.h"
#include "entitylist.h"
#include "gamestats.h"
#include "GameStats.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the fireball
extern short g_sModelIndexWExplosion; // (in combatweapon.cpp) holds the index for the underwater explosion
extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud
extern int g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the fireball
extern int g_sModelIndexWExplosion; // (in combatweapon.cpp) holds the index for the underwater explosion
extern int g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud
extern ConVar sk_plr_dmg_grenade;
#if !defined( CLIENT_DLL )
@@ -127,13 +127,9 @@ void CBaseGrenade::Explode( trace_t *pTrace, int bitsDamageType )
}
Vector vecAbsOrigin = GetAbsOrigin();
int contents = UTIL_PointContents ( vecAbsOrigin );
int contents = UTIL_PointContents ( vecAbsOrigin, MASK_ALL );
#if defined( TF_DLL )
// Since this code only runs on the server, make sure it shows the tempents it creates.
// This solves a problem with remote detonating the pipebombs (client wasn't seeing the explosion effect)
CDisablePredictionFiltering disabler;
#endif
if ( pTrace->fraction != 1.0 )
{
@@ -172,14 +168,13 @@ void CBaseGrenade::Explode( trace_t *pTrace, int bitsDamageType )
// Use the thrower's position as the reported position
Vector vecReported = m_hThrower ? m_hThrower->GetAbsOrigin() : vec3_origin;
EmitSound( "BaseGrenade.Explode" );
CTakeDamageInfo info( this, m_hThrower, GetBlastForce(), GetAbsOrigin(), m_flDamage, bitsDamageType, 0, &vecReported );
RadiusDamage( info, GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL );
UTIL_DecalTrace( pTrace, "Scorch" );
EmitSound( "BaseGrenade.Explode" );
SetThink( &CBaseGrenade::SUB_Remove );
SetTouch( NULL );
SetSolid( SOLID_NONE );
@@ -214,7 +209,7 @@ void CBaseGrenade::Explode( trace_t *pTrace, int bitsDamageType )
void CBaseGrenade::Smoke( void )
{
Vector vecAbsOrigin = GetAbsOrigin();
if ( UTIL_PointContents ( vecAbsOrigin ) & MASK_WATER )
if ( UTIL_PointContents ( vecAbsOrigin, MASK_WATER ) & MASK_WATER )
{
UTIL_Bubbles( vecAbsOrigin - Vector( 64, 64, 64 ), vecAbsOrigin + Vector( 64, 64, 64 ), 100 );
}
@@ -412,9 +407,9 @@ void CBaseGrenade::BounceTouch( CBaseEntity *pOther )
BounceSound();
}
m_flPlaybackRate = GetAbsVelocity().Length() / 200.0;
if (m_flPlaybackRate > 1.0)
if (GetPlaybackRate() > 1.0)
m_flPlaybackRate = 1;
else if (m_flPlaybackRate < 0.5)
else if (GetPlaybackRate() < 0.5)
m_flPlaybackRate = 0;
}
+4 -7
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -11,8 +11,6 @@
#pragma once
#endif
#include "baseprojectile.h"
#if defined( CLIENT_DLL )
#define CBaseGrenade C_BaseGrenade
@@ -31,12 +29,12 @@
class CTakeDamageInfo;
#if !defined( CLIENT_DLL )
class CBaseGrenade : public CBaseProjectile, public CDefaultPlayerPickupVPhysics
class CBaseGrenade : public CBaseCombatCharacter, public CDefaultPlayerPickupVPhysics
#else
class CBaseGrenade : public CBaseProjectile
class CBaseGrenade : public CBaseCombatCharacter
#endif
{
DECLARE_CLASS( CBaseGrenade, CBaseProjectile );
DECLARE_CLASS( CBaseGrenade, CBaseCombatCharacter );
public:
CBaseGrenade(void);
@@ -120,7 +118,6 @@ public:
bool m_bHasWarnedAI; // whether or not this grenade has issued its DANGER sound to the world sound list yet.
CNetworkVar( bool, m_bIsLive ); // Is this grenade live, or can it be picked up?
CNetworkVar( float, m_DmgRadius ); // How far do I do damage?
CNetworkVar( float, m_flNextAttack );
float m_flDetonateTime; // Time at which to detonate.
float m_flWarnAITime; // Time at which to warn the AI
+2 -3
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
@@ -35,7 +35,6 @@ CBaseParticleEntity::CBaseParticleEntity( void )
m_bSimulate = true;
m_nToolParticleEffectId = TOOLPARTICLESYSTEMID_INVALID;
#endif
m_bShouldDeletedOnChangelevel = false;
}
CBaseParticleEntity::~CBaseParticleEntity( void )
@@ -43,7 +42,7 @@ CBaseParticleEntity::~CBaseParticleEntity( void )
#if defined( CLIENT_DLL )
if ( ToolsEnabled() && ( m_nToolParticleEffectId != TOOLPARTICLESYSTEMID_INVALID ) && clienttools->IsInRecordingMode() )
{
KeyValues *msg = new KeyValues( "ParticleSystem_Destroy" );
KeyValues *msg = new KeyValues( "OldParticleSystem_Destroy" );
msg->SetInt( "id", m_nToolParticleEffectId );
m_nToolParticleEffectId = TOOLPARTICLESYSTEMID_INVALID;
}
+1 -13
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -35,16 +35,6 @@ public:
CBaseParticleEntity();
virtual ~CBaseParticleEntity();
virtual int ObjectCaps()
{
if( m_bShouldDeletedOnChangelevel )
return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION;
else
return BaseClass::ObjectCaps();
}
void SetShouldDeletedOnChangelevel( bool bDel ) { m_bShouldDeletedOnChangelevel = bDel; }
// CBaseEntity overrides.
public:
#if !defined( CLIENT_DLL )
@@ -86,8 +76,6 @@ public:
void SetLifetime(float lifetime);
private:
bool m_bShouldDeletedOnChangelevel;
CBaseParticleEntity( const CBaseParticleEntity & ); // not defined, not accessible
};
+192 -185
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements shared baseplayer class functionality
//
@@ -9,9 +9,7 @@
#include "movevars_shared.h"
#include "util_shared.h"
#include "datacache/imdlcache.h"
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
#include "tf_gamerules.h"
#endif
#include "collisionutils.h"
#if defined( CLIENT_DLL )
@@ -20,9 +18,8 @@
#include "c_basedoor.h"
#include "c_world.h"
#include "view.h"
#include "client_virtualreality.h"
#define CRecipientFilter C_RecipientFilter
#include "sourcevr/isourcevirtualreality.h"
#else
@@ -32,31 +29,25 @@
#include "doors.h"
#include "ai_basenpc.h"
#include "env_zoom.h"
#include "ammodef.h"
extern int TrainSpeed(int iSpeed, int iMax);
#endif
#if defined( CSTRIKE_DLL )
#include "weapon_c4.h"
#endif // CSTRIKE_DLL
#include "in_buttons.h"
#include "engine/IEngineSound.h"
#include "tier0/vprof.h"
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "decals.h"
#include "obstacle_pushaway.h"
#ifdef SIXENSE
#include "sixense/in_sixense.h"
#endif
// NVNT haptic utils
#include "haptics/haptic_utils.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if defined(GAME_DLL) && !defined(_XBOX)
#if defined(GAME_DLL)
ConVar sv_infinite_ammo( "sv_infinite_ammo", "0", FCVAR_CHEAT, "Player's active weapon will never run out of ammo" );
#if !defined(_XBOX)
extern ConVar sv_pushaway_max_force;
extern ConVar sv_pushaway_force;
extern ConVar sv_turbophysics;
@@ -76,16 +67,11 @@
if ( !pEntity->VPhysicsGetObject() )
return false;
#if defined( CSTRIKE_DLL )
// don't push the bomb!
if ( dynamic_cast<CC4*>( pEntity ) )
return false;
#endif // CSTRIKE_DLL
return g_pGameRules->CanEntityBeUsePushed( pEntity );
}
};
#endif
#endif
#ifdef CLIENT_DLL
ConVar mp_usehwmmodels( "mp_usehwmmodels", "0", NULL, "Enable the use of the hw morph models. (-1 = never, 1 = always, 0 = based upon GPU)" ); // -1 = never, 0 = if hasfastvertextextures, 1 = always
@@ -93,47 +79,14 @@ ConVar mp_usehwmmodels( "mp_usehwmmodels", "0", NULL, "Enable the use of the hw
bool UseHWMorphModels()
{
// #ifdef CLIENT_DLL
// if ( mp_usehwmmodels.GetInt() == 0 )
// return g_pMaterialSystemHardwareConfig->HasFastVertexTextures();
//
// return mp_usehwmmodels.GetInt() > 0;
// #else
// return false;
// #endif
#ifdef CLIENT_DLL
if ( mp_usehwmmodels.GetInt() == 0 )
return g_pMaterialSystemHardwareConfig->HasFastVertexTextures();
return mp_usehwmmodels.GetInt() > 0;
#else
return false;
}
void CopySoundNameWithModifierToken( char *pchDest, const char *pchSource, int nMaxLenInChars, const char *pchToken )
{
// Copy the sound name
int nSource = 0;
int nDest = 0;
bool bFoundPeriod = false;
while ( pchSource[ nSource ] != '\0' && nDest < nMaxLenInChars - 2 )
{
pchDest[ nDest ] = pchSource[ nSource ];
nDest++;
nSource++;
if ( !bFoundPeriod && pchSource[ nSource - 1 ] == '.' )
{
// Insert special token after the period
bFoundPeriod = true;
int nToken = 0;
while ( pchToken[ nToken ] != '\0' && nDest < nMaxLenInChars - 2 )
{
pchDest[ nDest ] = pchToken[ nToken ];
nDest++;
nToken++;
}
}
}
pchDest[ nDest ] = '\0';
#endif
}
//-----------------------------------------------------------------------------
@@ -145,16 +98,6 @@ float CBasePlayer::GetTimeBase( void ) const
return m_nTickBase * TICK_INTERVAL;
}
float CBasePlayer::GetPlayerMaxSpeed()
{
// player max speed is the lower limit of m_flMaxSpeed and sv_maxspeed
float fMaxSpeed = sv_maxspeed.GetFloat();
if ( MaxSpeed() > 0.0f && MaxSpeed() < fMaxSpeed )
fMaxSpeed = MaxSpeed();
return fMaxSpeed;
}
//-----------------------------------------------------------------------------
// Purpose: Called every usercmd by the player PreThink
//-----------------------------------------------------------------------------
@@ -289,6 +232,22 @@ void CBasePlayer::ItemPostFrame()
#if !defined( CLIENT_DLL )
ImpulseCommands();
extern ConVar sv_infinite_ammo;
if( sv_infinite_ammo.GetBool() && (GetActiveWeapon() != NULL) )
{
CBaseCombatWeapon *pWeapon = GetActiveWeapon();
pWeapon->m_iClip1 = pWeapon->GetMaxClip1();
int iPrimaryAmmoType = pWeapon->GetPrimaryAmmoType();
if( iPrimaryAmmoType >= 0 )
SetAmmoCount( GetAmmoDef()->MaxCarry( iPrimaryAmmoType, this ), iPrimaryAmmoType );
pWeapon->m_iClip2 = pWeapon->GetMaxClip2();
int iSecondaryAmmoType = pWeapon->GetSecondaryAmmoType();
if( iSecondaryAmmoType >= 0 )
SetAmmoCount( GetAmmoDef()->MaxCarry( iSecondaryAmmoType, this ), iSecondaryAmmoType );
}
#else
// NOTE: If we ever support full impulse commands on the client,
// remove this line and call ImpulseCommands instead.
@@ -307,6 +266,11 @@ const QAngle &CBasePlayer::EyeAngles( )
if ( !pMoveParent )
{
// if in camera mode, use that
if ( GetViewEntity() != NULL )
{
return GetViewEntity()->EyeAngles();
}
return pl.v_angle;
}
@@ -342,15 +306,21 @@ Vector CBasePlayer::EyePosition( )
#ifdef CLIENT_DLL
if ( IsObserver() )
{
if ( GetObserverMode() == OBS_MODE_CHASE )
if ( m_iObserverMode == OBS_MODE_CHASE )
{
if ( IsLocalPlayer() )
if ( IsLocalPlayer( this ) )
{
return MainViewOrigin();
return MainViewOrigin(GetSplitScreenPlayerSlot());
}
}
}
#endif
// if in camera mode, use that
if ( GetViewEntity() != NULL )
{
return GetViewEntity()->EyePosition();
}
return BaseClass::EyePosition();
}
}
@@ -365,17 +335,17 @@ const Vector CBasePlayer::GetPlayerMins( void ) const
{
if ( IsObserver() )
{
return VEC_OBS_HULL_MIN_SCALED( this );
return VEC_OBS_HULL_MIN;
}
else
{
if ( GetFlags() & FL_DUCKING )
{
return VEC_DUCK_HULL_MIN_SCALED( this );
return VEC_DUCK_HULL_MIN;
}
else
{
return VEC_HULL_MIN_SCALED( this );
return VEC_HULL_MIN;
}
}
}
@@ -389,21 +359,38 @@ const Vector CBasePlayer::GetPlayerMaxs( void ) const
{
if ( IsObserver() )
{
return VEC_OBS_HULL_MAX_SCALED( this );
return VEC_OBS_HULL_MAX;
}
else
{
if ( GetFlags() & FL_DUCKING )
{
return VEC_DUCK_HULL_MAX_SCALED( this );
return VEC_DUCK_HULL_MAX;
}
else
{
return VEC_HULL_MAX_SCALED( this );
return VEC_HULL_MAX;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBasePlayer::UpdateCollisionBounds( void )
{
if ( GetFlags() & FL_DUCKING )
{
SetCollisionBounds( VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX );
}
else
{
SetCollisionBounds( VEC_HULL_MIN, VEC_HULL_MAX );
}
}
//-----------------------------------------------------------------------------
// Purpose: Update the vehicle view, or simply return the cached position and angles
//-----------------------------------------------------------------------------
@@ -426,23 +413,6 @@ void CBasePlayer::CacheVehicleView( void )
// Get our view for this frame
pVehicle->GetVehicleViewPosition( nRole, &m_vecVehicleViewOrigin, &m_vecVehicleViewAngles, &m_flVehicleViewFOV );
m_nVehicleViewSavedFrame = gpGlobals->framecount;
#ifdef CLIENT_DLL
if( UseVR() )
{
C_BaseAnimating *pVehicleAnimating = dynamic_cast<C_BaseAnimating *>( pVehicle );
if( pVehicleAnimating )
{
int eyeAttachmentIndex = pVehicleAnimating->LookupAttachment( "vehicle_driver_eyes" );
Vector vehicleEyeOrigin;
QAngle vehicleEyeAngles;
pVehicleAnimating->GetAttachment( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
g_ClientVirtualReality.OverrideTorsoTransform( vehicleEyeOrigin, vehicleEyeAngles );
}
}
#endif
}
}
@@ -482,7 +452,7 @@ void CBasePlayer::EyePositionAndVectors( Vector *pPosition, Vector *pForward,
}
else
{
VectorCopy( BaseClass::EyePosition(), *pPosition );
VectorCopy( EyePosition(), *pPosition );
AngleVectors( EyeAngles(), pForward, pRight, pUp );
}
}
@@ -513,7 +483,7 @@ void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOri
float speed;
float velrun;
float velwalk;
int fLadder;
bool fLadder;
if ( m_flStepSoundTime > 0 )
{
@@ -548,12 +518,7 @@ void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOri
bool movingalongground = ( groundspeed > 0.0001f );
bool moving_fast_enough = ( speed >= velwalk );
#ifdef PORTAL
// In Portal we MUST play footstep sounds even when the player is moving very slowly
// This is used to count the number of footsteps they take in the challenge mode
// -Jeep
moving_fast_enough = true;
#endif
// To hear step sounds you must be either on a ladder or moving along the ground AND
// You must be moving fast enough
@@ -563,7 +528,7 @@ void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOri
// MoveHelper()->PlayerSetAnimation( PLAYER_WALK );
bWalking = speed < velrun;
bWalking = speed < velrun;
VectorCopy( vecOrigin, knee );
VectorCopy( vecOrigin, feet );
@@ -580,11 +545,7 @@ void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOri
SetStepSoundTime( STEPSOUNDTIME_ON_LADDER, bWalking );
}
#ifdef CSTRIKE_DLL
else if ( enginetrace->GetPointContents( knee ) & MASK_WATER ) // we want to use the knee for Cstrike, not the waist
#else
else if ( GetWaterLevel() == WL_Waist )
#endif // CSTRIKE_DLL
{
static int iSkipStep = 0;
@@ -680,7 +641,7 @@ void CBasePlayer::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, flo
return;
int nSide = m_Local.m_nStepside;
unsigned short stepSoundName = nSide ? psurface->sounds.stepleft : psurface->sounds.stepright;
unsigned short stepSoundName = nSide ? psurface->sounds.runStepLeft : psurface->sounds.runStepRight;
if ( !stepSoundName )
return;
@@ -698,10 +659,6 @@ void CBasePlayer::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, flo
{
IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps();
const char *pSoundName = physprops->GetString( stepSoundName );
// Give child classes an opportunity to override.
pSoundName = GetOverrideStepSound( pSoundName );
if ( !CBaseEntity::GetParametersForSound( pSoundName, params, NULL ) )
return;
@@ -727,27 +684,13 @@ void CBasePlayer::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, flo
EmitSound_t ep;
ep.m_nChannel = CHAN_BODY;
ep.m_pSoundName = params.soundname;
#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL )
if( TFGameRules()->IsMannVsMachineMode() )
{
ep.m_flVolume = params.volume;
}
else
{
ep.m_flVolume = fvol;
}
#else
ep.m_flVolume = fvol;
#endif
ep.m_SoundLevel = params.soundlevel;
ep.m_nFlags = 0;
ep.m_nPitch = params.pitch;
ep.m_pOrigin = &vecOrigin;
EmitSound( filter, entindex(), ep );
// Kyle says: ugggh. This function may as well be called "PerformPileOfDesperateGameSpecificFootstepHacks".
OnEmitFootstepSound( params, vecOrigin, fvol );
}
void CBasePlayer::UpdateButtonState( int nUserCmdButtonMask )
@@ -820,6 +763,11 @@ Vector CBasePlayer::Weapon_ShootPosition( )
return EyePosition();
}
bool CBasePlayer::Weapon_CanUse( CBaseCombatWeapon *pWeapon )
{
return true;
}
void CBasePlayer::SetAnimationExtension( const char *pExtension )
{
Q_strncpy( m_szAnimExtension, pExtension, sizeof(m_szAnimExtension) );
@@ -935,12 +883,6 @@ void CBasePlayer::SimulatePlayerSimulatedEntities( void )
continue;
}
#if defined( CLIENT_DLL )
if ( e->IsClientCreated() && prediction->InPrediction() && !prediction->IsFirstTimePredicted() )
{
continue;
}
#endif
Assert( e->IsPlayerSimulated() );
Assert( e->GetSimulatingPlayer() == this );
@@ -963,13 +905,6 @@ void CBasePlayer::SimulatePlayerSimulatedEntities( void )
continue;
}
#if defined( CLIENT_DLL )
if ( e->IsClientCreated() && prediction->InPrediction() && !prediction->IsFirstTimePredicted() )
{
continue;
}
#endif
Assert( e->IsPlayerSimulated() );
Assert( e->GetSimulatingPlayer() == this );
@@ -985,7 +920,7 @@ void CBasePlayer::SimulatePlayerSimulatedEntities( void )
//-----------------------------------------------------------------------------
void CBasePlayer::ClearPlayerSimulationList( void )
{
int c = m_SimulatedByThisPlayer.Size();
int c = m_SimulatedByThisPlayer.Count();
int i;
for ( i = c - 1; i >= 0; i-- )
@@ -1078,13 +1013,8 @@ CBaseEntity *CBasePlayer::FindUseEntity()
// A button, etc. can be made out of clip brushes, make sure it's +useable via a traceline, too.
int useableContents = MASK_SOLID | CONTENTS_DEBRIS | CONTENTS_PLAYERCLIP;
#ifdef CSTRIKE_DLL
useableContents = MASK_NPCSOLID_BRUSHONLY | MASK_OPAQUE_AND_NPCS;
#endif
#ifdef HL1_DLL
useableContents = MASK_SOLID;
#endif
#ifndef CLIENT_DLL
CBaseEntity *pFoundByTrace = NULL;
#endif
@@ -1542,11 +1472,6 @@ void CBasePlayer::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear,
if ( !pVehicle )
{
#if defined( CLIENT_DLL )
if( UseVR() )
g_ClientVirtualReality.CancelTorsoTransformOverride();
#endif
if ( IsObserver() )
{
CalcObserverView( eyeOrigin, eyeAngles, fov );
@@ -1560,10 +1485,36 @@ void CBasePlayer::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear,
{
CalcVehicleView( pVehicle, eyeOrigin, eyeAngles, zNear, zFar, fov );
}
// NVNT update fov on the haptics dll for input scaling.
#if defined( CLIENT_DLL )
if(IsLocalPlayer() && haptics)
haptics->UpdatePlayerFOV(fov);
// Set the follow bone if necessary
FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
static ConVarRef cvFollowBoneIndexVar( "cl_camera_follow_bone_index" );
CStudioHdr const* pHdr = GetModelPtr();
if ( pHdr &&
cvFollowBoneIndexVar.IsValid() &&
C_BasePlayer::GetLocalPlayer() == this )
{
int boneIdx = cvFollowBoneIndexVar.GetInt();
if ( boneIdx >= -1 && boneIdx < pHdr->numbones() )
{
extern Vector g_cameraFollowPos;
if ( boneIdx == -1 )
{
VectorCopy( GetRenderOrigin(), g_cameraFollowPos );
}
else if ( pHdr->pBone( boneIdx )->flags & BONE_USED_BY_ANYTHING )
{
MatrixPosition( m_BoneAccessor.GetBone( boneIdx ), g_cameraFollowPos );
}
}
}
}
#endif
}
@@ -1590,19 +1541,17 @@ void CBasePlayer::CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& f
}
#endif
VectorCopy( EyePosition(), eyeOrigin );
#ifdef SIXENSE
if ( g_pSixenseInput->IsEnabled() )
// TrackIR
if ( IsHeadTrackingEnabled() )
{
VectorCopy( EyePosition() + GetEyeOffset(), eyeOrigin );
VectorCopy( EyeAngles() + GetEyeAngleOffset(), eyeAngles );
}
else
{
VectorCopy( EyePosition(), eyeOrigin );
VectorCopy( EyeAngles(), eyeAngles );
}
#else
VectorCopy( EyeAngles(), eyeAngles );
#endif
#if defined( CLIENT_DLL )
if ( !prediction->InPrediction() )
@@ -1613,7 +1562,9 @@ void CBasePlayer::CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& f
// Snack off the origin before bob + water offset are applied
Vector vecBaseEyePosition = eyeOrigin;
QAngle baseEyeAngles = eyeAngles;
CalcViewBob( eyeOrigin );
CalcViewRoll( eyeAngles );
// Apply punch angle
@@ -1623,8 +1574,10 @@ void CBasePlayer::CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& f
if ( !prediction->InPrediction() )
{
// Shake it up baby!
vieweffects->CalcShake();
vieweffects->ApplyShake( eyeOrigin, eyeAngles, 1.0 );
GetViewEffects()->CalcShake();
GetViewEffects()->ApplyShake( eyeOrigin, eyeAngles, 1.0 );
// Tilting handled in CInput::AdjustAngles
}
#endif
@@ -1659,6 +1612,14 @@ void CBasePlayer::CalcVehicleView(
eyeOrigin = m_vecVehicleViewOrigin;
eyeAngles = m_vecVehicleViewAngles;
// TrackIR
if ( IsHeadTrackingEnabled() )
{
eyeAngles += GetEyeAngleOffset();
eyeOrigin += GetEyeOffset();
}
// TrackIR
#if defined( CLIENT_DLL )
fov = GetFOV();
@@ -1679,8 +1640,8 @@ void CBasePlayer::CalcVehicleView(
if ( !prediction->InPrediction() )
{
// Shake it up baby!
vieweffects->CalcShake();
vieweffects->ApplyShake( eyeOrigin, eyeAngles, 1.0 );
GetViewEffects()->CalcShake();
GetViewEffects()->ApplyShake( eyeOrigin, eyeAngles, 1.0 );
}
#endif
@@ -1767,6 +1728,9 @@ void CBasePlayer::CalcViewRoll( QAngle& eyeAngles )
eyeAngles[ROLL] += side;
}
void CBasePlayer::CalcViewBob( Vector& eyeOrigin )
{
}
void CBasePlayer::DoMuzzleFlash()
{
@@ -1833,7 +1797,7 @@ void CBasePlayer::SharedSpawn()
m_Local.m_flStepSize = sv_stepsize.GetFloat();
m_Local.m_bAllowAutoMovement = true;
m_nRenderFX = kRenderFxNone;
SetRenderFX( kRenderFxNone );
m_flNextAttack = gpGlobals->curtime;
m_flMaxspeed = 0.0f;
@@ -1849,11 +1813,6 @@ void CBasePlayer::SharedSpawn()
m_Local.m_flFallVelocity = 0;
SetBloodColor( BLOOD_COLOR_RED );
// NVNT inform haptic dll we have just spawned local player
#ifdef CLIENT_DLL
if(IsLocalPlayer() &&haptics)
haptics->LocalPlayerReset();
#endif
}
@@ -1866,7 +1825,7 @@ int CBasePlayer::GetDefaultFOV( void ) const
#if defined( CLIENT_DLL )
if ( GetObserverMode() == OBS_MODE_IN_EYE )
{
C_BasePlayer *pTargetPlayer = dynamic_cast<C_BasePlayer*>( GetObserverTarget() );
C_BasePlayer *pTargetPlayer = ToBasePlayer( GetObserverTarget() );
if ( pTargetPlayer && !pTargetPlayer->IsObserver() )
{
@@ -1876,8 +1835,6 @@ int CBasePlayer::GetDefaultFOV( void ) const
#endif
int iFOV = ( m_iDefaultFOV == 0 ) ? g_pGameRules->DefaultFOV() : m_iDefaultFOV;
if ( iFOV > MAX_FOV )
iFOV = MAX_FOV;
return iFOV;
}
@@ -2031,13 +1988,6 @@ void CBasePlayer::SetPlayerUnderwater( bool state )
{
if ( m_bPlayerUnderwater != state )
{
#if defined( WIN32 ) && !defined( _X360 )
// NVNT turn on haptic drag when underwater
if(state)
HapticSetDrag(this,1);
else
HapticSetDrag(this,0);
#endif
m_bPlayerUnderwater = state;
#ifdef CLIENT_DLL
@@ -2075,10 +2025,67 @@ bool fogparams_t::operator !=( const fogparams_t& other ) const
this->colorSecondaryLerpTo.Get() != other.colorSecondaryLerpTo.Get() ||
this->startLerpTo != other.startLerpTo ||
this->endLerpTo != other.endLerpTo ||
this->maxdensityLerpTo != other.maxdensityLerpTo ||
this->lerptime != other.lerptime ||
this->duration != other.duration )
this->duration != other.duration ||
this->HDRColorScale != other.HDRColorScale )
return true;
return false;
}
void CBasePlayer::IncrementEFNoInterpParity()
{
// Only matters in multiplayer
if ( gpGlobals->maxClients == 1 )
return;
m_ubEFNoInterpParity = (m_ubEFNoInterpParity + 1) % NOINTERP_PARITY_MAX;
}
int CBasePlayer::GetEFNoInterpParity() const
{
return (int)m_ubEFNoInterpParity;
}
void CBasePlayer::AddSplitScreenPlayer( CBasePlayer *pOther )
{
CHandle< CBasePlayer > h;
h = pOther;
if ( m_hSplitScreenPlayers.Find( h ) == m_hSplitScreenPlayers.InvalidIndex() )
{
m_hSplitScreenPlayers.AddToTail( h );
}
}
void CBasePlayer::RemoveSplitScreenPlayer( CBasePlayer *pOther )
{
CHandle< CBasePlayer > h;
h = pOther;
m_hSplitScreenPlayers.FindAndRemove( h );
}
CUtlVector< CHandle< CBasePlayer > > &CBasePlayer::GetSplitScreenPlayers()
{
return m_hSplitScreenPlayers;
}
//-----------------------------------------------------------------------------
// Purpose: Strips off IN_xxx flags from the player's input
//-----------------------------------------------------------------------------
void CBasePlayer::ForceButtons( int nButtons )
{
m_afButtonForced |= nButtons;
}
//-----------------------------------------------------------------------------
// Purpose: Re-enables stripped IN_xxx flags to the player's input
//-----------------------------------------------------------------------------
void CBasePlayer::UnforceButtons( int nButtons )
{
m_afButtonForced &= ~nButtons;
}
CBaseEntity* CBasePlayer::GetSoundscapeListener()
{
return this;
}
+27 -12
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -12,7 +12,10 @@
#endif
// PlayerUse defines
#define PLAYER_USE_RADIUS 80.f
#define CONE_45_DEGREES 0.707f
#define CONE_15_DEGREES 0.9659258f
#define CONE_90_DEGREES 0
@@ -32,16 +35,30 @@
#define DEATH_ANIMATION_TIME 3.0f
typedef struct
// multiplayer only
#define NOINTERP_PARITY_MAX 4
#define NOINTERP_PARITY_MAX_BITS 2
struct autoaim_params_t
{
Vector m_vecAutoAimDir; // The direction autoaim wishes to point.
Vector m_vecAutoAimPoint; // The point (world space) that autoaim is aiming at.
EHANDLE m_hAutoAimEntity; // The entity that autoaim is aiming at.
bool m_bAutoAimAssisting; // If this is true, autoaim is aiming at the target. If false, the player is naturally aiming.
bool m_bOnTargetNatural;
float m_fScale;
float m_fMaxDist;
} autoaim_params_t;
autoaim_params_t()
{
m_fScale = 0;
m_fMaxDist = 0;
m_fMaxDeflection = -1.0f;
m_bOnTargetQueryOnly = false;
}
Vector m_vecAutoAimDir; // Output: The direction autoaim wishes to point.
Vector m_vecAutoAimPoint; // Output: The point (world space) that autoaim is aiming at.
EHANDLE m_hAutoAimEntity; // Output: The entity that autoaim is aiming at.
float m_fScale; // Input:
float m_fMaxDist; // Input:
float m_fMaxDeflection; // Input:
bool m_bOnTargetQueryOnly; // Input: Don't do expensive assistance, just resolve m_bOnTargetNatural
bool m_bAutoAimAssisting; // Output: If this is true, autoaim is aiming at the target.
bool m_bOnTargetNatural; // Output: If true, the player is on target without assistance.
};
enum stepsoundtimes_t
{
@@ -51,8 +68,6 @@ enum stepsoundtimes_t
STEPSOUNDTIME_WATER_FOOT,
};
void CopySoundNameWithModifierToken( char *pchDest, const char *pchSource, int nMaxLenInChars, const char *pchToken );
// Shared header file for players
#if defined( CLIENT_DLL )
#define CBasePlayer C_BasePlayer
-26
View File
@@ -1,26 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "baseprojectile.h"
IMPLEMENT_NETWORKCLASS_ALIASED( BaseProjectile, DT_BaseProjectile )
BEGIN_NETWORK_TABLE( CBaseProjectile, DT_BaseProjectile )
END_NETWORK_TABLE()
//-----------------------------------------------------------------------------
// Purpose: Constructor.
//-----------------------------------------------------------------------------
CBaseProjectile::CBaseProjectile()
{
#ifdef GAME_DLL
m_iDestroyableHitCount = 0;
#endif
}
-53
View File
@@ -1,53 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BASEPROJECTILE_H
#define BASEPROJECTILE_H
#ifdef _WIN32
#pragma once
#endif
#include "cbase.h"
#ifdef GAME_DLL
#include "baseanimating.h"
#else
#include "c_baseanimating.h"
#endif
#ifdef CLIENT_DLL
#define CBaseProjectile C_BaseProjectile
#endif // CLIENT_DLL
//=============================================================================
//
// Base Projectile.
//
//=============================================================================
class CBaseProjectile : public CBaseAnimating
{
public:
DECLARE_CLASS( CBaseProjectile, CBaseAnimating );
DECLARE_NETWORKCLASS();
CBaseProjectile();
#ifdef GAME_DLL
virtual int GetDestroyableHitCount( void ) const { return m_iDestroyableHitCount; }
void IncrementDestroyableHitCount( void ) { ++m_iDestroyableHitCount; }
#endif // GAME_DLL
virtual bool IsDestroyable( void ) { return false; }
virtual void Destroy( bool bBlinkOut = true, bool bBreakRocket = false ) {}
protected:
#ifdef GAME_DLL
int m_iDestroyableHitCount;
#endif // GAME_DLL
};
#endif // BASEPROJECTILE_H
+43 -87
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -11,28 +11,22 @@
#if defined( CLIENT_DLL )
#include "iprediction.h"
#include "prediction.h"
#include "client_virtualreality.h"
#include "sourcevr/isourcevirtualreality.h"
#else
#include "vguiscreen.h"
#endif
#if defined( CLIENT_DLL ) && defined( SIXENSE )
#include "sixense/in_sixense.h"
#include "sixense/sixense_convars_extern.h"
#endif
#ifdef SIXENSE
extern ConVar in_forceuser;
#include "iclientmode.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define VIEWMODEL_ANIMATION_PARITY_BITS 3
#define SCREEN_OVERLAY_MATERIAL "vgui/screens/vgui_overlay"
#if defined( CLIENT_DLL )
ConVar viewmodel_offset_x( "viewmodel_offset_x", "0.0", FCVAR_ARCHIVE ); // the viewmodel offset from default in X
ConVar viewmodel_offset_y( "viewmodel_offset_y", "0.0", FCVAR_ARCHIVE ); // the viewmodel offset from default in Y
ConVar viewmodel_offset_z( "viewmodel_offset_z", "0.0", FCVAR_ARCHIVE ); // the viewmodel offset from default in Z
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@@ -42,8 +36,11 @@ CBaseViewModel::CBaseViewModel()
// NOTE: We do this here because the color is never transmitted for the view model.
m_nOldAnimationParity = 0;
m_EntClientFlags |= ENTCLIENTFLAG_ALWAYS_INTERPOLATE;
RenderWithViewModels( true );
#endif
SetRenderColor( 255, 255, 255, 255 );
SetRenderColor( 255, 255, 255 );
SetRenderAlpha( 255 );
// View model of this weapon
m_sVMName = NULL_STRING;
@@ -87,17 +84,9 @@ void CBaseViewModel::Spawn( void )
}
#if defined ( CSTRIKE_DLL ) && !defined ( CLIENT_DLL )
#define VGUI_CONTROL_PANELS
#endif
#if defined ( TF_DLL )
#define VGUI_CONTROL_PANELS
#endif
#ifdef INVASION_DLL
#define VGUI_CONTROL_PANELS
#endif
//-----------------------------------------------------------------------------
// Purpose:
@@ -225,9 +214,6 @@ void CBaseViewModel::SpawnControlPanels()
pScreen->SetActive( false );
pScreen->MakeVisibleOnlyToTeammates( false );
#ifdef INVASION_DLL
pScreen->SetOverlayMaterial( SCREEN_OVERLAY_MATERIAL );
#endif
pScreen->SetAttachedToViewModel( true );
int nScreen = m_hScreens.AddToTail( );
m_hScreens[nScreen].Set( pScreen );
@@ -390,6 +376,22 @@ void CBaseViewModel::CalcViewModelView( CBasePlayer *owner, const Vector& eyePos
QAngle vmangles = eyeAngles;
Vector vmorigin = eyePosition;
Vector vecRight;
Vector vecUp;
Vector vecForward;
AngleVectors( vmangoriginal, &vecForward, &vecRight, &vecUp );
//Vector vecOffset = Vector( viewmodel_offset_x.GetFloat(), viewmodel_offset_y.GetFloat(), viewmodel_offset_z.GetFloat() );
vmorigin += (vecForward * viewmodel_offset_y.GetFloat()) + (vecUp * viewmodel_offset_z.GetFloat()) + (vecRight * viewmodel_offset_x.GetFloat());
// TrackIR
if ( IsHeadTrackingEnabled() )
{
vmorigin = owner->EyePosition();
VectorAngles( owner->GetAutoaimVector( AUTOAIM_5DEGREES ), vmangoriginal );
vmangles = vmangoriginal;
}
// TrackIR
CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
//Allow weapon lagging
if ( pWeapon != NULL )
@@ -400,70 +402,31 @@ void CBaseViewModel::CalcViewModelView( CBasePlayer *owner, const Vector& eyePos
{
// add weapon-specific bob
pWeapon->AddViewmodelBob( this, vmorigin, vmangles );
#if defined ( CSTRIKE_DLL )
CalcViewModelLag( vmorigin, vmangles, vmangoriginal );
#endif
}
}
// Add model-specific bob even if no weapon associated (for head bob for off hand models)
AddViewModelBob( owner, vmorigin, vmangles );
#if !defined ( CSTRIKE_DLL )
// This was causing weapon jitter when rotating in updated CS:S; original Source had this in above InPrediction block 07/14/10
// Add lag
CalcViewModelLag( vmorigin, vmangles, vmangoriginal );
#endif
#if defined( CLIENT_DLL )
if ( !prediction->InPrediction() )
{
// Let the viewmodel shake at about 10% of the amplitude of the player's view
vieweffects->ApplyShake( vmorigin, vmangles, 0.1 );
ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( GetOwner() );
GetViewEffects()->ApplyShake( vmorigin, vmangles, 0.1 );
}
#endif
if( UseVR() )
{
g_ClientVirtualReality.OverrideViewModelTransform( vmorigin, vmangles, pWeapon && pWeapon->ShouldUseLargeViewModelVROverride() );
}
SetLocalOrigin( vmorigin );
SetLocalAngles( vmangles );
#ifdef SIXENSE
if( g_pSixenseInput->IsEnabled() && (owner->GetObserverMode()==OBS_MODE_NONE) && !UseVR() )
{
const float max_gun_pitch = 20.0f;
float viewmodel_fov_ratio = g_pClientMode->GetViewModelFOV()/owner->GetFOV();
QAngle gun_angles = g_pSixenseInput->GetViewAngleOffset() * -viewmodel_fov_ratio;
// Clamp pitch a bit to minimize seeing back of viewmodel
if( gun_angles[PITCH] < -max_gun_pitch )
{
gun_angles[PITCH] = -max_gun_pitch;
}
#ifdef WIN32 // ShouldFlipViewModel comes up unresolved on osx? Mabye because it's defined inline? fixme
if( ShouldFlipViewModel() )
{
gun_angles[YAW] *= -1.0f;
}
#endif
vmangles = EyeAngles() + gun_angles;
SetLocalAngles( vmangles );
}
#endif
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float g_fMaxViewModelLag = 1.5f;
void CBaseViewModel::CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& original_angles )
{
Vector vOriginalOrigin = origin;
@@ -483,9 +446,9 @@ void CBaseViewModel::CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& o
// If we start to lag too far behind, we'll increase the "catch up" speed. Solves the problem with fast cl_yawspeed, m_yaw or joysticks
// rotating quickly. The old code would slam lastfacing with origin causing the viewmodel to pop to a new position
float flDiff = vDifference.Length();
if ( (flDiff > g_fMaxViewModelLag) && (g_fMaxViewModelLag > 0.0f) )
if ( flDiff > 1.5f )
{
float flScale = flDiff / g_fMaxViewModelLag;
float flScale = flDiff / 1.5f;
flSpeed *= flScale;
}
@@ -498,6 +461,7 @@ void CBaseViewModel::CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& o
Assert( m_vecLastFacing.IsValid() );
}
Vector right, up;
AngleVectors( original_angles, &forward, &right, &up );
@@ -507,16 +471,11 @@ void CBaseViewModel::CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& o
else if ( pitch < -180.0f )
pitch += 360.0f;
if ( g_fMaxViewModelLag == 0.0f )
{
origin = vOriginalOrigin;
angles = vOriginalAngles;
}
//FIXME: These are the old settings that caused too many exposed polys on some models
VectorMA( origin, -pitch * 0.035f, forward, origin );
VectorMA( origin, -pitch * 0.03f, right, origin );
VectorMA( origin, -pitch * 0.02f, up, origin);
}
//-----------------------------------------------------------------------------
@@ -524,7 +483,7 @@ void CBaseViewModel::CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& o
//-----------------------------------------------------------------------------
#if defined( CLIENT_DLL )
extern void RecvProxy_EffectFlags( const CRecvProxyData *pData, void *pStruct, void *pOut );
void RecvProxy_SequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut );
void RecvProxy_ViewmodelSequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut );
#endif
//-----------------------------------------------------------------------------
@@ -558,42 +517,36 @@ IMPLEMENT_NETWORKCLASS_ALIASED( BaseViewModel, DT_BaseViewModel )
BEGIN_NETWORK_TABLE_NOBASE(CBaseViewModel, DT_BaseViewModel)
#if !defined( CLIENT_DLL )
SendPropModelIndex(SENDINFO(m_nModelIndex)),
SendPropEHandle (SENDINFO(m_hWeapon)),
SendPropInt (SENDINFO(m_nBody), 8),
SendPropInt (SENDINFO(m_nSkin), 10),
SendPropInt (SENDINFO(m_nSequence), 8, SPROP_UNSIGNED),
SendPropInt (SENDINFO(m_nViewModelIndex), VIEWMODEL_INDEX_BITS, SPROP_UNSIGNED),
SendPropFloat (SENDINFO(m_flPlaybackRate), 8, SPROP_ROUNDUP, -4.0, 12.0f),
SendPropInt (SENDINFO(m_fEffects), 10, SPROP_UNSIGNED),
SendPropInt (SENDINFO(m_fEffects), EF_MAX_BITS, SPROP_UNSIGNED),
SendPropInt (SENDINFO(m_nAnimationParity), 3, SPROP_UNSIGNED ),
SendPropEHandle (SENDINFO(m_hWeapon)),
SendPropEHandle (SENDINFO(m_hOwner)),
SendPropInt( SENDINFO( m_nNewSequenceParity ), EF_PARITY_BITS, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_nResetEventsParity ), EF_PARITY_BITS, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_nMuzzleFlashParity ), EF_MUZZLEFLASH_BITS, SPROP_UNSIGNED ),
#if !defined( INVASION_DLL ) && !defined( INVASION_CLIENT_DLL )
SendPropArray (SendPropFloat(SENDINFO_ARRAY(m_flPoseParameter), 8, 0, 0.0f, 1.0f), m_flPoseParameter),
#endif
#else
RecvPropInt (RECVINFO(m_nModelIndex)),
RecvPropEHandle (RECVINFO(m_hWeapon), RecvProxy_Weapon ),
RecvPropInt (RECVINFO(m_nSkin)),
RecvPropInt (RECVINFO(m_nBody)),
RecvPropInt (RECVINFO(m_nSequence), 0, RecvProxy_SequenceNum ),
RecvPropInt (RECVINFO(m_nSequence) ),
RecvPropInt (RECVINFO(m_nViewModelIndex)),
RecvPropFloat (RECVINFO(m_flPlaybackRate)),
RecvPropInt (RECVINFO(m_fEffects), 0, RecvProxy_EffectFlags ),
RecvPropInt (RECVINFO(m_nAnimationParity)),
RecvPropEHandle (RECVINFO(m_hWeapon), RecvProxy_Weapon ),
RecvPropEHandle (RECVINFO(m_hOwner)),
RecvPropInt( RECVINFO( m_nNewSequenceParity )),
RecvPropInt( RECVINFO( m_nResetEventsParity )),
RecvPropInt( RECVINFO( m_nMuzzleFlashParity )),
#if !defined( INVASION_DLL ) && !defined( INVASION_CLIENT_DLL )
RecvPropArray(RecvPropFloat(RECVINFO(m_flPoseParameter[0]) ), m_flPoseParameter ),
#endif
#endif
END_NETWORK_TABLE()
@@ -620,7 +573,10 @@ BEGIN_PREDICTION_DATA( CBaseViewModel )
END_PREDICTION_DATA()
void RecvProxy_SequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut )
// This needed to be done as a proxy for the surrounding box auto update when animations change.
// This doesn't have to be done for view models as they don't affect the bounding box and it was
// causing some timing problems with our world to view model under the covers swap.
void RecvProxy_ViewmodelSequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CBaseViewModel *model = (CBaseViewModel *)pStruct;
if (pData->m_Value.m_Int != model->GetSequence())
+38 -49
View File
@@ -1,9 +1,9 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
//===========================================================================//
#ifndef BASEVIEWMODEL_SHARED_H
#define BASEVIEWMODEL_SHARED_H
@@ -15,7 +15,6 @@
#include "utlvector.h"
#include "baseplayer_shared.h"
#include "shared_classnames.h"
#include "econ/ihasowner.h"
class CBaseCombatWeapon;
class CBaseCombatCharacter;
@@ -28,7 +27,7 @@ class CVGuiScreen;
#define VIEWMODEL_INDEX_BITS 1
class CBaseViewModel : public CBaseAnimating, public IHasOwner
class CBaseViewModel : public CBaseAnimating
{
DECLARE_CLASS( CBaseViewModel, CBaseAnimating );
public:
@@ -78,8 +77,6 @@ public:
void ShowControlPanells( bool show );
virtual CBaseCombatWeapon *GetOwningWeapon( void );
virtual CBaseEntity *GetOwnerViaInterface( void ) { return GetOwner(); }
virtual bool IsSelfAnimating()
{
@@ -88,14 +85,8 @@ public:
Vector m_vecLastFacing;
// Only support prediction in TF2 for now
#if defined( INVASION_DLL ) || defined( INVASION_CLIENT_DLL )
// All predicted weapons need to implement and return true
virtual bool IsPredicted( void ) const
{
return true;
}
#endif
virtual bool IsViewModel() const { return true; }
virtual bool IsViewModelOrAttachment() const { return true; }
#if !defined( CLIENT_DLL )
virtual int UpdateTransmitState( void );
@@ -103,27 +94,13 @@ public:
virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways );
#else
virtual RenderGroup_t GetRenderGroup();
// Only supported in TF2 right now
#if defined( INVASION_CLIENT_DLL )
virtual bool ShouldPredict( void )
{
if ( GetOwner() && GetOwner() == C_BasePlayer::GetLocalPlayer() )
return true;
return BaseClass::ShouldPredict();
}
#endif
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual C_BasePlayer *GetPredictionOwner( void );
virtual bool Interpolate( float currentTime );
bool ShouldFlipViewModel();
@@ -132,13 +109,11 @@ public:
virtual void ApplyBoneMatrixTransform( matrix3x4_t& transform );
virtual bool ShouldDraw();
virtual int DrawModel( int flags );
virtual int InternalDrawModel( int flags );
int DrawOverriddenViewmodel( int flags );
virtual int GetFxBlend( void );
virtual bool IsTransparent( void );
virtual bool UsesPowerOfTwoFrameBufferTexture( void );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
int DrawOverriddenViewmodel( int flags, const RenderableInstance_t &instance );
virtual uint8 OverrideAlphaModulation( uint8 nAlpha );
RenderableTranslucencyType_t ComputeTranslucencyType( void );
// Should this object cast shadows?
virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; }
@@ -148,9 +123,6 @@ public:
return false;
}
// Add entity to visible view models list?
virtual void AddEntity( void );
virtual void GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS]);
// See C_StudioModel's definition of this.
@@ -158,11 +130,10 @@ public:
// (inherited from C_BaseAnimating)
virtual void FormatViewModelAttachment( int nAttachment, matrix3x4_t &attachmentToWorld );
virtual bool IsViewModel() const;
CBaseCombatWeapon *GetWeapon() const { return m_hWeapon.Get(); }
#ifdef CLIENT_DLL
virtual bool ShouldResetSequenceOnNewModel( void ) { return false; }
// Attachments
@@ -171,15 +142,23 @@ public:
virtual bool GetAttachment( int number, Vector &origin );
virtual bool GetAttachment( int number, Vector &origin, QAngle &angles );
virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel );
#endif
private:
CBaseViewModel( const CBaseViewModel & ); // not defined, not accessible
#endif
private:
typedef CHandle< CBaseCombatWeapon > CBaseCombatWeaponHandle;
// FTYPEDESC_INSENDTABLE STUFF
CNetworkVar( int, m_nViewModelIndex ); // Which viewmodel is it?
// Used to force restart on client, only needs a few bits
CNetworkVar( int, m_nAnimationParity );
CNetworkVar( CBaseCombatWeaponHandle, m_hWeapon );
// FTYPEDESC_INSENDTABLE STUFF (end)
CNetworkHandle( CBaseEntity, m_hOwner ); // Player or AI carrying this weapon
// soonest time Update will call WeaponIdle
@@ -187,9 +166,6 @@ private:
Activity m_Activity;
// Used to force restart on client, only needs a few bits
CNetworkVar( int, m_nAnimationParity );
// Weapon art
string_t m_sVMName; // View model of this weapon
string_t m_sAnimationPrefix; // Prefix of the animations that should be used by the player carrying this weapon
@@ -199,12 +175,25 @@ private:
#endif
typedef CHandle< CBaseCombatWeapon > CBaseCombatWeaponHandle;
CNetworkVar( CBaseCombatWeaponHandle, m_hWeapon );
// Control panel
typedef CHandle<CVGuiScreen> ScreenHandle_t;
CUtlVector<ScreenHandle_t> m_hScreens;
};
inline CBaseViewModel *ToBaseViewModel( CBaseAnimating *pAnim )
{
if ( pAnim && pAnim->IsViewModel() )
return assert_cast<CBaseViewModel *>(pAnim);
return NULL;
}
inline CBaseViewModel *ToBaseViewModel( CBaseEntity *pEntity )
{
if ( !pEntity )
return NULL;
return ToBaseViewModel(pEntity->GetBaseAnimating());
}
#endif // BASEVIEWMODEL_SHARED_H
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
+76 -109
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc.
//
@@ -22,9 +22,7 @@
#include "viewrender.h"
#include "view.h"
#ifdef PORTAL
#include "c_prop_portal.h"
#endif //ifdef PORTAL
#endif
@@ -34,17 +32,23 @@
#define BEAM_DEFAULT_HALO_SCALE 10
#if !defined( CLIENT_DLL )
// Lightning target, just alias landmark
//-----------------------------------------------------------------------------
// info targets are like point entities except you can force them to spawn on the client
//-----------------------------------------------------------------------------
class CInfoTarget : public CPointEntity
{
public:
DECLARE_CLASS( CInfoTarget, CPointEntity );
void Spawn( void );
virtual int UpdateTransmitState();
};
//info targets are like point entities except you can force them to spawn on the client
//-----------------------------------------------------------------------------
// Force transmission
//-----------------------------------------------------------------------------
void CInfoTarget::Spawn( void )
{
BaseClass::Spawn();
@@ -55,6 +59,19 @@ void CInfoTarget::Spawn( void )
}
}
//-----------------------------------------------------------------------------
// Purpose: Always transmitted to clients
//-----------------------------------------------------------------------------
int CInfoTarget::UpdateTransmitState()
{
// Spawn flags 2 means we always transmit
if ( HasSpawnFlags(0x02) )
return SetTransmitState( FL_EDICT_ALWAYS );
return BaseClass::UpdateTransmitState();
}
LINK_ENTITY_TO_CLASS( info_target, CInfoTarget );
#endif
@@ -95,7 +112,7 @@ void RecvProxy_Beam_ScrollSpeed( const CRecvProxyData *pData, void *pStruct, voi
beam->m_fSpeed = val;
}
#else
#if !defined( NO_ENTITY_PREDICTION )
#if !defined( NO_ENTITY_PREDICTION ) && defined( USE_PREDICTABLEID )
static void* SendProxy_SendPredictableId( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID )
{
CBaseEntity *pEntity = (CBaseEntity *)pStruct;
@@ -132,7 +149,7 @@ LINK_ENTITY_TO_CLASS( beam, CBeam );
// This table encodes the CBeam data.
IMPLEMENT_NETWORKCLASS_ALIASED( Beam, DT_Beam )
#if !defined( NO_ENTITY_PREDICTION )
#if !defined( NO_ENTITY_PREDICTION ) && defined( USE_PREDICTABLEID )
BEGIN_NETWORK_TABLE_NOBASE( CBeam, DT_BeamPredictableId )
#if !defined( CLIENT_DLL )
SendPropPredictableId( SENDINFO( m_PredictableID ) ),
@@ -172,17 +189,14 @@ BEGIN_NETWORK_TABLE_NOBASE( CBeam, DT_Beam )
SendPropFloat (SENDINFO(m_flFrameRate), 10, SPROP_ROUNDUP, -25.0f, 25.0f ),
SendPropFloat (SENDINFO(m_flHDRColorScale), 0, SPROP_NOSCALE, 0.0f, 100.0f ),
SendPropFloat (SENDINFO(m_flFrame), 20, SPROP_ROUNDDOWN | SPROP_CHANGES_OFTEN, 0.0f, 256.0f),
SendPropInt (SENDINFO(m_clrRender), 32, SPROP_UNSIGNED | SPROP_CHANGES_OFTEN ),
SendPropInt (SENDINFO(m_clrRender), 32, SPROP_UNSIGNED | SPROP_CHANGES_OFTEN, SendProxy_Color32ToInt32 ),
SendPropInt (SENDINFO(m_nClipStyle), CBeam::kBEAMCLIPSTYLE_NUMBITS+1, SPROP_UNSIGNED ),
SendPropVector (SENDINFO(m_vecEndPos), -1, SPROP_COORD ),
#ifdef PORTAL
SendPropBool (SENDINFO(m_bDrawInMainRender) ),
SendPropBool (SENDINFO(m_bDrawInPortalRender) ),
#endif
SendPropModelIndex(SENDINFO(m_nModelIndex) ),
SendPropVector (SENDINFO(m_vecOrigin), 19, SPROP_CHANGES_OFTEN, MIN_COORD_INTEGER, MAX_COORD_INTEGER),
SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent) ),
SendPropInt (SENDINFO(m_nMinDXLevel), 8, SPROP_UNSIGNED ),
#if !defined( NO_ENTITY_PREDICTION )
#if !defined( NO_ENTITY_PREDICTION ) && defined( USE_PREDICTABLEID )
SendPropDataTable( "beampredictable_id", 0, &REFERENCE_SEND_TABLE( DT_BeamPredictableId ), SendProxy_SendPredictableId ),
#endif
@@ -210,21 +224,18 @@ BEGIN_NETWORK_TABLE_NOBASE( CBeam, DT_Beam )
RecvPropFloat (RECVINFO(m_fSpeed), 0, RecvProxy_Beam_ScrollSpeed ),
RecvPropFloat(RECVINFO(m_flFrameRate)),
RecvPropFloat(RECVINFO(m_flHDRColorScale)),
RecvPropInt(RECVINFO(m_clrRender)),
RecvPropInt(RECVINFO(m_clrRender), 0, RecvProxy_Int32ToColor32 ),
RecvPropInt(RECVINFO(m_nRenderFX)),
RecvPropInt(RECVINFO(m_nRenderMode)),
RecvPropFloat(RECVINFO(m_flFrame)),
RecvPropInt(RECVINFO(m_nClipStyle)),
RecvPropVector(RECVINFO(m_vecEndPos)),
#ifdef PORTAL
RecvPropBool(RECVINFO(m_bDrawInMainRender) ),
RecvPropBool(RECVINFO(m_bDrawInPortalRender) ),
#endif
RecvPropInt(RECVINFO(m_nModelIndex)),
RecvPropInt(RECVINFO(m_nMinDXLevel)),
RecvPropVector(RECVINFO_NAME(m_vecNetworkOrigin, m_vecOrigin)),
RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
#if !defined( NO_ENTITY_PREDICTION )
#if !defined( NO_ENTITY_PREDICTION ) && defined( USE_PREDICTABLEID )
RecvPropDataTable( "beampredictable_id", 0, 0, &REFERENCE_RECV_TABLE( DT_BeamPredictableId ) ),
#endif
@@ -239,7 +250,6 @@ BEGIN_DATADESC( CBeam )
DEFINE_FIELD( m_nNumBeamEnts, FIELD_INTEGER ),
DEFINE_ARRAY( m_hAttachEntity, FIELD_EHANDLE, MAX_BEAM_ENTS ),
DEFINE_ARRAY( m_nAttachIndex, FIELD_INTEGER, MAX_BEAM_ENTS ),
DEFINE_FIELD( m_nMinDXLevel, FIELD_INTEGER ),
DEFINE_FIELD( m_fWidth, FIELD_FLOAT ),
DEFINE_FIELD( m_fEndWidth, FIELD_FLOAT ),
@@ -262,10 +272,7 @@ BEGIN_DATADESC( CBeam )
DEFINE_KEYFIELD( m_nDissolveType, FIELD_INTEGER, "dissolvetype" ),
#ifdef PORTAL
DEFINE_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN ),
#endif
// Inputs
DEFINE_INPUTFUNC( FIELD_FLOAT, "Width", InputWidth ),
@@ -302,12 +309,8 @@ BEGIN_PREDICTION_DATA( CBeam )
DEFINE_PRED_FIELD( m_flFrameRate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_clrRender, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_nMinDXLevel, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD_TOL( m_vecEndPos, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.125f ),
#ifdef PORTAL
DEFINE_PRED_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
#endif
DEFINE_PRED_FIELD( m_nModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
DEFINE_PRED_FIELD_TOL( m_vecOrigin, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.125f ),
@@ -328,19 +331,16 @@ CBeam::CBeam( void )
m_vecEndPos.Init();
#endif
m_nMinDXLevel = 0;
m_flHDRColorScale = 1.0f; // default value.
#if !defined( CLIENT_DLL )
m_nDissolveType = -1;
#else
m_queryHandleHalo = 0;
AddToEntityList(ENTITY_LIST_SIMULATE);
#endif
#ifdef PORTAL
m_bDrawInMainRender = true;
m_bDrawInPortalRender = true;
#endif
}
//-----------------------------------------------------------------------------
@@ -423,7 +423,10 @@ void CBeam::SetStartEntity( CBaseEntity *pEntity )
m_hAttachEntity.Set( 0, pEntity );
SetOwnerEntity( pEntity );
RelinkBeam();
pEntity->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
if ( pEntity )
{
pEntity->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
}
}
void CBeam::SetEndEntity( CBaseEntity *pEntity )
@@ -432,7 +435,10 @@ void CBeam::SetEndEntity( CBaseEntity *pEntity )
m_hAttachEntity.Set( m_nNumBeamEnts-1, pEntity );
m_hEndEntity = pEntity;
RelinkBeam();
pEntity->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
if ( pEntity )
{
pEntity->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
}
}
@@ -476,7 +482,7 @@ const Vector &CBeam::GetAbsStartPos( void ) const
{
if ( GetType() == BEAM_ENTS && GetStartEntity() )
{
edict_t *pent = engine->PEntityOfEntIndex( GetStartEntity() );
edict_t *pent = INDEXENT( GetStartEntity() );
CBaseEntity *ent = CBaseEntity::Instance( pent );
if ( !ent )
{
@@ -492,7 +498,7 @@ const Vector &CBeam::GetAbsEndPos( void ) const
{
if ( GetType() != BEAM_POINTS && GetType() != BEAM_HOSE && GetEndEntity() )
{
edict_t *pent = engine->PEntityOfEntIndex( GetEndEntity() );
edict_t *pent = INDEXENT( GetEndEntity() );
CBaseEntity *ent = CBaseEntity::Instance( pent );
if ( ent )
return ent->GetAbsOrigin();
@@ -691,19 +697,7 @@ void CBeam::RelinkBeam( void )
Vector vecAbsExtra1, vecAbsExtra2;
bool bUseExtraPoints = false;
#ifdef PORTAL
CBaseEntity *pStartEntity = GetStartEntityPtr();
CTraceFilterSkipClassname traceFilter( pStartEntity, "prop_energy_ball", COLLISION_GROUP_NONE );
ITraceFilter *pEntityBeamTraceFilter = NULL;
if ( pStartEntity )
pEntityBeamTraceFilter = pStartEntity->GetBeamTraceFilter();
CTraceFilterChain traceFilterChain( &traceFilter, pEntityBeamTraceFilter );
bUseExtraPoints = UTIL_Portal_Trace_Beam( this, startPos, endPos, vecAbsExtra1, vecAbsExtra2, &traceFilterChain );
#endif
// UNDONE: Should we do this to make the boxes smaller?
//SetAbsOrigin( startPos );
@@ -780,7 +774,6 @@ void CBeam::BeamDamage( trace_t *ptr )
VectorNormalize( dir );
int nDamageType = DMG_ENERGYBEAM;
#ifndef HL1_DLL
if (m_nDissolveType == 0)
{
nDamageType = DMG_DISSOLVE;
@@ -789,7 +782,6 @@ void CBeam::BeamDamage( trace_t *ptr )
{
nDamageType = DMG_DISSOLVE | DMG_SHOCK;
}
#endif
CTakeDamageInfo info( this, this, m_flDamage * (gpGlobals->curtime - m_flFireTime), nDamageType );
CalculateMeleeDamageForce( &info, dir, ptr->endpos );
@@ -838,19 +830,19 @@ void CBeam::InputWidth( inputdata_t &inputdata )
void CBeam::InputColorRedValue( inputdata_t &inputdata )
{
int nNewColor = clamp( FastFloatToSmallInt(inputdata.value.Float()), 0, 255 );
int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
SetColor( nNewColor, m_clrRender->g, m_clrRender->b );
}
void CBeam::InputColorGreenValue( inputdata_t &inputdata )
{
int nNewColor =clamp( FastFloatToSmallInt(inputdata.value.Float()), 0, 255 );
int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
SetColor( m_clrRender->r, nNewColor, m_clrRender->b );
}
void CBeam::InputColorBlueValue( inputdata_t &inputdata )
{
int nNewColor = clamp( FastFloatToSmallInt(inputdata.value.Float()), 0, 255 );
int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
SetColor( m_clrRender->r, m_clrRender->g, nNewColor );
}
@@ -963,7 +955,7 @@ bool CBeam::OnPredictedEntityRemove( bool isbeingremoved, C_BaseEntity *predicte
extern bool g_bRenderingScreenshot;
extern ConVar r_drawviewmodel;
int CBeam::DrawModel( int flags )
int CBeam::DrawModel( int flags, const RenderableInstance_t &instance )
{
if ( !m_bReadyToDraw )
return 0;
@@ -974,13 +966,7 @@ int CBeam::DrawModel( int flags )
if ( CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE )
return 0;
#ifdef PORTAL
if ( ( !g_pPortalRender->IsRenderingPortal() && !m_bDrawInMainRender ) ||
( g_pPortalRender->IsRenderingPortal() && !m_bDrawInPortalRender ) )
{
return 0;
}
#endif //#ifdef PORTAL
// Tracker 16432: If rendering a savegame screenshot don't draw beams
// who have viewmodels as their attached entity
@@ -989,7 +975,7 @@ int CBeam::DrawModel( int flags )
// If the beam is attached
for (int i=0;i<MAX_BEAM_ENTS;i++)
{
C_BaseViewModel *vm = dynamic_cast<C_BaseViewModel *>(m_hAttachEntity[i].Get());
C_BaseViewModel *vm = ToBaseViewModel(m_hAttachEntity[i].Get());
if ( vm )
{
return 0;
@@ -997,7 +983,7 @@ int CBeam::DrawModel( int flags )
}
}
beams->DrawBeam( this );
beams->DrawBeam( this, instance );
return 0;
}
@@ -1014,12 +1000,11 @@ void CBeam::OnDataChanged( DataUpdateType_t updateType )
C_BaseEntity *pEnt = m_hAttachEntity[i].Get();
if ( pEnt )
{
C_BaseCombatWeapon *pWpn = dynamic_cast<C_BaseCombatWeapon *>(pEnt);
if ( pWpn && pWpn->ShouldDrawUsingViewModel() )
C_BaseCombatWeapon *pWpn = pEnt->MyCombatWeaponPointer();
if ( pWpn && pWpn->IsCarriedByLocalPlayer() )
{
C_BasePlayer *player = ToBasePlayer( pWpn->GetOwner() );
// Use GetRenderedWeaponModel() instead?
C_BaseViewModel *pViewModel = player ? player->GetViewModel( 0 ) : NULL;
if ( pViewModel )
{
@@ -1034,45 +1019,39 @@ void CBeam::OnDataChanged( DataUpdateType_t updateType )
Vector mins, maxs;
ComputeBounds( mins, maxs );
SetCollisionBounds( mins, maxs );
AddToEntityList( ENTITY_LIST_SIMULATE );
}
bool CBeam::IsTransparent( void )
{
return true;
}
bool CBeam::ShouldDraw()
{
if ( m_nMinDXLevel != 0 )
{
if ( m_nMinDXLevel > g_pMaterialSystemHardwareConfig->GetDXSupportLevel() )
return false;
}
return BaseClass::ShouldDraw();
RenderableTranslucencyType_t CBeam::ComputeTranslucencyType()
{
return RENDERABLE_IS_TRANSLUCENT;
}
//-----------------------------------------------------------------------------
// Purpose: Adds to beam entity list
//-----------------------------------------------------------------------------
void CBeam::AddEntity( void )
bool CBeam::Simulate( void )
{
bool bRet = false;
// If set to invisible, skip. Do this before resetting the entity pointer so it has
// valid data to decide whether it's visible.
if ( !ShouldDraw() )
if ( ShouldDraw() )
{
return;
}
//FIXME: If we're hooked up to an attachment point, then recompute our bounds every frame
if ( m_hAttachEntity[0].Get() || m_hAttachEntity[1].Get() )
{
// Compute the bounds here...
Vector mins, maxs;
ComputeBounds( mins, maxs );
SetCollisionBounds( mins, maxs );
}
//FIXME: If we're hooked up to an attachment point, then recompute our bounds every frame
if ( m_hAttachEntity[0].Get() || m_hAttachEntity[1].Get() )
{
// Compute the bounds here...
Vector mins, maxs;
ComputeBounds( mins, maxs );
SetCollisionBounds( mins, maxs );
bRet = true;
}
MoveToLastReceivedPosition();
MoveToLastReceivedPosition();
}
BaseClass::Simulate();
return bRet;
}
//-----------------------------------------------------------------------------
@@ -1087,19 +1066,7 @@ void CBeam::ComputeBounds( Vector& mins, Vector& maxs )
bool bUseExtraPoints = false;
Vector vecAbsExtra1, vecAbsExtra2;
#ifdef PORTAL
CBaseEntity *pStartEntity = GetStartEntityPtr();
CTraceFilterSkipClassname traceFilter( pStartEntity, "prop_energy_ball", COLLISION_GROUP_NONE );
ITraceFilter *pEntityBeamTraceFilter = NULL;
if ( pStartEntity )
pEntityBeamTraceFilter = pStartEntity->GetBeamTraceFilter();
CTraceFilterChain traceFilterChain( &traceFilter, pEntityBeamTraceFilter );
bUseExtraPoints = UTIL_Portal_Trace_Beam( this, vecAbsStart, vecAbsEnd, vecAbsExtra1, vecAbsExtra2, &traceFilterChain );
#endif
switch( GetType() )
{
+25 -24
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -43,6 +43,7 @@
#include "c_pixel_visibility.h"
#endif
// I've seen CBeams glitter in the dark near Tannhauser gate...
class CBeam : public CBaseEntity
{
DECLARE_CLASS( CBeam, CBaseEntity );
@@ -105,8 +106,6 @@ public:
void SetFireTime( float flFireTime );
void SetFrameRate( float flFrameRate ) { m_flFrameRate = flFrameRate; }
void SetMinDXLevel( int nMinDXLevel ) { m_nMinDXLevel = nMinDXLevel; }
void TurnOn( void );
void TurnOff( void );
@@ -156,29 +155,34 @@ public:
void LiveForTime( float time );
void BeamDamageInstant( trace_t *ptr, float damage );
// Only supported in TF2 right now
#if defined( INVASION_CLIENT_DLL )
virtual bool ShouldPredict( void )
{
return true;
}
#endif
virtual const char *GetDecalName( void ) { return "BigShot"; }
// specify whether the beam should always go all the way to
// the end point, or clip against geometry, or clip against
// geometry and NPCs. This is only used by env_beams at present, but
// need to be in this CBeam because of the way it affects drawing.
enum BeamClipStyle_t
{
kNOCLIP = 0, // don't clip (default)
kGEOCLIP = 1,
kMODELCLIP = 2,
kBEAMCLIPSTYLE_NUMBITS = 2, //< number of bits needed to represent this object
};
inline BeamClipStyle_t GetClipStyle() const { return m_nClipStyle; }
#if defined( CLIENT_DLL )
// IClientEntity overrides.
public:
virtual int DrawModel( int flags );
virtual bool IsTransparent( void );
virtual bool ShouldDraw();
virtual bool IgnoresZBuffer( void ) const { return true; }
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual RenderableTranslucencyType_t ComputeTranslucencyType();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual bool OnPredictedEntityRemove( bool isbeingremoved, C_BaseEntity *predicted );
// Add beam to visible entities list?
virtual void AddEntity( void );
virtual bool Simulate( void );
virtual bool ShouldReceiveProjectedTextures( int flags )
{
return false;
@@ -226,8 +230,8 @@ private:
CNetworkVar( float, m_fAmplitude );
CNetworkVar( float, m_fStartFrame );
CNetworkVar( float, m_fSpeed );
CNetworkVar( int, m_nMinDXLevel );
CNetworkVar( float, m_flFrame );
CNetworkVar( BeamClipStyle_t, m_nClipStyle );
CNetworkVector( m_vecEndPos );
@@ -238,10 +242,7 @@ private:
#endif
public:
#ifdef PORTAL
CNetworkVar( bool, m_bDrawInMainRender );
CNetworkVar( bool, m_bDrawInPortalRender );
#endif //#ifdef PORTAL
};
#if !defined( CLIENT_DLL )
@@ -338,12 +339,12 @@ inline void CBeam::SetNoise( float amplitude )
inline void CBeam::SetColor( int r, int g, int b )
{
SetRenderColor( r, g, b, GetRenderColor().a );
SetRenderColor( r, g, b );
}
inline void CBeam::SetBrightness( int brightness )
{
SetRenderColorA( brightness );
SetRenderAlpha( brightness );
}
inline void CBeam::SetFrame( float frame )
@@ -415,7 +416,7 @@ inline float CBeam::GetNoise( void ) const
inline int CBeam::GetBrightness( void ) const
{
return GetRenderColor().a;
return GetRenderAlpha();
}
inline float CBeam::GetFrame( void ) const
+353
View File
@@ -0,0 +1,353 @@
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "blob_networkbypass.h"
#include "ispsharedmemory.h"
#ifndef CLIENT_DLL
#include "npc_surface.h"
#endif
#include "tier0/memdbgon.h"
BlobNetworkBypass_t *g_pBlobNetworkBypass;
#ifdef CLIENT_DLL
CInterpolatedVar< Vector > s_PositionInterpolators[BLOB_MAX_LEVEL_PARTICLES];
CInterpolatedVar< float > s_RadiusInterpolators[BLOB_MAX_LEVEL_PARTICLES];
CInterpolatedVar< Vector > s_ClosestSurfDirInterpolators[BLOB_MAX_LEVEL_PARTICLES];
BlobParticleInterpolation_t g_BlobParticleInterpolation;
void BlobNetworkBypass_CustomDemoDataCallback( uint8 *pData, size_t iSize );
#endif
class CBlobParticleNetworkBypassAutoGame : public CAutoGameSystemPerFrame
{
public:
virtual bool Init()
{
m_pSharedMemory = engine->GetSinglePlayerSharedMemorySpace( "BlobParticleNetworkBypass" );
m_pSharedMemory->Init( sizeof( BlobNetworkBypass_t ) );
g_pBlobNetworkBypass = (BlobNetworkBypass_t *)m_pSharedMemory->Base();
#ifdef CLIENT_DLL
float fInterpAmount = TICK_INTERVAL * (C_BaseEntity::IsSimulatingOnAlternateTicks()?2:1);
for( int i = 0; i != BLOB_MAX_LEVEL_PARTICLES; ++i )
{
s_PositionInterpolators[i].Setup( &g_BlobParticleInterpolation.vInterpolatedPositions[i], LATCH_ANIMATION_VAR ); //LATCH_SIMULATION_VAR, LATCH_ANIMATION_VAR
s_PositionInterpolators[i].SetInterpolationAmount( fInterpAmount ); //fInterpAmount
s_RadiusInterpolators[i].Setup( &g_BlobParticleInterpolation.vInterpolatedRadii[i], LATCH_ANIMATION_VAR ); //LATCH_SIMULATION_VAR, LATCH_ANIMATION_VAR
s_RadiusInterpolators[i].SetInterpolationAmount( fInterpAmount ); //fInterpAmount
s_ClosestSurfDirInterpolators[i].Setup( &g_BlobParticleInterpolation.vInterpolatedClosestSurfDir[i], LATCH_ANIMATION_VAR ); //LATCH_SIMULATION_VAR, LATCH_ANIMATION_VAR
s_ClosestSurfDirInterpolators[i].SetInterpolationAmount( fInterpAmount ); //fInterpAmount
}
m_iOldHighestIndexUsed = 0;
memset( &m_bOldInUse, 0, sizeof( m_bOldInUse ) );
engine->RegisterDemoCustomDataCallback( MAKE_STRING( "BlobNetworkBypass_CustomDemoDataCallback" ), BlobNetworkBypass_CustomDemoDataCallback );
#endif
return true;
}
virtual void Shutdown()
{
m_pSharedMemory->Release();
m_pSharedMemory = NULL;
g_pBlobNetworkBypass = NULL;
}
#ifdef CLIENT_DLL
virtual void PreRender( void );
unsigned int m_iOldHighestIndexUsed;
CBitVec<BLOB_MAX_LEVEL_PARTICLES> m_bOldInUse;
#else
virtual void PreClientUpdate()
{
CNPC_Surface::UpdateBypassParticleData();
}
#endif
ISPSharedMemory *m_pSharedMemory;
};
static CBlobParticleNetworkBypassAutoGame s_CBPNBAG;
#ifndef CLIENT_DLL
int AllocateBlobNetworkBypassIndex( void )
{
int retval;
if( g_pBlobNetworkBypass->iNumParticlesAllocated == g_pBlobNetworkBypass->iHighestIndexUsed )
{
//no holes in the allocations, allocate from the end
retval = g_pBlobNetworkBypass->iHighestIndexUsed;
++g_pBlobNetworkBypass->iHighestIndexUsed;
}
else
{
CBitVec<BLOB_MAX_LEVEL_PARTICLES> notUsed;
g_pBlobNetworkBypass->bCurrentlyInUse.Not( &notUsed );
retval = notUsed.FindNextSetBit( 0 );
Assert( retval < (int)g_pBlobNetworkBypass->iHighestIndexUsed );
}
++g_pBlobNetworkBypass->iNumParticlesAllocated;
g_pBlobNetworkBypass->bCurrentlyInUse.Set( retval );
return retval;
}
void ReleaseBlobNetworkBypassIndex( int iIndex )
{
Assert( g_pBlobNetworkBypass->bCurrentlyInUse.IsBitSet( iIndex ) );
g_pBlobNetworkBypass->bCurrentlyInUse.Clear( iIndex );
g_pBlobNetworkBypass->vParticlePositions[iIndex] = vec3_origin;
g_pBlobNetworkBypass->vParticleRadii[iIndex] = 1.0f;
g_pBlobNetworkBypass->vParticleClosestSurfDir[iIndex] = vec3_origin;
--g_pBlobNetworkBypass->iNumParticlesAllocated;
Assert( iIndex < (int)g_pBlobNetworkBypass->iHighestIndexUsed );
if( iIndex == ((int)g_pBlobNetworkBypass->iHighestIndexUsed - 1) )
{
//search for newest high index
int iOldHighestIntUsed = g_pBlobNetworkBypass->iHighestIndexUsed / BITS_PER_INT;
for( int i = iOldHighestIntUsed; i >= 0; --i )
{
if( (g_pBlobNetworkBypass->bCurrentlyInUse.GetDWord( i ) & (-1)) != 0 )
{
int iLowBit = i * BITS_PER_INT;
int iHighBit = iLowBit + BITS_PER_INT;
for( int j = iHighBit; --j >= iLowBit; )
{
if( g_pBlobNetworkBypass->bCurrentlyInUse.IsBitSet( j ) )
{
g_pBlobNetworkBypass->iHighestIndexUsed = (uint32)j + 1;
break;
}
}
break;
}
}
}
Assert( g_pBlobNetworkBypass->iHighestIndexUsed >= g_pBlobNetworkBypass->iNumParticlesAllocated );
}
#else
void CBlobParticleNetworkBypassAutoGame::PreRender( void )
{
if( engine->IsRecordingDemo() && g_pBlobNetworkBypass->bDataUpdated )
{
//record the update, TODO: compress the data by omitting the holes
int iMaxIndex = MAX(g_pBlobNetworkBypass->iHighestIndexUsed, m_iOldHighestIndexUsed);
int iBitMax = (iMaxIndex / BITS_PER_INT) + 1;
size_t iDataSize = sizeof( int ) + sizeof( float ) + sizeof( int ) + sizeof( int ) + (sizeof( int ) * iBitMax) +
iMaxIndex*( sizeof( Vector ) + sizeof( float ) + sizeof( Vector ) );
uint8 *pData = new uint8 [iDataSize];
uint8 *pWrite = pData;
//let the receiver know how much of each array to expect
*(int *)pWrite = LittleDWord( iMaxIndex );
pWrite += sizeof( int );
//write the update timestamp
*(float *)pWrite = g_pBlobNetworkBypass->fTimeDataUpdated;
pWrite += sizeof( float );
//record usage information, also helps us effectively compress the subsequent data by omitting the holes.
*(int *)pWrite = LittleDWord( g_pBlobNetworkBypass->iHighestIndexUsed );
pWrite += sizeof( int );
*(int *)pWrite = LittleDWord( g_pBlobNetworkBypass->iNumParticlesAllocated );
pWrite += sizeof( int );
int *pIntParser = (int *)&g_pBlobNetworkBypass->bCurrentlyInUse;
for( int i = 0; i != iBitMax; ++i )
{
//convert and write the bitfield integers
*(int *)pWrite = LittleDWord( *pIntParser );
pWrite += sizeof( int );
++pIntParser;
}
//write positions
memcpy( pWrite, g_pBlobNetworkBypass->vParticlePositions, sizeof( Vector ) * iMaxIndex );
pWrite += sizeof( Vector ) * iMaxIndex;
//write radii
memcpy( pWrite, g_pBlobNetworkBypass->vParticleRadii, sizeof( float ) * iMaxIndex );
pWrite += sizeof( float ) * iMaxIndex;
//write closest surface direction
memcpy( pWrite, g_pBlobNetworkBypass->vParticleClosestSurfDir, sizeof( Vector ) * iMaxIndex );
pWrite += sizeof( Vector ) * iMaxIndex;
engine->RecordDemoCustomData( BlobNetworkBypass_CustomDemoDataCallback, pData, iDataSize );
Assert( pWrite == (pData + iDataSize) );
delete []pData;
}
//invalidate interpolation on freed indices, do a quick update for brand new indices
{
//operate on smaller chunks based on the assumption that LARGE portions of the end of the bitvecs are empty
CBitVec<BITS_PER_INT> *pCurrentlyInUse = (CBitVec<BITS_PER_INT> *)&g_pBlobNetworkBypass->bCurrentlyInUse;
CBitVec<BITS_PER_INT> *pOldInUse = (CBitVec<BITS_PER_INT> *)&m_bOldInUse;
int iStop = (MAX(g_pBlobNetworkBypass->iHighestIndexUsed, m_iOldHighestIndexUsed) / BITS_PER_INT) + 1;
int iBaseIndex = 0;
//float fNewIndicesUpdateTime = g_pBlobNetworkBypass->bPositionsUpdated ? g_pBlobNetworkBypass->fTimeDataUpdated : gpGlobals->curtime;
for( int i = 0; i != iStop; ++i )
{
CBitVec<BITS_PER_INT> bInUseXOR;
pCurrentlyInUse->Xor( *pOldInUse, &bInUseXOR ); //find bits that changed
int j = 0;
while( (j = bInUseXOR.FindNextSetBit( j )) != -1 )
{
int iChangedUsageIndex = iBaseIndex + j;
if( pOldInUse->IsBitSet( iChangedUsageIndex ) )
{
//index no longer used
g_BlobParticleInterpolation.vInterpolatedPositions[iChangedUsageIndex] = vec3_origin;
s_PositionInterpolators[iChangedUsageIndex].ClearHistory();
g_BlobParticleInterpolation.vInterpolatedRadii[iChangedUsageIndex] = 1.0f;
s_RadiusInterpolators[iChangedUsageIndex].ClearHistory();
g_BlobParticleInterpolation.vInterpolatedClosestSurfDir[iChangedUsageIndex] = vec3_origin;
s_ClosestSurfDirInterpolators[iChangedUsageIndex].ClearHistory();
}
else
{
//index just started being used. Assume we got an out of band update to the position
g_BlobParticleInterpolation.vInterpolatedPositions[iChangedUsageIndex] = g_pBlobNetworkBypass->vParticlePositions[iChangedUsageIndex];
s_PositionInterpolators[iChangedUsageIndex].Reset( gpGlobals->curtime );
g_BlobParticleInterpolation.vInterpolatedRadii[iChangedUsageIndex] = g_pBlobNetworkBypass->vParticleRadii[iChangedUsageIndex];
s_RadiusInterpolators[iChangedUsageIndex].Reset( gpGlobals->curtime );
g_BlobParticleInterpolation.vInterpolatedClosestSurfDir[iChangedUsageIndex] = g_pBlobNetworkBypass->vParticleClosestSurfDir[iChangedUsageIndex];
s_ClosestSurfDirInterpolators[iChangedUsageIndex].Reset( gpGlobals->curtime );
//s_PositionInterpolators[iChangedUsageIndex].NoteChanged( gpGlobals->curtime, fNewIndicesUpdateTime, true );
}
++j;
if( j == BITS_PER_INT )
break;
}
iBaseIndex += BITS_PER_INT;
++pCurrentlyInUse;
++pOldInUse;
}
memcpy( &m_bOldInUse, &g_pBlobNetworkBypass->bCurrentlyInUse, sizeof( m_bOldInUse ) );
m_iOldHighestIndexUsed = g_pBlobNetworkBypass->iHighestIndexUsed;
}
if( g_pBlobNetworkBypass->iHighestIndexUsed == 0 )
return;
static ConVarRef cl_interpREF( "cl_interp" );
//now do the interpolation of positions still in use
{
float fInterpTime = gpGlobals->curtime - cl_interpREF.GetFloat();
CBitVec<BITS_PER_INT> *pIntParser = (CBitVec<BITS_PER_INT> *)&g_pBlobNetworkBypass->bCurrentlyInUse;
int iStop = (g_pBlobNetworkBypass->iHighestIndexUsed / BITS_PER_INT) + 1;
int iBaseIndex = 0;
for( int i = 0; i != iStop; ++i )
{
int j = 0;
while( (j = pIntParser->FindNextSetBit( j )) != -1 )
{
int iUpdateIndex = iBaseIndex + j;
if( g_pBlobNetworkBypass->bDataUpdated )
{
g_BlobParticleInterpolation.vInterpolatedPositions[iUpdateIndex] = g_pBlobNetworkBypass->vParticlePositions[iUpdateIndex];
s_PositionInterpolators[iUpdateIndex].NoteChanged( gpGlobals->curtime, g_pBlobNetworkBypass->fTimeDataUpdated, true );
g_BlobParticleInterpolation.vInterpolatedRadii[iUpdateIndex] = g_pBlobNetworkBypass->vParticleRadii[iUpdateIndex];
s_RadiusInterpolators[iUpdateIndex].NoteChanged( gpGlobals->curtime, g_pBlobNetworkBypass->fTimeDataUpdated, true );
g_BlobParticleInterpolation.vInterpolatedClosestSurfDir[iUpdateIndex] = g_pBlobNetworkBypass->vParticleClosestSurfDir[iUpdateIndex];
s_ClosestSurfDirInterpolators[iUpdateIndex].NoteChanged( gpGlobals->curtime, g_pBlobNetworkBypass->fTimeDataUpdated, true );
//s_PositionInterpolators[iUpdateIndex].AddToHead( gpGlobals->curtime, &g_pBlobNetworkBypass->vParticlePositions[iUpdateIndex], false );
}
s_PositionInterpolators[iUpdateIndex].Interpolate( fInterpTime );
s_RadiusInterpolators[iUpdateIndex].Interpolate( fInterpTime );
s_ClosestSurfDirInterpolators[iUpdateIndex].Interpolate( fInterpTime );
++j;
if( j == BITS_PER_INT )
break;
}
iBaseIndex += BITS_PER_INT;
++pIntParser;
}
g_pBlobNetworkBypass->bDataUpdated = false;
}
}
void BlobNetworkBypass_CustomDemoDataCallback( uint8 *pData, size_t iSize )
{
// FIXME: need a version number!
uint8 *pParse = pData;
int iMaxIndex = LittleDWord( *(int *)pParse );
pParse += sizeof( int );
int iBitMax = (iMaxIndex / BITS_PER_INT) + 1;
Assert( iSize == (sizeof( int ) + sizeof( float ) + sizeof( int ) + sizeof( int ) + (sizeof( int ) * iBitMax) +
iMaxIndex*( sizeof( Vector ) + sizeof( float ) + sizeof( Vector ) )) );
g_pBlobNetworkBypass->fTimeDataUpdated = *(float *)pParse;
pParse += sizeof( float );
g_pBlobNetworkBypass->iHighestIndexUsed = LittleDWord( *(int *)pParse );
pParse += sizeof( int );
g_pBlobNetworkBypass->iNumParticlesAllocated = LittleDWord( *(int *)pParse );
pParse += sizeof( int );
int *pIntParser = (int *)&g_pBlobNetworkBypass->bCurrentlyInUse;
for( int i = 0; i != iBitMax; ++i )
{
//read and convert the bitfield integers
*pIntParser = LittleDWord( *(int *)pParse );
pParse += sizeof( int );
++pIntParser;
}
//read positions
memcpy( g_pBlobNetworkBypass->vParticlePositions, pParse, sizeof( Vector ) * iMaxIndex );
pParse += sizeof( Vector ) * iMaxIndex;
//read radii
memcpy( g_pBlobNetworkBypass->vParticleRadii, pParse, sizeof( float ) * iMaxIndex );
pParse += sizeof( float ) * iMaxIndex;
//read closest surface direction
memcpy( g_pBlobNetworkBypass->vParticleClosestSurfDir, pParse, sizeof( Vector ) * iMaxIndex );
pParse += sizeof( Vector ) * iMaxIndex;
g_pBlobNetworkBypass->bDataUpdated = true;
Assert( pParse == (pData + iSize) );
}
#endif
+61
View File
@@ -0,0 +1,61 @@
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
//
// Purpose: Game rules for Blob.
//
//=============================================================================//
#ifndef BLOB_NETWORKBYPASS_H
#define BLOB_NETWORKBYPASS_H
#ifdef _WIN32
#pragma once
#endif
#include "bitvec.h"
#define BLOB_MAX_LEVEL_PARTICLES 4000 // maximum number of blob particles in a given level at any one time
#define BLOB_MAX_LEVEL_PARTICLES_BITS 12 // the number of bits needed to represent the number of particles above (should be ceil(lg(BLOB_MAX_LEVEL_PARTICLES)))
#define PARTICLEUSAGENUMINTS ((BLOB_MAX_LEVEL_PARTICLES + (BITS_PER_INT-1)) / BITS_PER_INT)
#define BLOBPARTICLEPOSITION(x) (g_pBlobNetworkBypass->vParticlePositions[x])
#define BLOBPARTICLERADIUS(x) (g_pBlobNetworkBypass->vParticleRadii[x])
#define BLOBPARTICLECLOSESTSURFDIR(x) (g_pBlobNetworkBypass->vParticleClosestSurfDir[x])
#ifdef CLIENT_DLL
#define BLOBPARTICLEPOS_INTERP(x) (g_BlobParticleInterpolation.vInterpolatedPositions[x])
#define BLOBPARTICLERADIUS_INTERP(x) (g_BlobParticleInterpolation.vInterpolatedRadii[x])
#define BLOBPARTICLECLOSESTSURFDIR_INTERP(x) (g_BlobParticleInterpolation.vInterpolatedClosestSurfDir[x])
#endif
struct BlobNetworkBypass_t
{
//these 2 ints and bitvec help us communicate which particles contain valid data
uint32 iNumParticlesAllocated;
uint32 iHighestIndexUsed;
CBitVec<BLOB_MAX_LEVEL_PARTICLES> bCurrentlyInUse;
//actual data we want to communicate using the bypass
Vector vParticlePositions[BLOB_MAX_LEVEL_PARTICLES];
float vParticleRadii[BLOB_MAX_LEVEL_PARTICLES];
Vector vParticleClosestSurfDir[BLOB_MAX_LEVEL_PARTICLES];
float fTimeDataUpdated;
bool bDataUpdated;
};
#ifdef CLIENT_DLL
struct BlobParticleInterpolation_t
{
Vector vInterpolatedPositions[BLOB_MAX_LEVEL_PARTICLES];
float vInterpolatedRadii[BLOB_MAX_LEVEL_PARTICLES];
Vector vInterpolatedClosestSurfDir[BLOB_MAX_LEVEL_PARTICLES];
};
extern BlobParticleInterpolation_t g_BlobParticleInterpolation;
#endif
extern BlobNetworkBypass_t *g_pBlobNetworkBypass;
#ifndef CLIENT_DLL
int AllocateBlobNetworkBypassIndex( void );
void ReleaseBlobNetworkBypassIndex( int iIndex );
#endif
#endif // BLOB_NETWORKBYPASS_H
-226
View File
@@ -1,226 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "cam_thirdperson.h"
#include "gamerules.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static Vector CAM_HULL_MIN(-CAM_HULL_OFFSET,-CAM_HULL_OFFSET,-CAM_HULL_OFFSET);
static Vector CAM_HULL_MAX( CAM_HULL_OFFSET, CAM_HULL_OFFSET, CAM_HULL_OFFSET);
#ifdef CLIENT_DLL
#include "input.h"
extern const ConVar *sv_cheats;
extern ConVar cam_idealdist;
extern ConVar cam_idealdistright;
extern ConVar cam_idealdistup;
void CAM_ToThirdPerson(void);
void CAM_ToFirstPerson(void);
void ToggleThirdPerson( bool bValue )
{
if ( bValue == true )
{
CAM_ToThirdPerson();
}
else
{
CAM_ToFirstPerson();
}
}
void ThirdPersonChange( IConVar *pConVar, const char *pOldValue, float flOldValue )
{
ConVarRef var( pConVar );
ToggleThirdPerson( var.GetBool() );
}
ConVar cl_thirdperson( "cl_thirdperson", "0", FCVAR_NOT_CONNECTED | FCVAR_USERINFO | FCVAR_ARCHIVE | FCVAR_DEVELOPMENTONLY, "Enables/Disables third person", ThirdPersonChange );
#endif
void CThirdPersonManager::Init( void )
{
m_bOverrideThirdPerson = false;
m_bForced = false;
m_flUpFraction = 0.0f;
m_flFraction = 1.0f;
m_flUpLerpTime = 0.0f;
m_flLerpTime = 0.0f;
m_flUpOffset = CAMERA_UP_OFFSET;
if ( input )
{
input->CAM_SetCameraThirdData( NULL, vec3_angle );
}
}
void CThirdPersonManager::Update( void )
{
#ifdef CLIENT_DLL
if ( !sv_cheats )
{
sv_cheats = cvar->FindVar( "sv_cheats" );
}
// If cheats have been disabled, pull us back out of third-person view.
if ( sv_cheats && !sv_cheats->GetBool() && GameRules() && GameRules()->AllowThirdPersonCamera() == false )
{
if ( (bool)input->CAM_IsThirdPerson() == true )
{
input->CAM_ToFirstPerson();
}
return;
}
if ( IsOverridingThirdPerson() == false )
{
if ( (bool)input->CAM_IsThirdPerson() != ( cl_thirdperson.GetBool() || m_bForced ) && GameRules() && GameRules()->AllowThirdPersonCamera() == true )
{
ToggleThirdPerson( m_bForced || cl_thirdperson.GetBool() );
}
}
#endif
}
Vector CThirdPersonManager::GetDesiredCameraOffset( void )
{
if ( IsOverridingThirdPerson() == true )
{
return Vector( cam_idealdist.GetFloat(), cam_idealdistright.GetFloat(), cam_idealdistup.GetFloat() );
}
return m_vecDesiredCameraOffset;
}
Vector CThirdPersonManager::GetFinalCameraOffset( void )
{
Vector vDesired = GetDesiredCameraOffset();
if ( m_flUpFraction != 1.0f )
{
vDesired.z += m_flUpOffset;
}
return vDesired;
}
Vector CThirdPersonManager::GetDistanceFraction( void )
{
if ( IsOverridingThirdPerson() == true )
{
return Vector( m_flTargetFraction, m_flTargetFraction, m_flTargetFraction );
}
float flFraction = m_flFraction;
float flUpFraction = m_flUpFraction;
float flFrac = RemapValClamped( gpGlobals->curtime - m_flLerpTime, 0, CAMERA_OFFSET_LERP_TIME, 0, 1 );
flFraction = Lerp( flFrac, m_flFraction, m_flTargetFraction );
if ( flFrac == 1.0f )
{
m_flFraction = m_flTargetFraction;
}
flFrac = RemapValClamped( gpGlobals->curtime - m_flUpLerpTime, 0, CAMERA_UP_OFFSET_LERP_TIME, 0, 1 );
flUpFraction = 1.0f - Lerp( flFrac, m_flUpFraction, m_flTargetUpFraction );
if ( flFrac == 1.0f )
{
m_flUpFraction = m_flTargetUpFraction;
}
return Vector( flFraction, flFraction, flUpFraction );
}
void CThirdPersonManager::PositionCamera( CBasePlayer *pPlayer, QAngle angles )
{
if ( pPlayer )
{
trace_t trace;
Vector camForward, camRight, camUp;
// find our player's origin, and from there, the eye position
Vector origin = pPlayer->GetLocalOrigin();
origin += pPlayer->GetViewOffset();
AngleVectors( angles, &camForward, &camRight, &camUp );
Vector endPos = origin;
Vector vecCamOffset = endPos + (camForward * - GetDesiredCameraOffset()[DIST_FORWARD]) + (camRight * GetDesiredCameraOffset()[ DIST_RIGHT ]) + (camUp * GetDesiredCameraOffset()[ DIST_UP ] );
// use our previously #defined hull to collision trace
CTraceFilterSimple traceFilter( pPlayer, COLLISION_GROUP_NONE );
UTIL_TraceHull( endPos, vecCamOffset, CAM_HULL_MIN, CAM_HULL_MAX, MASK_SOLID & ~CONTENTS_MONSTER, &traceFilter, &trace );
if ( trace.fraction != m_flTargetFraction )
{
m_flLerpTime = gpGlobals->curtime;
}
m_flTargetFraction = trace.fraction;
m_flTargetUpFraction = 1.0f;
//If we're getting closer to a wall snap the fraction right away.
if ( m_flTargetFraction < m_flFraction )
{
m_flFraction = m_flTargetFraction;
m_flLerpTime = gpGlobals->curtime;
}
// move the camera closer if it hit something
if( trace.fraction < 1.0 )
{
m_vecCameraOffset[ DIST ] *= trace.fraction;
UTIL_TraceHull( endPos, endPos + (camForward * - GetDesiredCameraOffset()[DIST_FORWARD]), CAM_HULL_MIN, CAM_HULL_MAX, MASK_SOLID & ~CONTENTS_MONSTER, &traceFilter, &trace );
if ( trace.fraction != 1.0f )
{
if ( trace.fraction != m_flTargetUpFraction )
{
m_flUpLerpTime = gpGlobals->curtime;
}
m_flTargetUpFraction = trace.fraction;
if ( m_flTargetUpFraction < m_flUpFraction )
{
m_flUpFraction = trace.fraction;
m_flUpLerpTime = gpGlobals->curtime;
}
}
}
}
}
bool CThirdPersonManager::WantToUseGameThirdPerson( void )
{
return cl_thirdperson.GetBool() && GameRules() && GameRules()->AllowThirdPersonCamera() && IsOverridingThirdPerson() == false;
}
CThirdPersonManager g_ThirdPersonManager;
-108
View File
@@ -1,108 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef CAM_THIRDPERSON_H
#define CAM_THIRDPERSON_H
#if defined( _WIN32 )
#pragma once
#endif
#ifdef CLIENT_DLL
#include "c_baseplayer.h"
#else
#include "baseplayer.h"
#endif
#define DIST_FORWARD 0
#define DIST_RIGHT 1
#define DIST_UP 2
//-------------------------------------------------- Constants
#define CAM_MIN_DIST 30.0
#define CAM_ANGLE_MOVE .5
#define MAX_ANGLE_DIFF 10.0
#define PITCH_MAX 90.0
#define PITCH_MIN 0
#define YAW_MAX 135.0
#define YAW_MIN -135.0
#define DIST 2
#define CAM_HULL_OFFSET 14.0 // the size of the bounding hull used for collision checking
#define CAMERA_UP_OFFSET 25.0f
#define CAMERA_OFFSET_LERP_TIME 0.5f
#define CAMERA_UP_OFFSET_LERP_TIME 0.25f
class CThirdPersonManager
{
public:
CThirdPersonManager() = default;
void SetCameraOffsetAngles( Vector vecOffset ) { m_vecCameraOffset = vecOffset; }
Vector GetCameraOffsetAngles( void ) { return m_vecCameraOffset; }
void SetDesiredCameraOffset( Vector vecOffset ) { m_vecDesiredCameraOffset = vecOffset; }
Vector GetDesiredCameraOffset( void );
Vector GetFinalCameraOffset( void );
void SetCameraOrigin( Vector vecOffset ) { m_vecCameraOrigin = vecOffset; }
Vector GetCameraOrigin( void ) { return m_vecCameraOrigin; }
void Update( void );
void PositionCamera( CBasePlayer *pPlayer, QAngle angles );
void UseCameraOffsets( bool bUse ) { m_bUseCameraOffsets = bUse; }
bool UsingCameraOffsets( void ) { return m_bUseCameraOffsets; }
QAngle GetCameraViewAngles( void ) { return m_ViewAngles; }
Vector GetDistanceFraction( void );
bool WantToUseGameThirdPerson( void );
void SetOverridingThirdPerson( bool bOverride ) { m_bOverrideThirdPerson = bOverride; }
bool IsOverridingThirdPerson( void ) { return m_bOverrideThirdPerson; }
void Init( void );
void SetForcedThirdPerson( bool bForced ) { m_bForced = bForced; }
bool GetForcedThirdPerson() const { return m_bForced; }
private:
// What is the current camera offset from the view origin?
Vector m_vecCameraOffset;
// Distances from the center
Vector m_vecDesiredCameraOffset;
Vector m_vecCameraOrigin;
bool m_bUseCameraOffsets;
QAngle m_ViewAngles;
float m_flFraction;
float m_flUpFraction;
float m_flTargetFraction;
float m_flTargetUpFraction;
bool m_bOverrideThirdPerson;
bool m_bForced;
float m_flUpOffset;
float m_flLerpTime;
float m_flUpLerpTime;
};
extern CThirdPersonManager g_ThirdPersonManager;
#endif // CAM_THIRDPERSON_H
+63
View File
@@ -0,0 +1,63 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose: Utility functions for cell coordinate calculations
// to reduce bandwidth usage
//
// $NoKeywords: $
//=============================================================================//
#ifndef CELLCOORD_H
#define CELLCOORD_H
#ifdef _WIN32
#pragma once
#endif
#include "worldsize.h"
// Given a world coord, return the cell it should be in
inline int CellFromCoord( int cellwidth, float f )
{
// We handle each side of zero difference to reduce precision errors
if ( f < 0.0f )
{
return Float2Int( f + MAX_COORD_INTEGER ) / cellwidth;
}
else
{
return Float2Int(f) / cellwidth + ( MAX_COORD_INTEGER / cellwidth );
}
}
// Given a cell and a world coord, return the offset into the cell
// cell should have been returned from CellFromCoord with the same f, we don't
// recompute here
inline float CellInCoord( int cellwidth, int cell, float f )
{
float r;
int c = abs( cell * cellwidth - MAX_COORD_INTEGER ) ;
if ( f < 0.0f )
{
r = c + f;
}
else
{
r = f - c;
}
// Pecision errors can futz the edges
return clamp( r, 0.0f, (float)cellwidth );
}
// Given a cell and an offset in that cell, reconstructor the world coord
inline float CoordFromCell( int cellwidth, int cell, float f )
{
int cellPos = ( cell * cellwidth );
float r = ( cellPos - MAX_COORD_INTEGER ) + f;
return r;
}
#endif //CELLCOORDCONVERTER_H
+5 -5
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -45,7 +45,7 @@ CChoreoActor& CChoreoActor::operator=( const CChoreoActor& src )
Q_strncpy( m_szName, src.m_szName, sizeof( m_szName ) );
Q_strncpy( m_szFacePoserModelName, src.m_szFacePoserModelName, sizeof( m_szFacePoserModelName ) );
for ( int i = 0; i < src.m_Channels.Size(); i++ )
for ( int i = 0; i < src.m_Channels.Count(); i++ )
{
CChoreoChannel *c = src.m_Channels[ i ];
CChoreoChannel *newChannel = new CChoreoChannel();
@@ -92,7 +92,7 @@ const char *CChoreoActor::GetName( void )
//-----------------------------------------------------------------------------
int CChoreoActor::GetNumChannels( void )
{
return m_Channels.Size();
return m_Channels.Count();
}
//-----------------------------------------------------------------------------
@@ -102,7 +102,7 @@ int CChoreoActor::GetNumChannels( void )
//-----------------------------------------------------------------------------
CChoreoChannel *CChoreoActor::GetChannel( int channel )
{
if ( channel < 0 || channel >= m_Channels.Size() )
if ( channel < 0 || channel >= m_Channels.Count() )
{
return NULL;
}
@@ -161,7 +161,7 @@ void CChoreoActor::SwapChannels( int c1, int c2 )
//-----------------------------------------------------------------------------
int CChoreoActor::FindChannelIndex( CChoreoChannel *channel )
{
for ( int i = 0; i < m_Channels.Size(); i++ )
for ( int i = 0; i < m_Channels.Count(); i++ )
{
if ( channel == m_Channels[ i ] )
{
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
+5 -5
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -45,7 +45,7 @@ CChoreoChannel& CChoreoChannel::operator=( const CChoreoChannel& src )
{
m_bActive = src.m_bActive;
Q_strncpy( m_szName, src.m_szName, sizeof( m_szName ) );
for ( int i = 0; i < src.m_Events.Size(); i++ )
for ( int i = 0; i < src.m_Events.Count(); i++ )
{
CChoreoEvent *e = src.m_Events[ i ];
CChoreoEvent *newEvent = new CChoreoEvent( e->GetScene() );
@@ -83,7 +83,7 @@ const char *CChoreoChannel::GetName( void )
//-----------------------------------------------------------------------------
int CChoreoChannel::GetNumEvents( void )
{
return m_Events.Size();
return m_Events.Count();
}
//-----------------------------------------------------------------------------
@@ -93,7 +93,7 @@ int CChoreoChannel::GetNumEvents( void )
//-----------------------------------------------------------------------------
CChoreoEvent *CChoreoChannel::GetEvent( int event )
{
if ( event < 0 || event >= m_Events.Size() )
if ( event < 0 || event >= m_Events.Count() )
{
return NULL;
}
@@ -138,7 +138,7 @@ void CChoreoChannel::RemoveAllEvents()
//-----------------------------------------------------------------------------
int CChoreoChannel::FindEventIndex( CChoreoEvent *event )
{
for ( int i = 0; i < m_Events.Size(); i++ )
for ( int i = 0; i < m_Events.Count(); i++ )
{
if ( event == m_Events[ i ] )
{
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
+51 -50
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -12,7 +12,6 @@
#include "choreoevent.h"
#include "choreoactor.h"
#include "choreochannel.h"
#include "minmax.h"
#include "mathlib/mathlib.h"
#include "tier1/strtools.h"
#include "choreoscene.h"
@@ -433,7 +432,7 @@ CFlexAnimationTrack::CFlexAnimationTrack( const CFlexAnimationTrack* src )
for ( int t = 0; t < 2; t++ )
{
m_Samples[ t ].Purge();
for ( int i = 0 ;i < src->m_Samples[ t ].Size(); i++ )
for ( int i = 0 ;i < src->m_Samples[ t ].Count(); i++ )
{
CExpressionSample s = src->m_Samples[ t ][ i ];
m_Samples[ t ].AddToTail( s );
@@ -528,7 +527,7 @@ int CFlexAnimationTrack::GetNumSamples( int type /*=0*/ )
{
Assert( type == 0 || type == 1 );
return m_Samples[ type ].Size();
return m_Samples[ type ].Count();
}
//-----------------------------------------------------------------------------
@@ -788,9 +787,9 @@ float CFlexAnimationTrack::GetFracIntensity( float time, int type )
prev = MAX( -1, prev );
next = MIN( next, rampCount );
bool bclamp[ 2 ];
CExpressionSample *esPre = GetBoundedSample( prev, bclamp[ 0 ], type );
CExpressionSample *esNext = GetBoundedSample( next, bclamp[ 1 ], type );
bool clamp[ 2 ];
CExpressionSample *esPre = GetBoundedSample( prev, clamp[ 0 ], type );
CExpressionSample *esNext = GetBoundedSample( next, clamp[ 1 ], type );
float dt = esEnd->time - esStart->time;
@@ -932,9 +931,9 @@ void CFlexAnimationTrack::Resort( int type /*=0*/ )
{
Assert( type == 0 || type == 1 );
for ( int i = 0; i < m_Samples[ type ].Size(); i++ )
for ( int i = 0; i < m_Samples[ type ].Count(); i++ )
{
for ( int j = i + 1; j < m_Samples[ type ].Size(); j++ )
for ( int j = i + 1; j < m_Samples[ type ].Count(); j++ )
{
CExpressionSample src = m_Samples[ type ][ i ];
CExpressionSample dest = m_Samples[ type ][ j ];
@@ -1117,7 +1116,7 @@ void CFlexAnimationTrack::RemoveOutOfRangeSamples( int type )
Assert( m_pEvent->HasEndTime() );
float duration = m_pEvent->GetDuration();
int c = m_Samples[ type ].Size();
int c = m_Samples[ type ].Count();
for ( int i = c-1; i >= 0; i-- )
{
CExpressionSample src = m_Samples[ type ][ i ];
@@ -1218,14 +1217,14 @@ CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src )
}
int i;
for ( i = 0; i < src.m_RelativeTags.Size(); i++ )
for ( i = 0; i < src.m_RelativeTags.Count(); i++ )
{
CEventRelativeTag newtag( src.m_RelativeTags[ i ] );
newtag.SetOwner( this );
m_RelativeTags.AddToTail( newtag );
}
for ( i = 0; i < src.m_TimingTags.Size(); i++ )
for ( i = 0; i < src.m_TimingTags.Count(); i++ )
{
CFlexTimingTag newtag( src.m_TimingTags[ i ] );
newtag.SetOwner( this );
@@ -1233,7 +1232,7 @@ CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src )
}
for ( t = 0; t < NUM_ABS_TAG_TYPES; t++ )
{
for ( i = 0; i < src.m_AbsoluteTags[ t ].Size(); i++ )
for ( i = 0; i < src.m_AbsoluteTags[ t ].Count(); i++ )
{
CEventAbsoluteTag newtag( src.m_AbsoluteTags[ t ][ i ] );
newtag.SetOwner( this );
@@ -1243,7 +1242,7 @@ CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src )
RemoveAllTracks();
for ( i = 0 ; i < src.m_FlexAnimationTracks.Size(); i++ )
for ( i = 0 ; i < src.m_FlexAnimationTracks.Count(); i++ )
{
CFlexAnimationTrack *newtrack = new CFlexAnimationTrack( src.m_FlexAnimationTracks[ i ] );
newtrack->SetEvent( this );
@@ -1655,9 +1654,9 @@ float CCurveData::GetIntensity( ICurveDataAccessor *data, float time )
prev = MAX( -1, prev );
next = MIN( next, rampCount );
bool bclamp[ 2 ];
CExpressionSample *esPre = GetBoundedSample( data, prev, bclamp[ 0 ] );
CExpressionSample *esNext = GetBoundedSample( data, next, bclamp[ 1 ] );
bool clamp[ 2 ];
CExpressionSample *esPre = GetBoundedSample( data, prev, clamp[ 0 ] );
CExpressionSample *esNext = GetBoundedSample( data, next, clamp[ 1 ] );
float dt = esEnd->time - esStart->time;
@@ -1666,12 +1665,12 @@ float CCurveData::GetIntensity( ICurveDataAccessor *data, float time )
Vector vEnd( esEnd->time, esEnd->value, 0 );
Vector vNext( esNext->time, esNext->value, 0 );
if ( bclamp[ 0 ] )
if ( clamp[ 0 ] )
{
vPre.x = vStart.x;
}
if ( bclamp[ 1 ] )
if ( clamp[ 1 ] )
{
vNext.x = vEnd.x;
}
@@ -1837,9 +1836,9 @@ float CCurveData::GetIntensityArea( ICurveDataAccessor *data, float time )
prev = MAX( -1, prev );
next = MIN( next, rampCount );
bool bclamp[ 2 ];
CExpressionSample *esPre = GetBoundedSample( data, prev, bclamp[ 0 ] );
CExpressionSample *esNext = GetBoundedSample( data, next, bclamp[ 1 ] );
bool clamp[ 2 ];
CExpressionSample *esPre = GetBoundedSample( data, prev, clamp[ 0 ] );
CExpressionSample *esNext = GetBoundedSample( data, next, clamp[ 1 ] );
float dt = esEnd->time - esStart->time;
@@ -1848,12 +1847,12 @@ float CCurveData::GetIntensityArea( ICurveDataAccessor *data, float time )
Vector vEnd( esEnd->time, esEnd->value, 0 );
Vector vNext( esNext->time, esNext->value, 0 );
if ( bclamp[ 0 ] )
if ( clamp[ 0 ] )
{
vPre.x = vStart.x;
}
if ( bclamp[ 1 ] )
if ( clamp[ 1 ] )
{
vNext.x = vEnd.x;
}
@@ -2064,6 +2063,8 @@ static EventNameMap_t g_NameMap[] =
{ CChoreoEvent::STOPPOINT, "stoppoint" },
{ CChoreoEvent::PERMIT_RESPONSES, "permitresponses" },
{ CChoreoEvent::GENERIC, "generic" },
{ CChoreoEvent::CAMERA, "camera" },
{ CChoreoEvent::SCRIPT, "script" },
};
//-----------------------------------------------------------------------------
@@ -2076,7 +2077,7 @@ public:
{
if ( ARRAYSIZE( g_NameMap ) != CChoreoEvent::NUM_TYPES )
{
Error( "g_NameMap contains %zd entries, CChoreoEvent::NUM_TYPES == %i!",
Error( "g_NameMap contains %i entries, CChoreoEvent::NUM_TYPES == %i!",
ARRAYSIZE( g_NameMap ), CChoreoEvent::NUM_TYPES );
}
for ( int i = 0; i < CChoreoEvent::NUM_TYPES; ++i )
@@ -2158,7 +2159,7 @@ public:
{
if ( ARRAYSIZE( g_CCNameMap ) != CChoreoEvent::NUM_CC_TYPES )
{
Error( "g_CCNameMap contains %zd entries, CChoreoEvent::NUM_CC_TYPES == %i!",
Error( "g_CCNameMap contains %i entries, CChoreoEvent::NUM_CC_TYPES == %i!",
ARRAYSIZE( g_CCNameMap ), CChoreoEvent::NUM_CC_TYPES );
}
for ( int i = 0; i < CChoreoEvent::NUM_CC_TYPES; ++i )
@@ -2383,7 +2384,7 @@ void CChoreoEvent::ClearAllRelativeTags( void )
//-----------------------------------------------------------------------------
int CChoreoEvent::GetNumRelativeTags( void )
{
return m_RelativeTags.Size();
return m_RelativeTags.Count();
}
//-----------------------------------------------------------------------------
@@ -2393,7 +2394,7 @@ int CChoreoEvent::GetNumRelativeTags( void )
//-----------------------------------------------------------------------------
CEventRelativeTag *CChoreoEvent::GetRelativeTag( int tagnum )
{
Assert( tagnum >= 0 && tagnum < m_RelativeTags.Size() );
Assert( tagnum >= 0 && tagnum < m_RelativeTags.Count() );
return &m_RelativeTags[ tagnum ];
}
@@ -2414,7 +2415,7 @@ void CChoreoEvent::AddRelativeTag( const char *tagname, float percentage )
//-----------------------------------------------------------------------------
void CChoreoEvent::RemoveRelativeTag( const char *tagname )
{
for ( int i = 0; i < m_RelativeTags.Size(); i++ )
for ( int i = 0; i < m_RelativeTags.Count(); i++ )
{
CEventRelativeTag *prt = &m_RelativeTags[ i ];
if ( !prt )
@@ -2435,7 +2436,7 @@ void CChoreoEvent::RemoveRelativeTag( const char *tagname )
//-----------------------------------------------------------------------------
CEventRelativeTag * CChoreoEvent::FindRelativeTag( const char *tagname )
{
for ( int i = 0; i < m_RelativeTags.Size(); i++ )
for ( int i = 0; i < m_RelativeTags.Count(); i++ )
{
CEventRelativeTag *prt = &m_RelativeTags[ i ];
if ( !prt )
@@ -2518,7 +2519,7 @@ void CChoreoEvent::ClearAllTimingTags( void )
//-----------------------------------------------------------------------------
int CChoreoEvent::GetNumTimingTags( void )
{
return m_TimingTags.Size();
return m_TimingTags.Count();
}
//-----------------------------------------------------------------------------
@@ -2528,7 +2529,7 @@ int CChoreoEvent::GetNumTimingTags( void )
//-----------------------------------------------------------------------------
CFlexTimingTag *CChoreoEvent::GetTimingTag( int tagnum )
{
Assert( tagnum >= 0 && tagnum < m_TimingTags.Size() );
Assert( tagnum >= 0 && tagnum < m_TimingTags.Count() );
return &m_TimingTags[ tagnum ];
}
@@ -2546,9 +2547,9 @@ void CChoreoEvent::AddTimingTag( const char *tagname, float percentage, bool loc
CFlexTimingTag temp( (CChoreoEvent *)0x1, "", 0.0f, false );
// ugly bubble sort
for ( int i = 0; i < m_TimingTags.Size(); i++ )
for ( int i = 0; i < m_TimingTags.Count(); i++ )
{
for ( int j = i + 1; j < m_TimingTags.Size(); j++ )
for ( int j = i + 1; j < m_TimingTags.Count(); j++ )
{
CFlexTimingTag *t1 = &m_TimingTags[ i ];
CFlexTimingTag *t2 = &m_TimingTags[ j ];
@@ -2569,7 +2570,7 @@ void CChoreoEvent::AddTimingTag( const char *tagname, float percentage, bool loc
//-----------------------------------------------------------------------------
void CChoreoEvent::RemoveTimingTag( const char *tagname )
{
for ( int i = 0; i < m_TimingTags.Size(); i++ )
for ( int i = 0; i < m_TimingTags.Count(); i++ )
{
CFlexTimingTag *ptt = &m_TimingTags[ i ];
if ( !ptt )
@@ -2590,7 +2591,7 @@ void CChoreoEvent::RemoveTimingTag( const char *tagname )
//-----------------------------------------------------------------------------
CFlexTimingTag * CChoreoEvent::FindTimingTag( const char *tagname )
{
for ( int i = 0; i < m_TimingTags.Size(); i++ )
for ( int i = 0; i < m_TimingTags.Count(); i++ )
{
CFlexTimingTag *ptt = &m_TimingTags[ i ];
if ( !ptt )
@@ -2627,7 +2628,7 @@ void CChoreoEvent::OnEndTimeChanged( void )
//-----------------------------------------------------------------------------
int CChoreoEvent::GetNumFlexAnimationTracks( void )
{
return m_FlexAnimationTracks.Size();
return m_FlexAnimationTracks.Count();
}
//-----------------------------------------------------------------------------
@@ -2929,7 +2930,7 @@ void CChoreoEvent::ClearAllAbsoluteTags( AbsTagType type )
//-----------------------------------------------------------------------------
int CChoreoEvent::GetNumAbsoluteTags( AbsTagType type )
{
return m_AbsoluteTags[ type ].Size();
return m_AbsoluteTags[ type ].Count();
}
//-----------------------------------------------------------------------------
@@ -2940,7 +2941,7 @@ int CChoreoEvent::GetNumAbsoluteTags( AbsTagType type )
//-----------------------------------------------------------------------------
CEventAbsoluteTag *CChoreoEvent::GetAbsoluteTag( AbsTagType type, int tagnum )
{
Assert( tagnum >= 0 && tagnum < m_AbsoluteTags[ type ].Size() );
Assert( tagnum >= 0 && tagnum < m_AbsoluteTags[ type ].Count() );
return &m_AbsoluteTags[ type ][ tagnum ];
}
@@ -2952,7 +2953,7 @@ CEventAbsoluteTag *CChoreoEvent::GetAbsoluteTag( AbsTagType type, int tagnum )
//-----------------------------------------------------------------------------
CEventAbsoluteTag *CChoreoEvent::FindAbsoluteTag( AbsTagType type, const char *tagname )
{
for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ )
for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ )
{
CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ];
if ( !ptag )
@@ -2981,9 +2982,9 @@ void CChoreoEvent::AddAbsoluteTag( AbsTagType type, const char *tagname, float t
CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f );
// ugly bubble sort
for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ )
for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ )
{
for ( int j = i + 1; j < m_AbsoluteTags[ type ].Size(); j++ )
for ( int j = i + 1; j < m_AbsoluteTags[ type ].Count(); j++ )
{
CEventAbsoluteTag *t1 = &m_AbsoluteTags[ type ][ i ];
CEventAbsoluteTag *t2 = &m_AbsoluteTags[ type ][ j ];
@@ -3005,7 +3006,7 @@ void CChoreoEvent::AddAbsoluteTag( AbsTagType type, const char *tagname, float t
//-----------------------------------------------------------------------------
void CChoreoEvent::RemoveAbsoluteTag( AbsTagType type, const char *tagname )
{
for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ )
for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ )
{
CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ];
if ( !ptag )
@@ -3033,7 +3034,7 @@ bool CChoreoEvent::VerifyTagOrder( )
// Sort tags
CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f );
for ( int i = 0; i < m_AbsoluteTags[ CChoreoEvent::ORIGINAL ].Size(); i++ )
for ( int i = 0; i < m_AbsoluteTags[ CChoreoEvent::ORIGINAL ].Count(); i++ )
{
CEventAbsoluteTag *ptag = &m_AbsoluteTags[ CChoreoEvent::ORIGINAL ][ i ];
if ( !ptag )
@@ -3045,7 +3046,7 @@ bool CChoreoEvent::VerifyTagOrder( )
continue;
bInOrder = false;
for ( int j = i + 1; j < m_AbsoluteTags[ CChoreoEvent::PLAYBACK ].Size(); j++ )
for ( int j = i + 1; j < m_AbsoluteTags[ CChoreoEvent::PLAYBACK ].Count(); j++ )
{
CEventAbsoluteTag *t2 = &m_AbsoluteTags[ CChoreoEvent::PLAYBACK ][ j ];
@@ -3530,9 +3531,9 @@ void CCurveData::Clear( void )
//-----------------------------------------------------------------------------
void CCurveData::Resort( ICurveDataAccessor *data )
{
for ( int i = 0; i < m_Ramp.Size(); i++ )
for ( int i = 0; i < m_Ramp.Count(); i++ )
{
for ( int j = i + 1; j < m_Ramp.Size(); j++ )
for ( int j = i + 1; j < m_Ramp.Count(); j++ )
{
CExpressionSample src = m_Ramp[ i ];
CExpressionSample dest = m_Ramp[ j ];
@@ -3689,7 +3690,7 @@ bool CChoreoEvent::PreventTagOverlap( void )
//-----------------------------------------------------------------------------
CEventAbsoluteTag *CChoreoEvent::FindEntryTag( AbsTagType type )
{
for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ )
for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ )
{
CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ];
if ( !ptag )
@@ -3710,7 +3711,7 @@ CEventAbsoluteTag *CChoreoEvent::FindEntryTag( AbsTagType type )
//-----------------------------------------------------------------------------
CEventAbsoluteTag *CChoreoEvent::FindExitTag( AbsTagType type )
{
for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ )
for ( int i = 0; i < m_AbsoluteTags[ type ].Count(); i++ )
{
CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ];
if ( !ptag )
@@ -3927,7 +3928,7 @@ static void CleanupTokenName( char const *in, char *dest, int destlen )
char *out = dest;
while ( *in && ( out - dest ) < destlen )
{
if ( V_isalnum( *in ) || // lowercase, uppercase, digits and underscore are valid
if ( isalnum( *in ) || // lowercase, uppercase, digits and underscore are valid
*in == '_' )
{
*out++ = *in;
+7 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -307,6 +307,12 @@ public:
// A string passed to the game code for interpretation
GENERIC,
// Camera control
CAMERA,
// Script function call
SCRIPT,
// THIS MUST BE LAST!!!
NUM_TYPES,
} EVENTTYPE;
+183 -178
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
@@ -126,7 +126,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src )
// Delete existing
int i;
for ( i = 0; i < m_Actors.Size(); i++ )
for ( i = 0; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
Assert( a );
@@ -135,7 +135,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src )
m_Actors.RemoveAll();
for ( i = 0; i < m_Events.Size(); i++ )
for ( i = 0; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
Assert( e );
@@ -144,7 +144,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src )
m_Events.RemoveAll();
for ( i = 0 ; i < m_Channels.Size(); i++ )
for ( i = 0 ; i < m_Channels.Count(); i++ )
{
CChoreoChannel *c = m_Channels[ i ];
Assert( c );
@@ -170,7 +170,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src )
// Now copy the object tree
// First copy the global events
for ( i = 0; i < src.m_Events.Size(); i++ )
for ( i = 0; i < src.m_Events.Count(); i++ )
{
CChoreoEvent *event = src.m_Events[ i ];
if ( event->GetActor() == NULL )
@@ -184,7 +184,7 @@ CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src )
}
// Finally, push actors, channels, events onto global stacks
for ( i = 0; i < src.m_Actors.Size(); i++ )
for ( i = 0; i < src.m_Actors.Count(); i++ )
{
CChoreoActor *actor = src.m_Actors[ i ];
CChoreoActor *newActor = AllocActor();
@@ -262,7 +262,7 @@ void CChoreoScene::Init( IChoreoEventCallback *callback )
CChoreoScene::~CChoreoScene( void )
{
int i;
for ( i = 0; i < m_Actors.Size(); i++ )
for ( i = 0; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
Assert( a );
@@ -271,7 +271,7 @@ CChoreoScene::~CChoreoScene( void )
m_Actors.RemoveAll();
for ( i = 0; i < m_Events.Size(); i++ )
for ( i = 0; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
Assert( e );
@@ -280,7 +280,7 @@ CChoreoScene::~CChoreoScene( void )
m_Events.RemoveAll();
for ( i = 0 ; i < m_Channels.Size(); i++ )
for ( i = 0 ; i < m_Channels.Count(); i++ )
{
CChoreoChannel *c = m_Channels[ i ];
Assert( c );
@@ -388,7 +388,7 @@ void CChoreoScene::Print( void )
// Look for events that don't have actor/channel set
int i;
for ( i = 0 ; i < m_Events.Size(); i++ )
for ( i = 0 ; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
if ( e->GetActor() )
@@ -397,7 +397,7 @@ void CChoreoScene::Print( void )
PrintEvent( 0, e );
}
for ( i = 0 ; i < m_Actors.Size(); i++ )
for ( i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -476,7 +476,7 @@ CChoreoActor *CChoreoScene::AllocActor( void )
//-----------------------------------------------------------------------------
CChoreoActor *CChoreoScene::FindActor( const char *name )
{
for ( int i = 0; i < m_Actors.Size(); i++ )
for ( int i = 0; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -495,7 +495,7 @@ CChoreoActor *CChoreoScene::FindActor( const char *name )
//-----------------------------------------------------------------------------
int CChoreoScene::GetNumEvents( void )
{
return m_Events.Size();
return m_Events.Count();
}
//-----------------------------------------------------------------------------
@@ -505,7 +505,7 @@ int CChoreoScene::GetNumEvents( void )
//-----------------------------------------------------------------------------
CChoreoEvent *CChoreoScene::GetEvent( int event )
{
if ( event < 0 || event >= m_Events.Size() )
if ( event < 0 || event >= m_Events.Count() )
return NULL;
return m_Events[ event ];
@@ -517,7 +517,7 @@ CChoreoEvent *CChoreoScene::GetEvent( int event )
//-----------------------------------------------------------------------------
int CChoreoScene::GetNumActors( void )
{
return m_Actors.Size();
return m_Actors.Count();
}
//-----------------------------------------------------------------------------
@@ -538,7 +538,7 @@ CChoreoActor *CChoreoScene::GetActor( int actor )
//-----------------------------------------------------------------------------
int CChoreoScene::GetNumChannels( void )
{
return m_Channels.Size();
return m_Channels.Count();
}
//-----------------------------------------------------------------------------
@@ -617,9 +617,9 @@ void CCurveData::Parse( ISceneTokenProcessor *tokenizer, ICurveDataAccessor *dat
s->SetCurveType( curveType );
}
if ( samples.Size() >= 1 )
if ( samples.Count() >= 1 )
{
for ( int i = 0; i < samples.Size(); i++ )
for ( int i = 0; i < samples.Count(); i++ )
{
CExpressionSample sample = samples[ i ];
@@ -838,7 +838,7 @@ void CChoreoScene::ParseFlexAnimations( ISceneTokenProcessor *tokenizer, CChoreo
}
}
if ( active || samples[ 0 ].Size() >= 1 )
if ( active || samples[ 0 ].Count() >= 1 )
{
// Add it in
CFlexAnimationTrack *track = e->AddTrack( flexcontroller );
@@ -851,7 +851,7 @@ void CChoreoScene::ParseFlexAnimations( ISceneTokenProcessor *tokenizer, CChoreo
for ( int t = 0; t < ( combo ? 2 : 1 ); t++ )
{
for ( int i = 0; i < samples[ t ].Size(); i++ )
for ( int i = 0; i < samples[ t ].Count(); i++ )
{
CExpressionSample *sample = &samples[ t ][ i ];
@@ -1525,7 +1525,7 @@ void CChoreoScene::InternalDetermineEventTypes()
{
m_bitvecHasEventOfType.ClearAll();
for ( int i = 0 ; i < m_Actors.Size(); i++ )
for ( int i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -1578,6 +1578,47 @@ float CChoreoScene::FindStopTime( void )
return lasttime;
}
float CChoreoScene::FindLastSpeakTime( void ) const
{
// walk backward from the end of events to the beginning looking for the last speak event
const int c = m_Events.Count();
int lastSpeakEvent;
for ( lastSpeakEvent = c-1 ; lastSpeakEvent >= 0 ; --lastSpeakEvent )
{
CChoreoEvent * RESTRICT e = m_Events[ lastSpeakEvent ];
Assert( e );
if ( e->GetType() == CChoreoEvent::SPEAK )
break;
}
if ( lastSpeakEvent < 0 ) // we found no speak event
{
return 0;
}
/*
// now walk forward from the beginning to the last event counting the duration of each event
float lasttime = 0.0f;
for ( int i = 0; i <= lastSpeakEvent ; i++ )
{
CChoreoEvent * RESTRICT e = m_Events[ i ];
Assert( e );
float checktime = e->HasEndTime() ? e->GetEndTime() : e->GetStartTime();
if ( checktime > lasttime )
{
lasttime = checktime;
}
}
return lasttime;
*/
CChoreoEvent * RESTRICT finalSpeechEvent = m_Events[lastSpeakEvent];
return finalSpeechEvent->HasEndTime() ? finalSpeechEvent->GetEndTime() : finalSpeechEvent->GetStartTime();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *fp -
@@ -1617,7 +1658,7 @@ void CChoreoScene::MarkForSaveAll( bool mark )
int i;
// Mark global events
for ( i = 0 ; i < m_Events.Size(); i++ )
for ( i = 0 ; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
if ( e->GetActor() )
@@ -1627,7 +1668,7 @@ void CChoreoScene::MarkForSaveAll( bool mark )
}
// Recursively mark everything else
for ( i = 0 ; i < m_Actors.Size(); i++ )
for ( i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -1650,7 +1691,7 @@ bool CChoreoScene::ExportMarkedToFile( const char *filename )
// Look for events that don't have actor/channel set
int i;
for ( i = 0 ; i < m_Events.Size(); i++ )
for ( i = 0 ; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
if ( e->GetActor() )
@@ -1659,7 +1700,7 @@ bool CChoreoScene::ExportMarkedToFile( const char *filename )
FileSaveEvent( buf, 0, e );
}
for ( i = 0 ; i < m_Actors.Size(); i++ )
for ( i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -1693,7 +1734,7 @@ bool CChoreoScene::SaveToFile( const char *filename )
// Look for events that don't have actor/channel set
int i;
for ( i = 0 ; i < m_Events.Size(); i++ )
for ( i = 0 ; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
if ( e->GetActor() )
@@ -1702,7 +1743,7 @@ bool CChoreoScene::SaveToFile( const char *filename )
FileSaveEvent( buf, 0, e );
}
for ( i = 0 ; i < m_Actors.Size(); i++ )
for ( i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -2217,7 +2258,7 @@ float CChoreoScene::FindAdjustedStartTime( void )
CChoreoEvent *e;
for ( int i = 0; i < m_Events.Size(); i++ )
for ( int i = 0; i < m_Events.Count(); i++ )
{
e = m_Events[ i ];
@@ -2249,7 +2290,7 @@ float CChoreoScene::FindAdjustedEndTime( void )
CChoreoEvent *e;
for ( int i = 0; i < m_Events.Size(); i++ )
for ( int i = 0; i < m_Events.Count(); i++ )
{
e = m_Events[ i ];
@@ -2288,7 +2329,7 @@ void CChoreoScene::ResetSimulation( bool forward /*= true*/, float starttime /*=
m_PauseEvents.RemoveAll();
// Put all items into the pending queue
for ( int i = 0; i < m_Events.Size(); i++ )
for ( int i = 0; i < m_Events.Count(); i++ )
{
e = m_Events[ i ];
e->ResetProcessing();
@@ -2315,7 +2356,7 @@ void CChoreoScene::ResetSimulation( bool forward /*= true*/, float starttime /*=
// choreoprintf( 0, "Start time %f\n", m_flCurrentTime );
m_flLastActiveTime = 0.0f;
m_nActiveEvents = m_Events.Size();
m_nActiveEvents = m_Events.Count();
m_flStartTime = starttime;
m_flEndTime = endtime;
@@ -2330,7 +2371,7 @@ bool CChoreoScene::CheckEventCompletion( void )
bool bAllCompleted = true;
// check all items in the active pending queue
for ( int i = 0; i < m_ActiveResumeConditions.Size(); i++ )
for ( int i = 0; i < m_ActiveResumeConditions.Count(); i++ )
{
e = m_ActiveResumeConditions[ i ];
@@ -2340,6 +2381,36 @@ bool CChoreoScene::CheckEventCompletion( void )
}
//-----------------------------------------------------------------------------
// Returns true if the last speech event in the scene has triggered,
// even if other scene events are still running or pending.
//-----------------------------------------------------------------------------
bool CChoreoScene::SpeechFinished( void ) const
{
// look through all the events and find the latest end time
// for a speech event. (They aren't necessarily stored in order.)
float lastEndTime = -1;
const int c = m_Events.Count();
for ( int i = 0 ; i < c ; ++i )
{
if ( m_Events[i]->GetType() == CChoreoEvent::SPEAK )
{
float endtime = m_Events[i]->GetEndTime();
lastEndTime = MAX( lastEndTime, endtime );
}
}
if ( lastEndTime >= 0 )
{
return m_flCurrentTime >= lastEndTime;
}
else
{
return false;
}
}
//-----------------------------------------------------------------------------
@@ -2348,7 +2419,7 @@ bool CChoreoScene::CheckEventCompletion( void )
//-----------------------------------------------------------------------------
bool CChoreoScene::SimulationFinished( void )
{
// Scene's linger for a little bit to allow things to settle
// Scenes linger for a little bit to allow things to settle
// check for events that are still active...
if ( m_flCurrentTime > m_flLatestTime )
@@ -2376,7 +2447,7 @@ CChoreoEvent *CChoreoScene::FindPauseBetweenTimes( float starttime, float endtim
CChoreoEvent *e;
// Iterate through all events in the scene
for ( int i = 0; i < m_PauseEvents.Size(); i++ )
for ( int i = 0; i < m_PauseEvents.Count(); i++ )
{
e = m_PauseEvents[ i ];
if ( !e )
@@ -2627,14 +2698,16 @@ void CChoreoScene::AddPauseEventDependency( CChoreoEvent *pauseEvent, CChoreoEve
//-----------------------------------------------------------------------------
// Purpose:
// Input : curtime -
// Input : dt -
//-----------------------------------------------------------------------------
void CChoreoScene::Think( float curtime )
{
CChoreoEvent *e;
float oldt = m_flCurrentTime;
float dt;
float dt = curtime - oldt;
bool playing_forward = ( dt >= 0.0f ) ? true : false;
m_nActiveEvents = 0;
@@ -2642,34 +2715,9 @@ void CChoreoScene::Think( float curtime )
CUtlRBTree< ActiveList, int > pending(0,0,EventLess);
// Handle loop events first:
//float flLoopPoint = LoopThink( curtime );
LoopThink( curtime );
if ( m_flCurrentTime != oldt )
{
// We hit a loop, we need to adjust the times.
//curtime = m_flCurrentTime + ( oldt - flLoopPoint ); // if we overshot, skip by how much we overshot
curtime = m_flCurrentTime;
Assert( curtime > 0.0f );
}
dt = curtime - oldt;
oldt = m_flCurrentTime;
bool playing_forward = ( dt >= 0.0f ) ? true : false;
//if ( !playing_forward )
//{
// Msg( "-----dt was negative. %f oldt: %f t: %f\n", dt, oldt, curtime );
//}
//else
//{
// Msg( "+++++dt was positive. %f oldt: %f t: %f\n", dt, oldt, curtime );
//}
// Iterate through all events in the scene
int i;
for ( i = 0; i < m_Events.Size(); i++ )
for ( i = 0; i < m_Events.Count(); i++ )
{
e = m_Events[ i ];
if ( !e )
@@ -2680,6 +2728,7 @@ void CChoreoScene::Think( float curtime )
if ( disposition != PROCESSING_TYPE_IGNORE )
{
ActiveList entry;
entry.e = e;
@@ -2690,6 +2739,8 @@ void CChoreoScene::Think( float curtime )
}
// Events are sorted start time and then by channel and actor slot or by name if those aren't equal
bool dump = false;
i = pending.FirstInorder();
while ( i != pending.InvalidIndex() )
{
@@ -2697,11 +2748,61 @@ void CChoreoScene::Think( float curtime )
Assert( entry->e );
ProcessActiveListEntry( entry );
if ( dump )
{
Msg( "%f == %s starting at %f (actor %p channel %p)\n",
m_flCurrentTime, entry->e->GetName(), entry->e->GetStartTime(),
entry->e->GetActor(), entry->e->GetChannel() );
}
switch ( entry->pt )
{
default:
case PROCESSING_TYPE_IGNORE:
{
Assert( 0 );
}
break;
case PROCESSING_TYPE_START:
case PROCESSING_TYPE_START_RESUMECONDITION:
{
entry->e->StartProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime );
if ( entry->pt == PROCESSING_TYPE_START_RESUMECONDITION )
{
Assert( entry->e->IsResumeCondition() );
m_ActiveResumeConditions.AddToTail( entry->e );
}
// This event can "pause" the scene, so we need to remember who "paused" the scene so that
// when we resume we can resume any suppressed events dependent on this pauser...
if ( entry->e->GetType() == CChoreoEvent::SECTION )
{
// So this event should be in the pauseevents list, otherwise this'll be -1
m_nLastPauseEvent = m_PauseEvents.Find( entry->e );
}
}
break;
case PROCESSING_TYPE_CONTINUE:
{
entry->e->ContinueProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime );
}
break;
case PROCESSING_TYPE_STOP:
{
entry->e->StopProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime );
}
break;
}
i = pending.NextInorder( i );
}
if ( dump )
{
Msg( "\n" );
}
// If a Process call slams this time, don't override it!!!
if ( oldt == m_flCurrentTime )
{
@@ -2715,102 +2816,6 @@ void CChoreoScene::Think( float curtime )
}
}
//-----------------------------------------------------------------------------
// Purpose: Loop points are handled prior to other events
// Input : curtime -
//-----------------------------------------------------------------------------
float CChoreoScene::LoopThink( float curtime )
{
float oldt = m_flCurrentTime;
float dt = curtime - oldt;
bool playing_forward = ( dt >= 0.0f ) ? true : false;
// Iterate through all events in the scene
CChoreoEvent *e;
int i;
for ( i = 0; i < m_Events.Size(); i++ )
{
e = m_Events[ i ];
if ( !e || e->GetType() != CChoreoEvent::LOOP )
continue;
PROCESSING_TYPE disposition;
m_nActiveEvents += EventThink( e, m_flCurrentTime, curtime, playing_forward, disposition );
if ( disposition != PROCESSING_TYPE_IGNORE )
{
ActiveList entry;
entry.e = e;
entry.pt = disposition;
//float ret = (float)atof( e->GetParameters() );
float ret = e->GetStartTime();
ProcessActiveListEntry( &entry );
return ret;
}
}
return 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : entry -
//-----------------------------------------------------------------------------
void CChoreoScene::ProcessActiveListEntry( ActiveList *entry )
{
const bool dump = false;
if ( dump )
{
Msg( "%f == %s starting at %f (actor %p channel %p)\n",
m_flCurrentTime, entry->e->GetName(), entry->e->GetStartTime(),
entry->e->GetActor(), entry->e->GetChannel() );
}
switch ( entry->pt )
{
default:
case PROCESSING_TYPE_IGNORE:
{
Assert( 0 );
}
break;
case PROCESSING_TYPE_START:
case PROCESSING_TYPE_START_RESUMECONDITION:
{
entry->e->StartProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime );
if ( entry->pt == PROCESSING_TYPE_START_RESUMECONDITION )
{
Assert( entry->e->IsResumeCondition() );
m_ActiveResumeConditions.AddToTail( entry->e );
}
// This event can "pause" the scene, so we need to remember who "paused" the scene so that
// when we resume we can resume any suppressed events dependent on this pauser...
if ( entry->e->GetType() == CChoreoEvent::SECTION )
{
// So this event should be in the pauseevents list, otherwise this'll be -1
m_nLastPauseEvent = m_PauseEvents.Find( entry->e );
}
}
break;
case PROCESSING_TYPE_CONTINUE:
{
entry->e->ContinueProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime );
}
break;
case PROCESSING_TYPE_STOP:
{
entry->e->StopProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime );
}
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
@@ -2867,7 +2872,7 @@ void CChoreoScene::RemoveActor( CChoreoActor *actor )
//-----------------------------------------------------------------------------
int CChoreoScene::FindActorIndex( CChoreoActor *actor )
{
for ( int i = 0; i < m_Actors.Size(); i++ )
for ( int i = 0; i < m_Actors.Count(); i++ )
{
if ( actor == m_Actors[ i ] )
{
@@ -2946,7 +2951,7 @@ void CChoreoScene::DeleteReferencedObjects( CChoreoEvent *event )
//-----------------------------------------------------------------------------
void CChoreoScene::DestroyActor( CChoreoActor *actor )
{
int size = m_Actors.Size();
int size = m_Actors.Count();
for ( int i = size - 1; i >= 0; i-- )
{
CChoreoActor *a = m_Actors[ i ];
@@ -2965,7 +2970,7 @@ void CChoreoScene::DestroyActor( CChoreoActor *actor )
//-----------------------------------------------------------------------------
void CChoreoScene::DestroyChannel( CChoreoChannel *channel )
{
int size = m_Channels.Size();
int size = m_Channels.Count();
for ( int i = size - 1; i >= 0; i-- )
{
CChoreoChannel *c = m_Channels[ i ];
@@ -2984,7 +2989,7 @@ void CChoreoScene::DestroyChannel( CChoreoChannel *channel )
//-----------------------------------------------------------------------------
void CChoreoScene::DestroyEvent( CChoreoEvent *event )
{
int size = m_Events.Size();
int size = m_Events.Count();
for ( int i = size - 1; i >= 0; i-- )
{
CChoreoEvent *e = m_Events[ i ];
@@ -3062,7 +3067,7 @@ void CChoreoScene::GetSceneTimes( float& start, float& end )
//-----------------------------------------------------------------------------
void CChoreoScene::ReconcileTags( void )
{
for ( int i = 0 ; i < m_Actors.Size(); i++ )
for ( int i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -3119,7 +3124,7 @@ void CChoreoScene::ReconcileTags( void )
//-----------------------------------------------------------------------------
CChoreoEvent *CChoreoScene::FindTargetingEvent( const char *wavname, const char *name )
{
for ( int i = 0 ; i < m_Actors.Size(); i++ )
for ( int i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -3161,7 +3166,7 @@ CChoreoEvent *CChoreoScene::FindTargetingEvent( const char *wavname, const char
//-----------------------------------------------------------------------------
CEventRelativeTag *CChoreoScene::FindTagByName( const char *wavname, const char *name )
{
for ( int i = 0 ; i < m_Actors.Size(); i++ )
for ( int i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -3203,16 +3208,16 @@ CEventRelativeTag *CChoreoScene::FindTagByName( const char *wavname, const char
//-----------------------------------------------------------------------------
void CChoreoScene::ExportEvents( const char *filename, CUtlVector< CChoreoEvent * >& events )
{
if ( events.Size() <= 0 )
if ( events.Count() <= 0 )
return;
// Create a serialization buffer
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
FilePrintf( buf, 0, "// Choreo version 1: <%i> Exported Events\n", events.Size() );
FilePrintf( buf, 0, "// Choreo version 1: <%i> Exported Events\n", events.Count() );
// Save out the selected events.
int i;
for ( i = 0 ; i < events.Size(); i++ )
for ( i = 0 ; i < events.Count(); i++ )
{
CChoreoEvent *e = events[ i ];
if ( !e->GetActor() )
@@ -3339,7 +3344,7 @@ float CChoreoScene::SnapTime( float t )
//-----------------------------------------------------------------------------
void CChoreoScene::ReconcileGestureTimes()
{
for ( int i = 0 ; i < m_Actors.Size(); i++ )
for ( int i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -3451,7 +3456,7 @@ bool CChoreoScene::Merge( CChoreoScene *other )
// Look for events that don't have actor/channel set
int i;
for ( i = 0 ; i < other->m_Events.Size(); i++ )
for ( i = 0 ; i < other->m_Events.Count(); i++ )
{
CChoreoEvent *e = other->m_Events[ i ];
if ( e->GetActor() )
@@ -3465,7 +3470,7 @@ bool CChoreoScene::Merge( CChoreoScene *other )
ecount++;
}
for ( i = 0 ; i < other->m_Actors.Size(); i++ )
for ( i = 0 ; i < other->m_Actors.Count(); i++ )
{
CChoreoActor *a = other->m_Actors[ i ];
@@ -3536,7 +3541,7 @@ bool CChoreoScene::Merge( CChoreoScene *other )
//-----------------------------------------------------------------------------
void CChoreoScene::ReconcileCloseCaption()
{
for ( int i = 0 ; i < m_Actors.Size(); i++ )
for ( int i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
@@ -3571,7 +3576,7 @@ void CChoreoScene::SetFileName( char const *fn )
bool CChoreoScene::GetPlayingSoundName( char *pchBuff, int iBuffLength )
{
for ( int i = 0; i < m_Events.Size(); i++ )
for ( int i = 0; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
if ( e->GetType() == CChoreoEvent::SPEAK && e->IsProcessing() )
@@ -3589,7 +3594,7 @@ bool CChoreoScene::GetPlayingSoundName( char *pchBuff, int iBuffLength )
//-----------------------------------------------------------------------------
bool CChoreoScene::HasUnplayedSpeech()
{
for ( int i = 0; i < m_Events.Size(); i++ )
for ( int i = 0; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
if ( e->GetType() == CChoreoEvent::SPEAK )
@@ -3608,7 +3613,7 @@ bool CChoreoScene::HasUnplayedSpeech()
//-----------------------------------------------------------------------------
bool CChoreoScene::HasFlexAnimation()
{
for ( int i = 0; i < m_Events.Size(); i++ )
for ( int i = 0; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
if ( e->GetType() == CChoreoEvent::FLEXANIMATION )
@@ -3695,7 +3700,7 @@ void CChoreoScene::SaveToBinaryBuffer( CUtlBuffer& buf, unsigned int nTextVersio
// Look for events that don't have actor/channel set
CUtlVector< CChoreoEvent * > eventList;
int i;
for ( i = 0 ; i < m_Events.Size(); i++ )
for ( i = 0 ; i < m_Events.Count(); i++ )
{
CChoreoEvent *e = m_Events[ i ];
if ( e->GetActor() )
@@ -3715,7 +3720,7 @@ void CChoreoScene::SaveToBinaryBuffer( CUtlBuffer& buf, unsigned int nTextVersio
// Now serialize the actors themselves
CUtlVector< CChoreoActor * > actorList;
for ( i = 0 ; i < m_Actors.Size(); i++ )
for ( i = 0 ; i < m_Actors.Count(); i++ )
{
CChoreoActor *a = m_Actors[ i ];
if ( !a )
+26 -24
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -39,21 +39,6 @@ class IChoreoStringPool;
//-----------------------------------------------------------------------------
class CChoreoScene : public ICurveDataAccessor
{
typedef enum
{
PROCESSING_TYPE_IGNORE = 0,
PROCESSING_TYPE_START,
PROCESSING_TYPE_START_RESUMECONDITION,
PROCESSING_TYPE_CONTINUE,
PROCESSING_TYPE_STOP,
} PROCESSING_TYPE;
struct ActiveList
{
PROCESSING_TYPE pt;
CChoreoEvent *e;
};
public:
// Construction
CChoreoScene( IChoreoEventCallback *callback );
@@ -87,7 +72,7 @@ public:
// Loading
bool ParseFromBuffer( char const *pFilename, ISceneTokenProcessor *tokenizer );
void SetPrintFunc( void ( *pfn )( PRINTF_FORMAT_STRING const char *fmt, ... ) );
void SetPrintFunc( void ( *pfn )( const char *fmt, ... ) );
// Saving
bool SaveToFile( const char *filename );
@@ -110,7 +95,7 @@ public:
static void ParseEdgeInfo( ISceneTokenProcessor *tokenizer, EdgeInfo_t *edgeinfo );
// Debugging
void SceneMsg( PRINTF_FORMAT_STRING const char *pFormat, ... );
void SceneMsg( const char *pFormat, ... );
void Print( void );
// Sound system needs to have sounds pre-queued by this much time
@@ -118,8 +103,6 @@ public:
// Simulation
void Think( float curtime );
float LoopThink( float curtime );
void ProcessActiveListEntry( ActiveList *entry );
// Retrieves time in simulation
float GetTime( void );
// Retrieves start/stop time for looped/debug scene
@@ -130,10 +113,14 @@ public:
// Has simulation finished
bool SimulationFinished( void );
// Has the last speech event in the scene already fired
bool SpeechFinished( void ) const;
// Reset simulation
void ResetSimulation( bool forward = true, float starttime = 0.0f, float endtime = 0.0f );
// Find time at which last simulation event is triggered
float FindStopTime( void );
// Find time at which last SPEAK event is complete
float FindLastSpeakTime( void ) const;
void ResumeSimulation( void );
@@ -255,6 +242,21 @@ private:
int IsTimeInRange( float t, float starttime, float endtime );
typedef enum
{
PROCESSING_TYPE_IGNORE = 0,
PROCESSING_TYPE_START,
PROCESSING_TYPE_START_RESUMECONDITION,
PROCESSING_TYPE_CONTINUE,
PROCESSING_TYPE_STOP,
} PROCESSING_TYPE;
struct ActiveList
{
PROCESSING_TYPE pt;
CChoreoEvent *e;
};
static bool EventLess( const CChoreoScene::ActiveList &al0, const CChoreoScene::ActiveList &al1 );
int EventThink( CChoreoEvent *e,
@@ -263,7 +265,7 @@ private:
bool playing_forward, PROCESSING_TYPE& disposition );
// Prints to debug console, etc
void choreoprintf( int level, PRINTF_FORMAT_STRING const char *fmt, ... );
void choreoprintf( int level, const char *fmt, ... );
// Initialize scene
void Init( IChoreoEventCallback *callback );
@@ -294,7 +296,7 @@ private:
// File I/O
public:
static void FilePrintf( CUtlBuffer& buf, int level, PRINTF_FORMAT_STRING const char *fmt, ... );
static void FilePrintf( CUtlBuffer& buf, int level, const char *fmt, ... );
private:
void FileSaveEvent( CUtlBuffer& buf, int level, CChoreoEvent *e );
void FileSaveChannel( CUtlBuffer& buf, int level, CChoreoChannel *c );
@@ -341,7 +343,7 @@ private:
float m_flLastActiveTime;
// Print callback function
void ( *m_pfnPrint )( PRINTF_FORMAT_STRING const char *fmt, ... );
void ( *m_pfnPrint )( const char *fmt, ... );
IChoreoEventCallback *m_pIChoreoEventCallback;
@@ -399,7 +401,7 @@ CChoreoScene *ChoreoLoadScene(
char const *filename,
IChoreoEventCallback *callback,
ISceneTokenProcessor *tokenizer,
void ( *pfn ) ( PRINTF_FORMAT_STRING const char *fmt, ... ) );
void ( *pfn ) ( const char *fmt, ... ) );
bool IsBufferBinaryVCD( char *pBuffer, int bufferSize );
+176 -159
View File
@@ -1,9 +1,9 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
//===========================================================================//
#include "cbase.h"
#include "collisionproperty.h"
@@ -18,6 +18,8 @@
#include "c_baseanimating.h"
#include "recvproxy.h"
#include "engine/ivdebugoverlay.h"
#else
#include "baseentity.h"
@@ -45,17 +47,16 @@ public:
virtual void LevelShutdownPostEntity();
// Members of IPartitionQueryCallback
virtual void OnPreQuery_V1() { Assert( 0 ); }
virtual void OnPreQuery( SpatialPartitionListMask_t listMask );
virtual void OnPostQuery( SpatialPartitionListMask_t listMask );
void AddEntity( CBaseEntity *pEntity );
~CDirtySpatialPartitionEntityList();
void LockPartitionForRead()
{
int nThreadId = g_nThreadID;
if ( m_nReadLockCount[nThreadId] == 0 )
if ( m_nReadLockCount[nThreadId] == 0 )
{
m_partitionMutex.LockForRead();
}
@@ -73,12 +74,10 @@ public:
private:
int m_nReadLockCount[MAX_THREADS_SUPPORTED];
CTSListWithFreeList<CBaseHandle> m_DirtyEntities;
CThreadSpinRWLock m_partitionMutex;
uint32 m_partitionWriteId;
CTHREADLOCALINT m_readLockCount;
int m_partitionWriteId;
int m_nReadLockCount[MAX_THREADS_SUPPORTED];
};
@@ -265,8 +264,6 @@ void CDirtySpatialPartitionEntityList::OnPostQuery( SpatialPartitionListMask_t l
BEGIN_DATADESC_NO_BASE( CCollisionProperty )
// DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ),
DEFINE_GLOBAL_FIELD( m_vecMinsPreScaled, FIELD_VECTOR ),
DEFINE_GLOBAL_FIELD( m_vecMaxsPreScaled, FIELD_VECTOR ),
DEFINE_GLOBAL_FIELD( m_vecMins, FIELD_VECTOR ),
DEFINE_GLOBAL_FIELD( m_vecMaxs, FIELD_VECTOR ),
DEFINE_KEYFIELD( m_nSolidType, FIELD_CHARACTER, "solid" ),
@@ -274,8 +271,6 @@ void CDirtySpatialPartitionEntityList::OnPostQuery( SpatialPartitionListMask_t l
DEFINE_FIELD( m_nSurroundType, FIELD_CHARACTER ),
DEFINE_FIELD( m_flRadius, FIELD_FLOAT ),
DEFINE_FIELD( m_triggerBloat, FIELD_CHARACTER ),
DEFINE_FIELD( m_vecSpecifiedSurroundingMinsPreScaled, FIELD_VECTOR ),
DEFINE_FIELD( m_vecSpecifiedSurroundingMaxsPreScaled, FIELD_VECTOR ),
DEFINE_FIELD( m_vecSpecifiedSurroundingMins, FIELD_VECTOR ),
DEFINE_FIELD( m_vecSpecifiedSurroundingMaxs, FIELD_VECTOR ),
DEFINE_FIELD( m_vecSurroundingMins, FIELD_VECTOR ),
@@ -292,8 +287,6 @@ void CDirtySpatialPartitionEntityList::OnPostQuery( SpatialPartitionListMask_t l
//-----------------------------------------------------------------------------
BEGIN_PREDICTION_DATA_NO_BASE( CCollisionProperty )
DEFINE_PRED_FIELD( m_vecMinsPreScaled, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_vecMaxsPreScaled, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_vecMins, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_vecMaxs, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_nSolidType, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
@@ -319,18 +312,18 @@ static void RecvProxy_SolidFlags( const CRecvProxyData *pData, void *pStruct, vo
((CCollisionProperty*)pStruct)->SetSolidFlags( pData->m_Value.m_Int );
}
static void RecvProxy_OBBMinsPreScaled( const CRecvProxyData *pData, void *pStruct, void *pOut )
static void RecvProxy_OBBMins( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CCollisionProperty *pProp = ((CCollisionProperty*)pStruct);
Vector &vecMins = *((Vector*)pData->m_Value.m_Vector);
pProp->SetCollisionBounds( vecMins, pProp->OBBMaxsPreScaled() );
pProp->SetCollisionBounds( vecMins, pProp->OBBMaxs() );
}
static void RecvProxy_OBBMaxsPreScaled( const CRecvProxyData *pData, void *pStruct, void *pOut )
static void RecvProxy_OBBMaxs( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CCollisionProperty *pProp = ((CCollisionProperty*)pStruct);
Vector &vecMaxs = *((Vector*)pData->m_Value.m_Vector);
pProp->SetCollisionBounds( pProp->OBBMinsPreScaled(), vecMaxs );
pProp->SetCollisionBounds( pProp->OBBMins(), vecMaxs );
}
static void RecvProxy_VectorDirtySurround( const CRecvProxyData *pData, void *pStruct, void *pOut )
@@ -371,29 +364,21 @@ static void SendProxy_SolidFlags( const SendProp *pProp, const void *pStruct, co
BEGIN_NETWORK_TABLE_NOBASE( CCollisionProperty, DT_CollisionProperty )
#ifdef CLIENT_DLL
RecvPropVector( RECVINFO(m_vecMinsPreScaled), 0, RecvProxy_OBBMinsPreScaled ),
RecvPropVector( RECVINFO(m_vecMaxsPreScaled), 0, RecvProxy_OBBMaxsPreScaled ),
RecvPropVector( RECVINFO(m_vecMins), 0 ),
RecvPropVector( RECVINFO(m_vecMaxs), 0 ),
RecvPropVector( RECVINFO(m_vecMins), 0, RecvProxy_OBBMins ),
RecvPropVector( RECVINFO(m_vecMaxs), 0, RecvProxy_OBBMaxs ),
RecvPropInt( RECVINFO( m_nSolidType ), 0, RecvProxy_Solid ),
RecvPropInt( RECVINFO( m_usSolidFlags ), 0, RecvProxy_SolidFlags ),
RecvPropInt( RECVINFO(m_nSurroundType), 0, RecvProxy_IntDirtySurround ),
RecvPropInt( RECVINFO(m_triggerBloat), 0, RecvProxy_IntDirtySurround ),
RecvPropVector( RECVINFO(m_vecSpecifiedSurroundingMinsPreScaled), 0, RecvProxy_VectorDirtySurround ),
RecvPropVector( RECVINFO(m_vecSpecifiedSurroundingMaxsPreScaled), 0, RecvProxy_VectorDirtySurround ),
RecvPropVector( RECVINFO(m_vecSpecifiedSurroundingMins), 0, RecvProxy_VectorDirtySurround ),
RecvPropVector( RECVINFO(m_vecSpecifiedSurroundingMaxs), 0, RecvProxy_VectorDirtySurround ),
#else
SendPropVector( SENDINFO(m_vecMinsPreScaled), 0, SPROP_NOSCALE),
SendPropVector( SENDINFO(m_vecMaxsPreScaled), 0, SPROP_NOSCALE),
SendPropVector( SENDINFO(m_vecMins), 0, SPROP_NOSCALE),
SendPropVector( SENDINFO(m_vecMaxs), 0, SPROP_NOSCALE),
SendPropInt( SENDINFO( m_nSolidType ), 3, SPROP_UNSIGNED, SendProxy_Solid ),
SendPropInt( SENDINFO( m_usSolidFlags ), FSOLID_MAX_BITS, SPROP_UNSIGNED, SendProxy_SolidFlags ),
SendPropInt( SENDINFO( m_nSurroundType ), SURROUNDING_TYPE_BIT_COUNT, SPROP_UNSIGNED ),
SendPropInt( SENDINFO(m_triggerBloat), 0, SPROP_UNSIGNED),
SendPropVector( SENDINFO(m_vecSpecifiedSurroundingMinsPreScaled), 0, SPROP_NOSCALE),
SendPropVector( SENDINFO(m_vecSpecifiedSurroundingMaxsPreScaled), 0, SPROP_NOSCALE),
SendPropVector( SENDINFO(m_vecSpecifiedSurroundingMins), 0, SPROP_NOSCALE),
SendPropVector( SENDINFO(m_vecSpecifiedSurroundingMaxs), 0, SPROP_NOSCALE),
#endif
@@ -422,8 +407,6 @@ CCollisionProperty::~CCollisionProperty()
void CCollisionProperty::Init( CBaseEntity *pEntity )
{
m_pOuter = pEntity;
m_vecMinsPreScaled.GetForModify().Init();
m_vecMaxsPreScaled.GetForModify().Init();
m_vecMins.GetForModify().Init();
m_vecMaxs.GetForModify().Init();
m_flRadius = 0.0f;
@@ -435,8 +418,6 @@ void CCollisionProperty::Init( CBaseEntity *pEntity )
m_nSurroundType = USE_OBB_COLLISION_BOUNDS;
m_vecSurroundingMins = vec3_origin;
m_vecSurroundingMaxs = vec3_origin;
m_vecSpecifiedSurroundingMinsPreScaled.GetForModify().Init();
m_vecSpecifiedSurroundingMaxsPreScaled.GetForModify().Init();
m_vecSpecifiedSurroundingMins.GetForModify().Init();
m_vecSpecifiedSurroundingMaxs.GetForModify().Init();
}
@@ -662,73 +643,22 @@ const matrix3x4_t& CCollisionProperty::CollisionToWorldTransform() const
//-----------------------------------------------------------------------------
// Sets the collision bounds + the size
//-----------------------------------------------------------------------------
void CCollisionProperty::SetCollisionBounds( const Vector &mins, const Vector &maxs )
void CCollisionProperty::SetCollisionBounds( const Vector& mins, const Vector &maxs )
{
if ( ( m_vecMinsPreScaled != mins ) || ( m_vecMaxsPreScaled != maxs ) )
{
m_vecMinsPreScaled = mins;
m_vecMaxsPreScaled = maxs;
}
bool bDirty = false;
// Check if it's a scaled model
CBaseAnimating *pAnim = GetOuter()->GetBaseAnimating();
if ( pAnim && pAnim->GetModelScale() != 1.0f )
{
// Do the scaling
Vector vecNewMins = mins * pAnim->GetModelScale();
Vector vecNewMaxs = maxs * pAnim->GetModelScale();
if ( ( m_vecMins != vecNewMins ) || ( m_vecMaxs != vecNewMaxs ) )
{
m_vecMins = vecNewMins;
m_vecMaxs = vecNewMaxs;
bDirty = true;
}
}
else
{
// No scaling needed!
if ( ( m_vecMins != mins ) || ( m_vecMaxs != maxs ) )
{
m_vecMins = mins;
m_vecMaxs = maxs;
bDirty = true;
}
}
if ( (m_vecMins == mins) && (m_vecMaxs == maxs) )
return;
m_vecMins = mins;
m_vecMaxs = maxs;
if ( bDirty )
{
//ASSERT_COORD( m_vecMins.Get() );
//ASSERT_COORD( m_vecMaxs.Get() );
//ASSERT_COORD( mins );
//ASSERT_COORD( maxs );
Vector vecSize;
VectorSubtract( m_vecMaxs, m_vecMins, vecSize );
m_flRadius = vecSize.Length() * 0.5f;
Vector vecSize;
VectorSubtract( maxs, mins, vecSize );
m_flRadius = vecSize.Length() * 0.5f;
MarkSurroundingBoundsDirty();
}
}
//-----------------------------------------------------------------------------
// Rebuilds the scaled bounds from the prescaled bounds after a model's scale has changed
//-----------------------------------------------------------------------------
void CCollisionProperty::RefreshScaledCollisionBounds( void )
{
SetCollisionBounds( m_vecMinsPreScaled, m_vecMaxsPreScaled );
SurroundingBoundsType_t nSurroundType = static_cast< SurroundingBoundsType_t >( m_nSurroundType.Get() );
if ( nSurroundType == USE_SPECIFIED_BOUNDS )
{
SetSurroundingBoundsType( nSurroundType,
&(m_vecSpecifiedSurroundingMinsPreScaled.Get()),
&(m_vecSpecifiedSurroundingMaxsPreScaled.Get()) );
}
else
{
SetSurroundingBoundsType( nSurroundType );
}
MarkSurroundingBoundsDirty();
}
@@ -746,6 +676,20 @@ float CCollisionProperty::BoundingRadius2D() const
}
//-----------------------------------------------------------------------------
// Bounding representation (OBB)
//-----------------------------------------------------------------------------
const Vector& CCollisionProperty::OBBMins( ) const
{
return m_vecMins.Get();
}
const Vector& CCollisionProperty::OBBMaxs( ) const
{
return m_vecMaxs.Get();
}
//-----------------------------------------------------------------------------
// Special trigger representation (OBB)
//-----------------------------------------------------------------------------
@@ -943,6 +887,19 @@ float CCollisionProperty::CalcDistanceFromPoint( const Vector &vecWorldPt ) cons
}
//-----------------------------------------------------------------------------
// Computes the square distance of the closest point in the OBB to a point specified in world space
//-----------------------------------------------------------------------------
float CCollisionProperty::CalcSqrDistanceFromPoint( const Vector &vecWorldPt ) const
{
// Calculate physics force
Vector localPt, localClosestPt;
WorldToCollisionSpace( vecWorldPt, &localPt );
CalcClosestPointOnAABB( m_vecMins.Get(), m_vecMaxs.Get(), localPt, localClosestPt );
return localPt.DistToSqr( localClosestPt );
}
//-----------------------------------------------------------------------------
// Compute the largest dot product of the OBB and the specified direction vector
//-----------------------------------------------------------------------------
@@ -1016,6 +973,60 @@ bool CCollisionProperty::ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vec
return false;
}
//-----------------------------------------------------------------------------
// Computes the surrounding collision bounds based on the current sequence box
//-----------------------------------------------------------------------------
void CCollisionProperty::ComputeOBBBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
{
bool bUseVPhysics = false;
if ( ( GetSolid() == SOLID_VPHYSICS ) && ( GetOuter()->GetMoveType() == MOVETYPE_VPHYSICS ) )
{
// UNDONE: This may not be necessary any more.
IPhysicsObject *pPhysics = GetOuter()->VPhysicsGetObject();
bUseVPhysics = pPhysics && pPhysics->IsAsleep();
}
ComputeCollisionSurroundingBox( bUseVPhysics, pVecWorldMins, pVecWorldMaxs );
}
//-----------------------------------------------------------------------------
// Computes the surrounding collision bounds from the current sequence box
//-----------------------------------------------------------------------------
void CCollisionProperty::ComputeRotationExpandedSequenceBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
{
CBaseAnimating *pAnim = GetOuter()->GetBaseAnimating();
if ( !pAnim )
{
ComputeOBBBounds( pVecWorldMins, pVecWorldMaxs );
return;
}
Vector mins, maxs;
pAnim->ExtractBbox( pAnim->GetSequence(), mins, maxs );
float flRadius = MAX( MAX( FloatMakePositive( mins.x ), FloatMakePositive( maxs.x ) ),
MAX( FloatMakePositive( mins.y ), FloatMakePositive( maxs.y ) ) );
mins.x = mins.y = -flRadius;
maxs.x = maxs.y = flRadius;
// Add bloat to account for gesture sequences
Vector vecBloat( 6, 6, 0 );
mins -= vecBloat;
maxs += vecBloat;
// NOTE: This is necessary because the server doesn't know how to blend
// animations together. Therefore, we have to just pick a box that can
// surround all of our potential sequences. This should be something we
// should be able to compute @ tool time instead, however.
VectorMin( mins, m_vecSurroundingMins, mins );
VectorMax( maxs, m_vecSurroundingMaxs, maxs );
VectorAdd( mins, GetCollisionOrigin(), *pVecWorldMins );
VectorAdd( maxs, GetCollisionOrigin(), *pVecWorldMaxs );
}
//-----------------------------------------------------------------------------
// Expand trigger bounds..
//-----------------------------------------------------------------------------
@@ -1091,6 +1102,10 @@ void CCollisionProperty::ComputeCollisionSurroundingBox( bool bUseVPhysics, Vect
//-----------------------------------------------------------------------------
// Computes the surrounding collision bounds based on whatever algorithm we want...
//-----------------------------------------------------------------------------
#ifdef CLIENT_DLL
static ConVar cl_show_bounds_errors( "cl_show_bounds_errors", "0" );
#endif
void CCollisionProperty::ComputeSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
{
if (( GetSolid() == SOLID_CUSTOM ) && (m_nSurroundType != USE_GAME_CODE ))
@@ -1105,17 +1120,8 @@ void CCollisionProperty::ComputeSurroundingBox( Vector *pVecWorldMins, Vector *p
switch( m_nSurroundType )
{
case USE_OBB_COLLISION_BOUNDS:
{
Assert( GetSolid() != SOLID_CUSTOM );
bool bUseVPhysics = false;
if ( ( GetSolid() == SOLID_VPHYSICS ) && ( GetOuter()->GetMoveType() == MOVETYPE_VPHYSICS ) )
{
// UNDONE: This may not be necessary any more.
IPhysicsObject *pPhysics = GetOuter()->VPhysicsGetObject();
bUseVPhysics = pPhysics && pPhysics->IsAsleep();
}
ComputeCollisionSurroundingBox( bUseVPhysics, pVecWorldMins, pVecWorldMaxs );
}
Assert( GetSolid() != SOLID_CUSTOM );
ComputeOBBBounds( pVecWorldMins, pVecWorldMaxs );
break;
case USE_BEST_COLLISION_BOUNDS:
@@ -1123,6 +1129,10 @@ void CCollisionProperty::ComputeSurroundingBox( Vector *pVecWorldMins, Vector *p
ComputeCollisionSurroundingBox( (GetSolid() == SOLID_VPHYSICS), pVecWorldMins, pVecWorldMaxs );
break;
case USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS:
ComputeRotationExpandedSequenceBounds( pVecWorldMins, pVecWorldMaxs );
break;
case USE_COLLISION_BOUNDS_NEVER_VPHYSICS:
Assert( GetSolid() != SOLID_CUSTOM );
ComputeCollisionSurroundingBox( false, pVecWorldMins, pVecWorldMaxs );
@@ -1149,25 +1159,56 @@ void CCollisionProperty::ComputeSurroundingBox( Vector *pVecWorldMins, Vector *p
return;
}
#ifdef DEBUG
/*
// For debugging purposes, make sure the bounds actually does surround the thing.
// Otherwise the optimization we were using isn't really all that great, is it?
Vector vecTestMins, vecTestMaxs;
ComputeCollisionSurroundingBox( (GetSolid() == SOLID_VPHYSICS), &vecTestMins, &vecTestMaxs );
//#ifdef DEBUG
#ifdef CLIENT_DLL
if ( cl_show_bounds_errors.GetBool() && ( m_nSurroundType == USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS ) )
{
// For debugging purposes, make sure the bounds actually does surround the thing.
// Otherwise the optimization we were using isn't really all that great, is it?
Vector vecTestMins, vecTestMaxs;
if ( GetOuter()->GetBaseAnimating() )
{
GetOuter()->GetBaseAnimating()->InvalidateBoneCache();
}
ComputeHitboxSurroundingBox( &vecTestMins, &vecTestMaxs );
Assert( vecTestMins.x >= pVecWorldMins->x && vecTestMins.y >= pVecWorldMins->y && vecTestMins.z >= pVecWorldMins->z );
Assert( vecTestMaxs.x <= pVecWorldMaxs->x && vecTestMaxs.y <= pVecWorldMaxs->y && vecTestMaxs.z <= pVecWorldMaxs->z );
// Now that we have the basics, let's expand for hitboxes if appropriate
Vector vecWorldHitboxMins, vecWorldHitboxMaxs;
if ( ComputeHitboxSurroundingBox( &vecWorldHitboxMins, &vecWorldHitboxMaxs ) )
{
VectorMin( vecWorldHitboxMaxs, vecTestMins, vecTestMins );
VectorMax( vecWorldHitboxMaxs, vecTestMaxs, vecTestMaxs );
if ( vecTestMins.x < pVecWorldMins->x || vecTestMins.y < pVecWorldMins->y || vecTestMins.z < pVecWorldMins->z ||
vecTestMaxs.x > pVecWorldMaxs->x || vecTestMaxs.y > pVecWorldMaxs->y || vecTestMaxs.z > pVecWorldMaxs->z )
{
const char *pSeqName = "<unknown seq>";
C_BaseAnimating *pAnim = GetOuter()->GetBaseAnimating();
if ( pAnim )
{
int nSequence = pAnim->GetSequence();
pSeqName = pAnim->GetSequenceName( nSequence );
}
Warning( "*** Bounds problem, index %d Eng %s, Seqeuence %s ", GetOuter()->entindex(), GetOuter()->GetClassname(), pSeqName );
Vector vecDelta = *pVecWorldMins - vecTestMins;
Vector vecDelta2 = vecTestMaxs - *pVecWorldMaxs;
if ( vecDelta.x > 0.0f || vecDelta2.x > 0.0f || vecDelta.y > 0.0f || vecDelta2.y > 0.0f )
{
Msg( "Outside X/Y by %.2f ", MAX( MAX( vecDelta.x, vecDelta2.x ), MAX( vecDelta.y, vecDelta2.y ) ) );
}
if ( vecDelta.z > 0.0f || vecDelta2.z > 0.0f )
{
Msg( "Outside Z by (below) %.2f, (above) %.2f ", MAX( vecDelta.z, 0.0f ), MAX( vecDelta2.z, 0.0f ) );
}
Msg( "\n" );
char pTemp[MAX_PATH];
Q_snprintf( pTemp, sizeof(pTemp), "%s [seq: %s]", GetOuter()->GetClassname(), pSeqName );
debugoverlay->AddBoxOverlay( vec3_origin, vecTestMins, vecTestMaxs, vec3_angle, 255, 0, 0, 0, 2 );
debugoverlay->AddBoxOverlay( vec3_origin, *pVecWorldMins, *pVecWorldMaxs, vec3_angle, 0, 0, 255, 0, 2 );
debugoverlay->AddTextOverlay( ( vecTestMins + vecTestMaxs ) * 0.5f, 2, pTemp );
}
}
Assert( vecTestMins.x >= pVecWorldMins->x && vecTestMins.y >= pVecWorldMins->y && vecTestMins.z >= pVecWorldMins->z );
Assert( vecTestMaxs.x <= pVecWorldMaxs->x && vecTestMaxs.y <= pVecWorldMaxs->y && vecTestMaxs.z <= pVecWorldMaxs->z );
*/
#endif
//#endif
}
@@ -1185,32 +1226,10 @@ void CCollisionProperty::SetSurroundingBoundsType( SurroundingBoundsType_t type,
else
{
Assert( pMins && pMaxs );
m_vecSpecifiedSurroundingMinsPreScaled = *pMins;
m_vecSpecifiedSurroundingMaxsPreScaled = *pMaxs;
// Check if it's a scaled model
CBaseAnimating *pAnim = GetOuter()->GetBaseAnimating();
if ( pAnim && pAnim->GetModelScale() != 1.0f )
{
// Do the scaling
Vector vecNewMins = *pMins * pAnim->GetModelScale();
Vector vecNewMaxs = *pMaxs * pAnim->GetModelScale();
m_vecSpecifiedSurroundingMins = vecNewMins;
m_vecSpecifiedSurroundingMaxs = vecNewMaxs;
m_vecSurroundingMins = vecNewMins;
m_vecSurroundingMaxs = vecNewMaxs;
}
else
{
// No scaling needed!
m_vecSpecifiedSurroundingMins = *pMins;
m_vecSpecifiedSurroundingMaxs = *pMaxs;
m_vecSurroundingMins = *pMins;
m_vecSurroundingMaxs = *pMaxs;
}
m_vecSpecifiedSurroundingMins = *pMins;
m_vecSpecifiedSurroundingMaxs = *pMaxs;
m_vecSurroundingMins = *pMins;
m_vecSurroundingMaxs = *pMaxs;
ASSERT_COORD( m_vecSurroundingMins );
ASSERT_COORD( m_vecSurroundingMaxs );
@@ -1223,10 +1242,16 @@ void CCollisionProperty::SetSurroundingBoundsType( SurroundingBoundsType_t type,
//-----------------------------------------------------------------------------
void CCollisionProperty::MarkSurroundingBoundsDirty()
{
// don't bother with the world
if ( m_pOuter->entindex() == 0 )
return;
GetOuter()->AddEFlags( EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS );
MarkPartitionHandleDirty();
#ifdef CLIENT_DLL
GetOuter()->MarkRenderHandleDirty();
g_pClientShadowMgr->AddToDirtyShadowList( GetOuter() );
g_pClientShadowMgr->MarkRenderToTextureShadowDirty( GetOuter()->GetShadowHandle() );
#else
GetOuter()->NetworkProp()->MarkPVSInformationDirty();
@@ -1255,6 +1280,7 @@ bool CCollisionProperty::DoesVPhysicsInvalidateSurroundingBox( ) const
case USE_HITBOXES:
case USE_ROTATION_EXPANDED_BOUNDS:
case USE_SPECIFIED_BOUNDS:
case USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS:
return false;
default:
@@ -1362,20 +1388,11 @@ void CCollisionProperty::UpdateServerPartitionMask( )
//-----------------------------------------------------------------------------
void CCollisionProperty::MarkPartitionHandleDirty()
{
// don't bother with the world
if ( m_pOuter->entindex() == 0 )
return;
if ( !m_pOuter->IsEFlagSet( EFL_DIRTY_SPATIAL_PARTITION ) )
{
m_pOuter->AddEFlags( EFL_DIRTY_SPATIAL_PARTITION );
s_DirtyKDTree.AddEntity( m_pOuter );
m_pOuter->AddEFlags( EFL_DIRTY_SPATIAL_PARTITION );
}
#ifdef CLIENT_DLL
GetOuter()->MarkRenderHandleDirty();
g_pClientShadowMgr->AddToDirtyShadowList( GetOuter() );
#endif
}
+33 -34
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -46,6 +46,7 @@ enum SurroundingBoundsType_t
USE_GAME_CODE,
USE_ROTATION_EXPANDED_BOUNDS,
USE_COLLISION_BOUNDS_NEVER_VPHYSICS,
USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS,
SURROUNDING_TYPE_BIT_COUNT = 3
};
@@ -72,10 +73,8 @@ public:
// Methods of ICollideable
virtual IHandleEntity *GetEntityHandle();
virtual const Vector& OBBMinsPreScaled() const { return m_vecMinsPreScaled.Get(); }
virtual const Vector& OBBMaxsPreScaled() const { return m_vecMaxsPreScaled.Get(); }
virtual const Vector& OBBMins() const { return m_vecMins.Get(); }
virtual const Vector& OBBMaxs() const { return m_vecMaxs.Get(); }
virtual const Vector& OBBMins( ) const;
virtual const Vector& OBBMaxs( ) const;
virtual void WorldSpaceTriggerBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) const;
virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
@@ -104,9 +103,6 @@ public:
// Sets the collision bounds + the size (OBB)
void SetCollisionBounds( const Vector& mins, const Vector &maxs );
// Rebuilds the scaled bounds from the pre-scaled bounds after a model's scale has changed
void RefreshScaledCollisionBounds( void );
// Sets special trigger bounds. The bloat amount indicates how much bigger the
// trigger bounds should be beyond the bounds set in SetCollisionBounds
// This method will also set the FSOLID flag FSOLID_USE_TRIGGER_BOUNDS
@@ -115,6 +111,7 @@ public:
// Sets the method by which the surrounding collision bounds is set
// You must pass in values for mins + maxs if you select the USE_SPECIFIED_BOUNDS type.
void SetSurroundingBoundsType( SurroundingBoundsType_t type, const Vector *pMins = NULL, const Vector *pMaxs = NULL );
SurroundingBoundsType_t GetSurroundingBoundsType() const;
// Sets the solid type (which type of collision representation)
void SetSolid( SolidType_t val );
@@ -169,12 +166,6 @@ public:
// Computes a bounding box in world space surrounding the collision bounds
void WorldSpaceAABB( Vector *pWorldMins, Vector *pWorldMaxs ) const;
// Get the collision space mins directly
const Vector & CollisionSpaceMins( void ) const;
// Get the collision space maxs directly
const Vector & CollisionSpaceMaxs( void ) const;
// Computes a "normalized" point (range 0,0,0 - 1,1,1) in collision space
// Useful for things like getting a point 75% of the way along z on the OBB, for example
const Vector & NormalizedToCollisionSpace( const Vector &in, Vector *pResult ) const;
@@ -193,6 +184,7 @@ public:
// Computes the distance from a point in world space to the OBB
float CalcDistanceFromPoint( const Vector &vecWorldPt ) const;
float CalcSqrDistanceFromPoint( const Vector &vecWorldPt ) const;
// Does a rotation make us need to recompute the surrounding box?
bool DoesRotationInvalidateSurroundingBox( ) const;
@@ -200,6 +192,9 @@ public:
// Does VPhysicsUpdate make us need to recompute the surrounding box?
bool DoesVPhysicsInvalidateSurroundingBox( ) const;
// Does a sequence change make us need to recompute the surrounding box?
bool DoesSequenceChangeInvalidateSurroundingBox( ) const;
// Marks the entity has having a dirty surrounding box
void MarkSurroundingBoundsDirty();
@@ -217,10 +212,16 @@ private:
bool ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
bool ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
// Computes the surrounding collision bounds based on the current sequence box
void ComputeOBBBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
// Computes the surrounding collision bounds from the current sequence box
void ComputeRotationExpandedSequenceBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
// Computes the surrounding collision bounds based on whatever algorithm we want...
void ComputeCollisionSurroundingBox( bool bUseVPhysics, Vector *pVecWorldMins, Vector *pVecWorldMaxs );
// Computes the surrounding collision bounds from the the OBB (not vphysics)
// Computes the surrounding collision bounds from the OBB (not vphysics)
void ComputeRotationExpandedBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
// Computes the surrounding collision bounds based on whatever algorithm we want...
@@ -239,27 +240,24 @@ private:
private:
CBaseEntity *m_pOuter;
CNetworkVector( m_vecMinsPreScaled );
CNetworkVector( m_vecMaxsPreScaled );
// BEGIN PREDICTION DATA COMPACTION (these fields are together to allow for faster copying in prediction system)
CNetworkVector( m_vecMins );
CNetworkVector( m_vecMaxs );
float m_flRadius;
CNetworkVar( unsigned short, m_usSolidFlags );
// One of the SOLID_ defines. Use GetSolid/SetSolid.
CNetworkVar( unsigned char, m_nSolidType );
CNetworkVar( unsigned char , m_triggerBloat );
// END PREDICTION DATA COMPACTION
float m_flRadius;
// Spatial partition
SpatialPartitionHandle_t m_Partition;
CNetworkVar( unsigned char, m_nSurroundType );
// One of the SOLID_ defines. Use GetSolid/SetSolid.
CNetworkVar( unsigned char, m_nSolidType );
CNetworkVar( unsigned char , m_triggerBloat );
// SUCKY: We didn't use to have to store this previously
// but storing it here means that we can network it + avoid a ton of
// client-side mismatch problems
CNetworkVector( m_vecSpecifiedSurroundingMinsPreScaled );
CNetworkVector( m_vecSpecifiedSurroundingMaxsPreScaled );
CNetworkVector( m_vecSpecifiedSurroundingMins );
CNetworkVector( m_vecSpecifiedSurroundingMaxs );
@@ -311,6 +309,10 @@ inline unsigned short CCollisionProperty::GetPartitionHandle() const
return m_Partition;
}
inline SurroundingBoundsType_t CCollisionProperty::GetSurroundingBoundsType() const
{
return (SurroundingBoundsType_t)m_nSurroundType.Get();
}
//-----------------------------------------------------------------------------
// Methods related to size
@@ -456,16 +458,12 @@ inline void CCollisionProperty::WorldSpaceAABB( Vector *pWorldMins, Vector *pWor
}
// Get the collision space mins directly
inline const Vector & CCollisionProperty::CollisionSpaceMins( void ) const
//-----------------------------------------------------------------------------
// Does a rotation make us need to recompute the surrounding box?
//-----------------------------------------------------------------------------
inline bool CCollisionProperty::DoesSequenceChangeInvalidateSurroundingBox( ) const
{
return m_vecMins;
}
// Get the collision space maxs directly
inline const Vector & CCollisionProperty::CollisionSpaceMaxs( void ) const
{
return m_vecMaxs;
return ( m_nSurroundType == USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS );
}
@@ -491,6 +489,7 @@ inline bool CCollisionProperty::DoesRotationInvalidateSurroundingBox( ) const
case USE_ROTATION_EXPANDED_BOUNDS:
case USE_SPECIFIED_BOUNDS:
case USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS:
return false;
default:
@@ -1,80 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "cs_achievements_and_stats_interface.h"
#include "baseachievement.h"
#include "GameEventListener.h"
#include "hl2orange.spa.h"
#include "iachievementmgr.h"
#include "utlmap.h"
#include "steam/steam_api.h"
#include "vgui_controls/Panel.h"
#include "vgui_controls/PHandle.h"
#include "vgui_controls/MenuItem.h"
#include "vgui_controls/MessageDialog.h"
#include "cs_gamestats_shared.h"
#include "../client/cstrike/VGUI/achievement_stats_summary.h"
#include "vgui/IInput.h"
#include "vgui/ILocalize.h"
#include "vgui/IPanel.h"
#include "vgui/ISurface.h"
#include "vgui/ISystem.h"
#include "vgui/IVGui.h"
#if defined(CSTRIKE_DLL) && defined(CLIENT_DLL)
CSAchievementsAndStatsInterface::CSAchievementsAndStatsInterface() : AchievementsAndStatsInterface()
{
m_pAchievementAndStatsSummary = NULL;
g_pAchievementsAndStatsInterface = this;
}
void CSAchievementsAndStatsInterface::CreatePanel( vgui::Panel* pParent )
{
// Create achievement & stats dialog if not already created
if ( !m_pAchievementAndStatsSummary )
{
m_pAchievementAndStatsSummary = new CAchievementAndStatsSummary(NULL);
}
if ( m_pAchievementAndStatsSummary )
{
m_pAchievementAndStatsSummary->SetParent(pParent);
}
}
void CSAchievementsAndStatsInterface::DisplayPanel()
{
// Position & show dialog
PositionDialog(m_pAchievementAndStatsSummary);
m_pAchievementAndStatsSummary->Activate();
//Make sure the top of the page appears on the screen (for video modes such as 1280x720).
int x, y;
m_pAchievementAndStatsSummary->GetPos( x, y );
if ( y < 0 )
{
m_pAchievementAndStatsSummary->SetPos( x, 0 );
}
}
void CSAchievementsAndStatsInterface::ReleasePanel()
{
// Make sure the BasePanel doesn't try to delete this, because it doesn't really own it.
if ( m_pAchievementAndStatsSummary )
{
m_pAchievementAndStatsSummary->SetParent((vgui::Panel*)NULL);
}
}
#endif
@@ -1,47 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef CSACHIEVEMENTSANDSTATSINTERFACE_H
#define CSACHIEVEMENTSANDSTATSINTERFACE_H
#ifdef _WIN32
#pragma once
#endif
#include "achievements_and_stats_interface.h"
#include "vgui_controls/Panel.h"
#include "vgui_controls/PHandle.h"
#include "vgui_controls/MenuItem.h"
#include "vgui_controls/MessageDialog.h"
#include "cs_gamestats_shared.h"
#include "../client/cstrike/VGUI/achievement_stats_summary.h"
#include "vgui/IInput.h"
#include "vgui/ILocalize.h"
#include "vgui/IPanel.h"
#include "vgui/ISurface.h"
#include "vgui/ISystem.h"
#include "vgui/IVGui.h"
#if defined(CSTRIKE_DLL) && defined(CLIENT_DLL)
class CSAchievementsAndStatsInterface : public AchievementsAndStatsInterface
{
public:
CSAchievementsAndStatsInterface();
virtual void CreatePanel( vgui::Panel* pParent );
virtual void DisplayPanel();
virtual void ReleasePanel();
virtual int GetAchievementsPanelMinWidth( void ) const { return cAchievementsDialogMinWidth; }
protected:
vgui::DHANDLE<vgui::Frame> m_pAchievementAndStatsSummary;
};
#endif
#endif // CSACHIEVEMENTSANDSTATSINTERFACE_H
-727
View File
@@ -1,727 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include <time.h>
#ifdef CLIENT_DLL
#include "achievementmgr.h"
#include "baseachievement.h"
#include "cs_achievement_constants.h"
#include "c_cs_team.h"
#include "c_cs_player.h"
#include "c_cs_playerresource.h"
#include "cs_gamerules.h"
#include "achievements_cs.h"
#include "cs_gamestats_shared.h"
#include "cs_client_gamestats.h"
// [dwenger] Necessary for stats display
#include "cs_achievements_and_stats_interface.h"
// [dwenger] Necessary for sorting achievements by award time
#include <vgui/ISystem.h>
#include "vgui_controls/Controls.h"
ConVar achievements_easymode( "achievement_easymode", "0", FCVAR_CLIENTDLL | FCVAR_DEVELOPMENTONLY,
"Enables all stat-based achievements to be earned at 10% of goals" );
// global achievement mgr for CS
CAchievementMgr g_AchievementMgrCS;
// [dwenger] Necessary for achievement / stats panel
CSAchievementsAndStatsInterface g_AchievementsAndStatsInterfaceCS;
CCSBaseAchievement::CCSBaseAchievement()
{
}
//-----------------------------------------------------------------------------
// Purpose: Determines the timestamp when the achievement is awarded
//-----------------------------------------------------------------------------
void CCSBaseAchievement::OnAchieved()
{
// __time32_t unlockTime;
// _time32(&unlockTime);
// SetUnlockTime(unlockTime);
}
//-----------------------------------------------------------------------------
// Purpose: Returns the time values when the achievement was awarded.
//-----------------------------------------------------------------------------
bool CCSBaseAchievement::GetAwardTime( int& year, int& month, int& day, int& hour, int& minute, int& second )
{
time_t t = GetUnlockTime();
if ( t != 0 )
{
struct tm structuredTime;
Plat_localtime(&t, &structuredTime);
year = structuredTime.tm_year + 1900;
month = structuredTime.tm_mon + 1; // 0..11
day = structuredTime.tm_mday;
hour = structuredTime.tm_hour;
minute = structuredTime.tm_min;
second = structuredTime.tm_sec;
return true;
}
return false;
}
void CCSBaseAchievement::GetSettings( KeyValues* pNodeOut )
{
BaseClass::GetSettings(pNodeOut);
pNodeOut->SetInt("unlockTime", GetUnlockTime());
}
void CCSBaseAchievement::ApplySettings( /* const */ KeyValues* pNodeIn )
{
BaseClass::ApplySettings(pNodeIn);
SetUnlockTime(pNodeIn->GetInt("unlockTime"));
}
/**
* Meta Achievement base class methods
*/
CAchievement_Meta::CAchievement_Meta() :
m_CallbackUserAchievement( this, &CAchievement_Meta::Steam_OnUserAchievementStored )
{
}
void CAchievement_Meta::Init()
{
SetFlags( ACH_SAVE_GLOBAL );
SetGoal( 1 );
}
void CAchievement_Meta::Steam_OnUserAchievementStored( UserAchievementStored_t *pUserAchievementStored )
{
if ( IsAchieved() )
return;
int iAchieved = 0;
FOR_EACH_VEC(m_requirements, i)
{
IAchievement* pAchievement = (IAchievement*)m_pAchievementMgr->GetAchievementByID(m_requirements[i]);
Assert ( pAchievement );
if ( pAchievement->IsAchieved() )
iAchieved++;
else
break;
}
if ( iAchieved == m_requirements.Count() )
{
AwardAchievement();
}
}
void CAchievement_Meta::AddRequirement( int nAchievementId )
{
m_requirements.AddToTail(nAchievementId);
}
#if 0
bool CheckWinNoEnemyCaps( IGameEvent *event, int iRole );
// Grace period that we allow a player to start after level init and still consider them to be participating for the full round. This is fairly generous
// because it can in some cases take a client several minutes to connect with respect to when the server considers the game underway
#define CS_FULL_ROUND_GRACE_PERIOD ( 4 * 60.0f )
bool IsLocalCSPlayerClass( int iClass );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCSBaseAchievementFullRound::Init()
{
m_iFlags |= ACH_FILTER_FULL_ROUND_ONLY;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCSBaseAchievementFullRound::ListenForEvents()
{
ListenForGameEvent( "teamplay_round_win" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCSBaseAchievementFullRound::FireGameEvent_Internal( IGameEvent *event )
{
if ( 0 == Q_strcmp( event->GetName(), "teamplay_round_win" ) )
{
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( pLocalPlayer )
{
// is the player currently on a game team?
int iTeam = pLocalPlayer->GetTeamNumber();
if ( iTeam >= FIRST_GAME_TEAM )
{
float flRoundTime = event->GetFloat( "round_time", 0 );
if ( flRoundTime > 0 )
{
Event_OnRoundComplete( flRoundTime, event );
}
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CCSBaseAchievementFullRound::PlayerWasInEntireRound( float flRoundTime )
{
float flTeamplayStartTime = m_pAchievementMgr->GetTeamplayStartTime();
if ( flTeamplayStartTime > 0 )
{
// has the player been present and on a game team since the start of this round (minus a grace period)?
if ( flTeamplayStartTime < ( gpGlobals->curtime - flRoundTime ) + CS_FULL_ROUND_GRACE_PERIOD )
return true;
}
return false;
}
#endif
//Base class for all achievements to kill x players with a given weapon
class CAchievement_StatGoal: public CCSBaseAchievement
{
public:
void SetStatId(CSStatType_t stat)
{
m_StatId = stat;
}
private:
virtual void Init()
{
SetFlags( ACH_SAVE_GLOBAL );
}
void OnPlayerStatsUpdate()
{
// when stats are updated by server, use most recent stat value
const StatsCollection_t& roundStats = g_CSClientGameStats.GetLifetimeStats();
int iOldCount = GetCount();
SetCount(roundStats[m_StatId]);
if ( GetCount() != iOldCount )
{
m_pAchievementMgr->SetDirty(true);
}
int iGoal = GetGoal();
if (!IsAchieved() && iGoal > 0 )
{
if (achievements_easymode.GetBool())
{
iGoal /= 10;
if ( iGoal == 0 )
iGoal = 1;
}
if ( GetCount() >= iGoal )
{
AwardAchievement();
}
}
}
CSStatType_t m_StatId;
};
#define DECLARE_ACHIEVEMENT_STATGOAL( achievementID, achievementName, iPointValue, iStatId, iGoal ) \
static CBaseAchievement *Create_##achievementID( void ) \
{ \
CAchievement_StatGoal *pAchievement = new CAchievement_StatGoal(); \
pAchievement->SetAchievementID( achievementID ); \
pAchievement->SetName( achievementName ); \
pAchievement->SetPointValue( iPointValue ); \
pAchievement->SetHideUntilAchieved( false ); \
pAchievement->SetStatId(iStatId); \
pAchievement->SetGoal( iGoal ); \
return pAchievement; \
}; \
static CBaseAchievementHelper g_##achievementID##_Helper( Create_##achievementID );
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsLow, "KILL_ENEMY_LOW", 10, CSSTAT_KILLS, 25); //25
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsMed, "KILL_ENEMY_MED", 10, CSSTAT_KILLS, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsHigh, "KILL_ENEMY_HIGH", 10, CSSTAT_KILLS, 10000); //10000
DECLARE_ACHIEVEMENT_STATGOAL(CSWinRoundsLow, "WIN_ROUNDS_LOW", 10, CSSTAT_ROUNDS_WON, 10); //10
DECLARE_ACHIEVEMENT_STATGOAL(CSWinRoundsMed, "WIN_ROUNDS_MED", 10, CSSTAT_ROUNDS_WON, 200); //200
DECLARE_ACHIEVEMENT_STATGOAL(CSWinRoundsHigh, "WIN_ROUNDS_HIGH", 10, CSSTAT_ROUNDS_WON, 5000); //5000
DECLARE_ACHIEVEMENT_STATGOAL(CSWinPistolRoundsLow, "WIN_PISTOLROUNDS_LOW", 10, CSSTAT_PISTOLROUNDS_WON, 5); //5
DECLARE_ACHIEVEMENT_STATGOAL(CSWinPistolRoundsMed, "WIN_PISTOLROUNDS_MED", 10, CSSTAT_PISTOLROUNDS_WON, 25); //25
DECLARE_ACHIEVEMENT_STATGOAL(CSWinPistolRoundsHigh, "WIN_PISTOLROUNDS_HIGH", 10, CSSTAT_PISTOLROUNDS_WON, 250); //250
DECLARE_ACHIEVEMENT_STATGOAL(CSMoneyEarnedLow, "EARN_MONEY_LOW", 10, CSSTAT_MONEY_EARNED, 125000); //125000
DECLARE_ACHIEVEMENT_STATGOAL(CSMoneyEarnedMed, "EARN_MONEY_MED", 10, CSSTAT_MONEY_EARNED, 2500000); //2500000
DECLARE_ACHIEVEMENT_STATGOAL(CSMoneyEarnedHigh, "EARN_MONEY_HIGH", 10, CSSTAT_MONEY_EARNED, 50000000); //50000000
DECLARE_ACHIEVEMENT_STATGOAL(CSGiveDamageLow, "GIVE_DAMAGE_LOW", 10, CSSTAT_DAMAGE, 2500); //2500
DECLARE_ACHIEVEMENT_STATGOAL(CSGiveDamageMed, "GIVE_DAMAGE_MED", 10, CSSTAT_DAMAGE, 50000); //50000
DECLARE_ACHIEVEMENT_STATGOAL(CSGiveDamageHigh, "GIVE_DAMAGE_HIGH", 10, CSSTAT_DAMAGE, 1000000); //1000000
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsDeagle, "KILL_ENEMY_DEAGLE", 5, CSSTAT_KILLS_DEAGLE, 200); //200
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsUSP, "KILL_ENEMY_USP", 5, CSSTAT_KILLS_USP, 200); //200
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsGlock, "KILL_ENEMY_GLOCK", 5, CSSTAT_KILLS_GLOCK, 200); //200
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsP228, "KILL_ENEMY_P228", 5, CSSTAT_KILLS_P228, 200); //200
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsElite, "KILL_ENEMY_ELITE", 5, CSSTAT_KILLS_ELITE, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsFiveSeven, "KILL_ENEMY_FIVESEVEN", 5, CSSTAT_KILLS_FIVESEVEN, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsAWP, "KILL_ENEMY_AWP", 5, CSSTAT_KILLS_AWP, 1000); //1000
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsAK47, "KILL_ENEMY_AK47", 5, CSSTAT_KILLS_AK47, 1000); //1000
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsM4A1, "KILL_ENEMY_M4A1", 5, CSSTAT_KILLS_M4A1, 1000); //1000
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsAUG, "KILL_ENEMY_AUG", 5, CSSTAT_KILLS_AUG, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsSG552, "KILL_ENEMY_SG552", 5, CSSTAT_KILLS_SG552, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsSG550, "KILL_ENEMY_SG550", 5, CSSTAT_KILLS_SG550, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsGALIL, "KILL_ENEMY_GALIL", 5, CSSTAT_KILLS_GALIL, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsFAMAS, "KILL_ENEMY_FAMAS", 5, CSSTAT_KILLS_FAMAS, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsScout, "KILL_ENEMY_SCOUT", 5, CSSTAT_KILLS_SCOUT, 1000); //1000
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsG3SG1, "KILL_ENEMY_G3SG1", 5, CSSTAT_KILLS_G3SG1, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsP90, "KILL_ENEMY_P90", 5, CSSTAT_KILLS_P90, 1000); //1000
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsMP5NAVY, "KILL_ENEMY_MP5NAVY", 5, CSSTAT_KILLS_MP5NAVY, 1000); //1000
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsTMP, "KILL_ENEMY_TMP", 5, CSSTAT_KILLS_TMP, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsMAC10, "KILL_ENEMY_MAC10", 5, CSSTAT_KILLS_MAC10, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsUMP45, "KILL_ENEMY_UMP45", 5, CSSTAT_KILLS_UMP45, 1000); //1000
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsM3, "KILL_ENEMY_M3", 5, CSSTAT_KILLS_M3, 200); //200
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsXM1014, "KILL_ENEMY_XM1014", 5, CSSTAT_KILLS_XM1014, 200); //200
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsM249, "KILL_ENEMY_M249", 5, CSSTAT_KILLS_M249, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsKnife, "KILL_ENEMY_KNIFE", 5, CSSTAT_KILLS_KNIFE, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSEnemyKillsHEGrenade, "KILL_ENEMY_HEGRENADE", 5, CSSTAT_KILLS_HEGRENADE, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSHeadshots, "HEADSHOTS", 5, CSSTAT_KILLS_HEADSHOT, 250); //250
DECLARE_ACHIEVEMENT_STATGOAL(CSKillsEnemyWeapon, "KILLS_ENEMY_WEAPON", 5, CSSTAT_KILLS_ENEMY_WEAPON, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSKillEnemyBlinded, "KILL_ENEMY_BLINDED", 5, CSSTAT_KILLS_ENEMY_BLINDED, 25); //25
DECLARE_ACHIEVEMENT_STATGOAL(CSDefuseBombsLow, "BOMB_DEFUSE_LOW", 5, CSSTAT_NUM_BOMBS_DEFUSED, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSPlantBombsLow, "BOMB_PLANT_LOW", 5, CSSTAT_NUM_BOMBS_PLANTED, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSRescueHostagesLow, "RESCUE_HOSTAGES_LOW", 5, CSSTAT_NUM_HOSTAGES_RESCUED, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSRescueHostagesMid, "RESCUE_HOSTAGES_MED", 5, CSSTAT_NUM_HOSTAGES_RESCUED, 500); //500
DECLARE_ACHIEVEMENT_STATGOAL(CSWinKnifeFightsLow, "WIN_KNIFE_FIGHTS_LOW", 5, CSSTAT_KILLS_KNIFE_FIGHT, 1); //1
DECLARE_ACHIEVEMENT_STATGOAL(CSWinKnifeFightsHigh, "WIN_KNIFE_FIGHTS_HIGH", 5, CSSTAT_KILLS_KNIFE_FIGHT, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSDecalSprays, "DECAL_SPRAYS", 5, CSSTAT_DECAL_SPRAYS, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSNightvisionDamage, "NIGHTVISION_DAMAGE", 5, CSSTAT_NIGHTVISION_DAMAGE, 5000); //5000
DECLARE_ACHIEVEMENT_STATGOAL(CSKillSnipers, "KILL_SNIPERS", 5, CSSTAT_KILLS_AGAINST_ZOOMED_SNIPER, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapCS_ASSAULT, "WIN_MAP_CS_ASSAULT", 5, CSSTAT_MAP_WINS_CS_ASSAULT, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapCS_COMPOUND, "WIN_MAP_CS_COMPOUND", 5, CSSTAT_MAP_WINS_CS_COMPOUND, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapCS_HAVANA, "WIN_MAP_CS_HAVANA", 5, CSSTAT_MAP_WINS_CS_HAVANA, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapCS_ITALY, "WIN_MAP_CS_ITALY", 5, CSSTAT_MAP_WINS_CS_ITALY, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapCS_MILITIA, "WIN_MAP_CS_MILITIA", 5, CSSTAT_MAP_WINS_CS_MILITIA, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapCS_OFFICE, "WIN_MAP_CS_OFFICE", 5, CSSTAT_MAP_WINS_CS_OFFICE, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_AZTEC, "WIN_MAP_DE_AZTEC", 5, CSSTAT_MAP_WINS_DE_AZTEC, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_CBBLE, "WIN_MAP_DE_CBBLE", 5, CSSTAT_MAP_WINS_DE_CBBLE, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_CHATEAU, "WIN_MAP_DE_CHATEAU", 5, CSSTAT_MAP_WINS_DE_CHATEAU, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_DUST2, "WIN_MAP_DE_DUST2", 5, CSSTAT_MAP_WINS_DE_DUST2, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_DUST, "WIN_MAP_DE_DUST", 5, CSSTAT_MAP_WINS_DE_DUST, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_INFERNO, "WIN_MAP_DE_INFERNO", 5, CSSTAT_MAP_WINS_DE_INFERNO, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_NUKE, "WIN_MAP_DE_NUKE", 5, CSSTAT_MAP_WINS_DE_NUKE, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_PIRANESI, "WIN_MAP_DE_PIRANESI", 5, CSSTAT_MAP_WINS_DE_PIRANESI, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_PORT, "WIN_MAP_DE_PORT", 5, CSSTAT_MAP_WINS_DE_PORT, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_PRODIGY, "WIN_MAP_DE_PRODIGY", 5, CSSTAT_MAP_WINS_DE_PRODIGY, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_TIDES, "WIN_MAP_DE_TIDES", 5, CSSTAT_MAP_WINS_DE_TIDES, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSWinMapDE_TRAIN, "WIN_MAP_DE_TRAIN", 5, CSSTAT_MAP_WINS_DE_TRAIN, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSDonateWeapons, "DONATE_WEAPONS", 5, CSSTAT_WEAPONS_DONATED, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSDominationsLow, "DOMINATIONS_LOW", 5, CSSTAT_DOMINATIONS, 1); //1
DECLARE_ACHIEVEMENT_STATGOAL(CSDominationsHigh, "DOMINATIONS_HIGH", 5, CSSTAT_DOMINATIONS, 10); //10
DECLARE_ACHIEVEMENT_STATGOAL(CSDominationOverkillsLow, "DOMINATION_OVERKILLS_LOW", 5, CSSTAT_DOMINATION_OVERKILLS, 1); //1
DECLARE_ACHIEVEMENT_STATGOAL(CSDominationOverkillsHigh, "DOMINATION_OVERKILLS_HIGH",5, CSSTAT_DOMINATION_OVERKILLS, 100); //100
DECLARE_ACHIEVEMENT_STATGOAL(CSRevengesLow, "REVENGES_LOW", 5, CSSTAT_REVENGES, 1); //1
DECLARE_ACHIEVEMENT_STATGOAL(CSRevengesHigh, "REVENGES_HIGH", 5, CSSTAT_REVENGES, 20); //20
//-----------------------------------------------------------------------------
// Purpose: Generic server awarded achievement
//-----------------------------------------------------------------------------
class CAchievementCS_ServerAwarded : public CCSBaseAchievement
{
virtual void Init()
{
SetGoal(1);
SetFlags( ACH_SAVE_GLOBAL );
}
// server fires an event for this achievement, no other code within achievement necessary
};
#define DECLARE_ACHIEVEMENT_SERVERAWARDED(achievementID, achievementName, iPointValue) \
static CBaseAchievement *Create_##achievementID( void ) \
{ \
CAchievementCS_ServerAwarded *pAchievement = new CAchievementCS_ServerAwarded( ); \
pAchievement->SetAchievementID( achievementID ); \
pAchievement->SetName( achievementName ); \
pAchievement->SetPointValue( iPointValue ); \
return pAchievement; \
}; \
static CBaseAchievementHelper g_##achievementID##_Helper( Create_##achievementID );
// server triggered achievements
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSBombDefuseCloseCall, "BOMB_DEFUSE_CLOSE_CALL", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSDefuseAndNeededKit, "BOMB_DEFUSE_NEEDED_KIT", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKilledDefuser, "KILL_BOMB_DEFUSER", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSWinBombPlant, "WIN_BOMB_PLANT", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSWinBombDefuse, "WIN_BOMB_DEFUSE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSPlantBombWithin25Seconds, "BOMB_PLANT_IN_25_SECONDS", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSRescueAllHostagesInARound, "RESCUE_ALL_HOSTAGES", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillEnemyWithFormerGun, "KILL_WITH_OWN_GUN", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillingSpree, "KILLING_SPREE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillTwoWithOneShot, "KILL_TWO_WITH_ONE_SHOT", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillEnemyReloading, "KILL_ENEMY_RELOADING", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillsWithMultipleGuns, "KILLS_WITH_MULTIPLE_GUNS", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSPosthumousGrenadeKill, "DEAD_GRENADE_KILL", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillEnemyTeam, "KILL_ENEMY_TEAM", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSLastPlayerAlive, "LAST_PLAYER_ALIVE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillEnemyLastBullet, "KILL_ENEMY_LAST_BULLET", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillingSpreeEnder, "KILLING_SPREE_ENDER", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillEnemiesWhileBlind, "KILL_ENEMIES_WHILE_BLIND", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillEnemiesWhileBlindHard, "KILL_ENEMIES_WHILE_BLIND_HARD", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSDamageNoKill, "DAMAGE_NO_KILL", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillLowDamage, "KILL_LOW_DAMAGE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKilledRescuer, "KILL_HOSTAGE_RESCUER", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSSurviveGrenade, "SURVIVE_GRENADE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKilledDefuserWithGrenade, "KILLED_DEFUSER_WITH_GRENADE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSSurvivedHeadshotDueToHelmet, "SURVIVED_HEADSHOT_DUE_TO_HELMET", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillSniperWithSniper, "KILL_SNIPER_WITH_SNIPER", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillSniperWithKnife, "KILL_SNIPER_WITH_KNIFE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSHipShot, "HIP_SHOT", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillWhenAtLowHealth, "KILL_WHEN_AT_LOW_HEALTH", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSGrenadeMultikill, "GRENADE_MULTIKILL", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSBombMultikill, "BOMB_MULTIKILL", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSPistolRoundKnifeKill, "PISTOL_ROUND_KNIFE_KILL", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSFastRoundWin, "FAST_ROUND_WIN", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSSurviveManyAttacks, "SURVIVE_MANY_ATTACKS", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSGooseChase, "GOOSE_CHASE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSWinBombPlantAfterRecovery, "WIN_BOMB_PLANT_AFTER_RECOVERY", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSLosslessExtermination, "LOSSLESS_EXTERMINATION", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSFlawlessVictory, "FLAWLESS_VICTORY", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSWinDualDuel, "WIN_DUAL_DUEL", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSFastHostageRescue, "FAST_HOSTAGE_RESCUE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSBreakWindows, "BREAK_WINDOWS", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSBreakProps, "BREAK_PROPS", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSUnstoppableForce, "UNSTOPPABLE_FORCE", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSImmovableObject, "IMMOVABLE_OBJECT", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSHeadshotsInRound, "HEADSHOTS_IN_ROUND", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillWhileInAir, "KILL_WHILE_IN_AIR", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillEnemyInAir, "KILL_ENEMY_IN_AIR", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillerAndEnemyInAir, "KILLER_AND_ENEMY_IN_AIR", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSSilentWin, "SILENT_WIN", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSBloodlessVictory, "BLOODLESS_VICTORY", 5);
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSWinRoundsWithoutBuying, "WIN_ROUNDS_WITHOUT_BUYING", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSDefuseDefense, "DEFUSE_DEFENSE", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSKillBombPickup, "KILL_BOMB_PICKUP", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSSameUniform, "SAME_UNIFORM", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSConcurrentDominations, "CONCURRENT_DOMINATIONS", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSDominationOverkillsMatch, "DOMINATION_OVERKILLS_MATCH", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSExtendedDomination, "EXTENDED_DOMINATION", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSCauseFriendlyFireWithFlashbang, "CAUSE_FRIENDLY_FIRE_WITH_FLASHBANG", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSWinClanMatch, "WIN_CLAN_MATCH", 5)
DECLARE_ACHIEVEMENT_SERVERAWARDED(CSSnipeTwoFromSameSpot, "SNIPE_TWO_FROM_SAME_SPOT", 5 )
//-----------------------------------------------------------------------------
// Meta Achievements
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Get all the pistol achievements
//-----------------------------------------------------------------------------
class CAchievementCS_PistolMaster : public CAchievement_Meta
{
DECLARE_CLASS( CAchievementCS_PistolMaster, CAchievement_Meta );
virtual void Init()
{
BaseClass::Init();
AddRequirement(CSEnemyKillsDeagle);
AddRequirement(CSEnemyKillsUSP);
AddRequirement(CSEnemyKillsGlock);
AddRequirement(CSEnemyKillsP228);
AddRequirement(CSEnemyKillsElite);
AddRequirement(CSEnemyKillsFiveSeven);
}
};
DECLARE_ACHIEVEMENT(CAchievementCS_PistolMaster, CSMetaPistol, "META_PISTOL", 10);
//-----------------------------------------------------------------------------
// Purpose: Get all the rifle achievements
//-----------------------------------------------------------------------------
class CAchievementCS_RifleMaster : public CAchievement_Meta
{
DECLARE_CLASS( CAchievementCS_RifleMaster, CAchievement_Meta );
virtual void Init()
{
BaseClass::Init();
AddRequirement(CSEnemyKillsAWP);
AddRequirement(CSEnemyKillsAK47);
AddRequirement(CSEnemyKillsM4A1);
AddRequirement(CSEnemyKillsAUG);
AddRequirement(CSEnemyKillsSG552);
AddRequirement(CSEnemyKillsSG550);
AddRequirement(CSEnemyKillsGALIL);
AddRequirement(CSEnemyKillsFAMAS);
AddRequirement(CSEnemyKillsScout);
AddRequirement(CSEnemyKillsG3SG1);
}
};
DECLARE_ACHIEVEMENT(CAchievementCS_RifleMaster, CSMetaRifle, "META_RIFLE", 10);
//-----------------------------------------------------------------------------
// Purpose: Get all the SMG achievements
//-----------------------------------------------------------------------------
class CAchievementCS_SubMachineGunMaster : public CAchievement_Meta
{
DECLARE_CLASS( CAchievementCS_SubMachineGunMaster, CAchievement_Meta );
virtual void Init()
{
BaseClass::Init();
AddRequirement(CSEnemyKillsP90);
AddRequirement(CSEnemyKillsMP5NAVY);
AddRequirement(CSEnemyKillsTMP);
AddRequirement(CSEnemyKillsMAC10);
AddRequirement(CSEnemyKillsUMP45);
}
};
DECLARE_ACHIEVEMENT(CAchievementCS_SubMachineGunMaster, CSMetaSMG, "META_SMG", 10);
//-----------------------------------------------------------------------------
// Purpose: Get all the Shotgun achievements
//-----------------------------------------------------------------------------
class CAchievementCS_ShotgunMaster : public CAchievement_Meta
{
DECLARE_CLASS( CAchievementCS_ShotgunMaster, CAchievement_Meta );
virtual void Init()
{
BaseClass::Init();
AddRequirement(CSEnemyKillsM3);
AddRequirement(CSEnemyKillsXM1014);
}
};
DECLARE_ACHIEVEMENT(CAchievementCS_ShotgunMaster, CSMetaShotgun, "META_SHOTGUN", 10);
//-----------------------------------------------------------------------------
// Purpose: Get every weapon achievement
//-----------------------------------------------------------------------------
class CAchievementCS_WeaponMaster : public CAchievement_Meta
{
DECLARE_CLASS( CAchievementCS_WeaponMaster, CAchievement_Meta );
virtual void Init()
{
BaseClass::Init();
AddRequirement(CSMetaPistol);
AddRequirement(CSMetaRifle);
AddRequirement(CSMetaSMG);
AddRequirement(CSMetaShotgun);
AddRequirement(CSEnemyKillsM249);
AddRequirement(CSEnemyKillsKnife);
AddRequirement(CSEnemyKillsHEGrenade);
}
};
DECLARE_ACHIEVEMENT(CAchievementCS_WeaponMaster, CSMetaWeaponMaster, "META_WEAPONMASTER", 50);
class CAchievementCS_KillWithAllWeapons : public CCSBaseAchievement
{
void Init()
{
SetFlags( ACH_SAVE_GLOBAL );
SetGoal( 1 );
}
void OnPlayerStatsUpdate()
{
const StatsCollection_t& roundStats = g_CSClientGameStats.GetLifetimeStats();
//Loop through all weapons we care about and make sure we got a kill with each.
for (int i = 0; WeaponName_StatId_Table[i].killStatId != CSSTAT_UNDEFINED; ++i)
{
CSStatType_t statId = WeaponName_StatId_Table[i].killStatId;
if ( roundStats[statId] == 0)
{
return;
}
}
//If we haven't bailed yet, award the achievement.
IncrementCount();
}
};
DECLARE_ACHIEVEMENT( CAchievementCS_KillWithAllWeapons, CSKillWithEveryWeapon, "KILL_WITH_EVERY_WEAPON", 5 );
class CAchievementCS_FriendsSameUniform : public CCSBaseAchievement
{
void Init()
{
SetFlags(ACH_SAVE_GLOBAL);
SetGoal(1);
}
void ListenForEvents()
{
ListenForGameEvent( "round_start" );
}
void FireGameEvent_Internal( IGameEvent *event )
{
if ( Q_strcmp( event->GetName(), "round_start" ) == 0 )
{
int localPlayerIndex = GetLocalPlayerIndex();
C_CSPlayer* pLocalPlayer = ToCSPlayer(UTIL_PlayerByIndex(localPlayerIndex));
// Initialize all to 1, since the local player doesn't get counted as we loop.
int numPlayersOnTeam = 1;
int numFriendsOnTeam = 1;
int numMatchingFriendsOnTeam = 1;
if (pLocalPlayer)
{
int localPlayerClass = pLocalPlayer->PlayerClass();
int localPlayerTeam = pLocalPlayer->GetTeamNumber();
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
if ( i != localPlayerIndex)
{
CCSPlayer *pPlayer = (CCSPlayer*) UTIL_PlayerByIndex( i );
if (pPlayer)
{
if (pPlayer->GetTeamNumber() == localPlayerTeam)
{
++numPlayersOnTeam;
if (pLocalPlayer->HasPlayerAsFriend(pPlayer) )
{
++numFriendsOnTeam;
if ( pPlayer->PlayerClass() == localPlayerClass )
++numMatchingFriendsOnTeam;
}
}
}
}
}
if (numMatchingFriendsOnTeam >= AchievementConsts::FriendsSameUniform_MinPlayers )
{
AwardAchievement();
}
}
}
}
};
DECLARE_ACHIEVEMENT( CAchievementCS_FriendsSameUniform, CSFriendsSameUniform, "FRIENDS_SAME_UNIFORM", 5 );
class CAchievementCS_AvengeFriend : public CCSBaseAchievement
{
void Init()
{
SetFlags(ACH_SAVE_GLOBAL);
SetGoal(1);
}
void ListenForEvents()
{
ListenForGameEvent( "player_avenged_teammate" );
}
void FireGameEvent_Internal( IGameEvent *event )
{
if ( Q_strcmp( event->GetName(), "player_avenged_teammate" ) == 0 )
{
int localPlayerIndex = GetLocalPlayerIndex();
C_CSPlayer* pLocalPlayer = ToCSPlayer(UTIL_PlayerByIndex(localPlayerIndex));
//for debugging
//int eventId = event->GetInt( "avenger_id" );
//int localUserId = pLocalPlayer->GetUserID();
if (pLocalPlayer && pLocalPlayer->GetUserID() == event->GetInt( "avenger_id" ))
{
int avengedPlayerIndex = engine->GetPlayerForUserID( event->GetInt( "avenged_player_id" ) );
if ( avengedPlayerIndex > 0 )
{
C_CSPlayer* pAvengedPlayer = ToCSPlayer(UTIL_PlayerByIndex(avengedPlayerIndex));
if (pAvengedPlayer && pLocalPlayer->HasPlayerAsFriend(pAvengedPlayer))
{
AwardAchievement();
}
}
}
}
}
};
DECLARE_ACHIEVEMENT( CAchievementCS_AvengeFriend, CSAvengeFriend, "AVENGE_FRIEND", 5 );
class CAchievementCS_CollectHolidayGifts : public CCSBaseAchievement
{
void Init()
{
SetFlags( ACH_SAVE_GLOBAL );
SetGoal( 3 );
SetStoreProgressInSteam( true );
}
virtual void ListenForEvents()
{
ListenForGameEvent( "christmas_gift_grab" );
}
void FireGameEvent_Internal( IGameEvent *event )
{
if ( !UTIL_IsHolidayActive( 3 /*kHoliday_Christmas*/ ) )
return;
if ( Q_strcmp( event->GetName(), "christmas_gift_grab" ) == 0 )
{
int iPlayer = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
CBaseEntity *pPlayer = UTIL_PlayerByIndex( iPlayer );
if ( pPlayer && pPlayer == C_CSPlayer::GetLocalCSPlayer() )
{
IncrementCount();
}
}
}
};
DECLARE_ACHIEVEMENT( CAchievementCS_CollectHolidayGifts, CSCollectHolidayGifts, "COLLECT_GIFTS", 5 );
#endif // CLIENT_DLL
-75
View File
@@ -1,75 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#ifdef CLIENT_DLL
bool CheckWinNoEnemyCaps( IGameEvent *event, int iRole );
bool IsLocalCSPlayerClass( int iClass );
bool GameRulesAllowsAchievements( void );
//----------------------------------------------------------------------------------------------------------------
// Base class for all CS achievements
class CCSBaseAchievement : public CBaseAchievement
{
DECLARE_CLASS( CCSBaseAchievement, CBaseAchievement );
public:
CCSBaseAchievement();
virtual void GetSettings( KeyValues* pNodeOut ); // serialize
virtual void ApplySettings( /* const */ KeyValues* pNodeIn ); // unserialize
// [dwenger] Necessary for sorting achievements by award time
virtual void OnAchieved();
bool GetAwardTime( int& year, int& month, int& day, int& hour, int& minute, int& second );
int64 GetSortKey() const { return GetUnlockTime(); }
};
//----------------------------------------------------------------------------------------------------------------
// Helper class for achievements that check that the player was playing on a game team for the full round
class CCSBaseAchievementFullRound : public CCSBaseAchievement
{
DECLARE_CLASS( CCSBaseAchievementFullRound, CCSBaseAchievement );
public:
virtual void Init() ;
virtual void ListenForEvents();
void FireGameEvent_Internal( IGameEvent *event );
bool PlayerWasInEntireRound( float flRoundTime );
virtual void Event_OnRoundComplete( float flRoundTime, IGameEvent *event ) = 0 ;
};
//----------------------------------------------------------------------------------------------------------------
// Helper class for achievements based on other achievements
class CAchievement_Meta : public CCSBaseAchievement
{
DECLARE_CLASS( CAchievement_Meta, CCSBaseAchievement );
public:
CAchievement_Meta();
virtual void Init();
#if !defined(NO_STEAM)
STEAM_CALLBACK( CAchievement_Meta, Steam_OnUserAchievementStored, UserAchievementStored_t, m_CallbackUserAchievement );
#endif
protected:
void AddRequirement( int nAchievementId );
private:
CUtlVector<int> m_requirements;
};
extern CAchievementMgr g_AchievementMgrCS; // global achievement mgr for CS
#endif // CLIENT_DLL
@@ -1,346 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "basecsgrenade_projectile.h"
float GetCurrentGravity( void );
#ifdef CLIENT_DLL
#include "c_cs_player.h"
#else
#include "bot_manager.h"
#include "cs_player.h"
#include "soundent.h"
#include "te_effect_dispatch.h"
#include "KeyValues.h"
BEGIN_DATADESC( CBaseCSGrenadeProjectile )
DEFINE_THINKFUNC( DangerSoundThink ),
END_DATADESC()
#endif
IMPLEMENT_NETWORKCLASS_ALIASED( BaseCSGrenadeProjectile, DT_BaseCSGrenadeProjectile )
BEGIN_NETWORK_TABLE( CBaseCSGrenadeProjectile, DT_BaseCSGrenadeProjectile )
#ifdef CLIENT_DLL
RecvPropVector( RECVINFO( m_vInitialVelocity ) )
#else
SendPropVector( SENDINFO( m_vInitialVelocity ),
20, // nbits
0, // flags
-3000, // low value
3000 // high value
)
#endif
END_NETWORK_TABLE()
#ifdef CLIENT_DLL
void CBaseCSGrenadeProjectile::PostDataUpdate( DataUpdateType_t type )
{
BaseClass::PostDataUpdate( type );
if ( type == DATA_UPDATE_CREATED )
{
// Now stick our initial velocity into the interpolation history
CInterpolatedVar< Vector > &interpolator = GetOriginInterpolator();
interpolator.ClearHistory();
float changeTime = GetLastChangeTime( LATCH_SIMULATION_VAR );
// Add a sample 1 second back.
Vector vCurOrigin = GetLocalOrigin() - m_vInitialVelocity;
interpolator.AddToHead( changeTime - 1.0, &vCurOrigin, false );
// Add the current sample.
vCurOrigin = GetLocalOrigin();
interpolator.AddToHead( changeTime, &vCurOrigin, false );
}
}
int CBaseCSGrenadeProjectile::DrawModel( int flags )
{
// During the first half-second of our life, don't draw ourselves if he's
// still playing his throw animation.
// (better yet, we could draw ourselves in his hand).
if ( GetThrower() != C_BasePlayer::GetLocalPlayer() )
{
if ( gpGlobals->curtime - m_flSpawnTime < 0.5 )
{
C_CSPlayer *pPlayer = dynamic_cast<C_CSPlayer*>( GetThrower() );
if ( pPlayer && pPlayer->m_PlayerAnimState->IsThrowingGrenade() )
{
return 0;
}
}
}
return BaseClass::DrawModel( flags );
}
void CBaseCSGrenadeProjectile::Spawn()
{
m_flSpawnTime = gpGlobals->curtime;
BaseClass::Spawn();
}
#else
void CBaseCSGrenadeProjectile::PostConstructor( const char *className )
{
BaseClass::PostConstructor( className );
TheBots->AddGrenade( this );
}
CBaseCSGrenadeProjectile::~CBaseCSGrenadeProjectile()
{
TheBots->RemoveGrenade( this );
}
void CBaseCSGrenadeProjectile::Spawn( void )
{
BaseClass::Spawn();
SetSolidFlags( FSOLID_NOT_STANDABLE );
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM );
SetSolid( SOLID_BBOX ); // So it will collide with physics props!
// smaller, cube bounding box so we rest on the ground
SetSize( Vector ( -2, -2, -2 ), Vector ( 2, 2, 2 ) );
}
void CBaseCSGrenadeProjectile::DangerSoundThink( void )
{
if (!IsInWorld())
{
Remove( );
return;
}
if( gpGlobals->curtime > m_flDetonateTime )
{
Detonate();
return;
}
CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, GetAbsVelocity().Length( ), 0.2 );
SetNextThink( gpGlobals->curtime + 0.2 );
if (GetWaterLevel() != 0)
{
SetAbsVelocity( GetAbsVelocity() * 0.5 );
}
}
//Sets the time at which the grenade will explode
void CBaseCSGrenadeProjectile::SetDetonateTimerLength( float timer )
{
m_flDetonateTime = gpGlobals->curtime + timer;
}
void CBaseCSGrenadeProjectile::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity )
{
//Assume all surfaces have the same elasticity
float flSurfaceElasticity = 1.0;
//Don't bounce off of players with perfect elasticity
if( trace.m_pEnt && trace.m_pEnt->IsPlayer() )
{
flSurfaceElasticity = 0.3;
}
// if its breakable glass and we kill it, don't bounce.
// give some damage to the glass, and if it breaks, pass
// through it.
bool breakthrough = false;
if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable" ) )
{
breakthrough = true;
}
if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable_surf" ) )
{
breakthrough = true;
}
if (breakthrough)
{
CTakeDamageInfo info( this, this, 10, DMG_CLUB );
trace.m_pEnt->DispatchTraceAttack( info, GetAbsVelocity(), &trace );
ApplyMultiDamage();
if( trace.m_pEnt->m_iHealth <= 0 )
{
// slow our flight a little bit
Vector vel = GetAbsVelocity();
vel *= 0.4;
SetAbsVelocity( vel );
return;
}
}
float flTotalElasticity = GetElasticity() * flSurfaceElasticity;
flTotalElasticity = clamp( flTotalElasticity, 0.0f, 0.9f );
// NOTE: A backoff of 2.0f is a reflection
Vector vecAbsVelocity;
PhysicsClipVelocity( GetAbsVelocity(), trace.plane.normal, vecAbsVelocity, 2.0f );
vecAbsVelocity *= flTotalElasticity;
// Get the total velocity (player + conveyors, etc.)
VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity );
float flSpeedSqr = DotProduct( vecVelocity, vecVelocity );
// Stop if on ground.
if ( trace.plane.normal.z > 0.7f ) // Floor
{
// Verify that we have an entity.
CBaseEntity *pEntity = trace.m_pEnt;
Assert( pEntity );
SetAbsVelocity( vecAbsVelocity );
if ( flSpeedSqr < ( 30 * 30 ) )
{
if ( pEntity->IsStandable() )
{
SetGroundEntity( pEntity );
}
// Reset velocities.
SetAbsVelocity( vec3_origin );
SetLocalAngularVelocity( vec3_angle );
//align to the ground so we're not standing on end
QAngle angle;
VectorAngles( trace.plane.normal, angle );
// rotate randomly in yaw
angle[1] = random->RandomFloat( 0, 360 );
// TODO: rotate around trace.plane.normal
SetAbsAngles( angle );
}
else
{
Vector vecDelta = GetBaseVelocity() - vecAbsVelocity;
Vector vecBaseDir = GetBaseVelocity();
VectorNormalize( vecBaseDir );
float flScale = vecDelta.Dot( vecBaseDir );
VectorScale( vecAbsVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, vecVelocity );
VectorMA( vecVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, GetBaseVelocity() * flScale, vecVelocity );
PhysicsPushEntity( vecVelocity, &trace );
}
}
else
{
// If we get *too* slow, we'll stick without ever coming to rest because
// we'll get pushed down by gravity faster than we can escape from the wall.
if ( flSpeedSqr < ( 30 * 30 ) )
{
// Reset velocities.
SetAbsVelocity( vec3_origin );
SetLocalAngularVelocity( vec3_angle );
}
else
{
SetAbsVelocity( vecAbsVelocity );
}
}
BounceSound();
// tell the bots a grenade has bounced
CCSPlayer *player = ToCSPlayer(GetThrower());
if ( player )
{
IGameEvent * event = gameeventmanager->CreateEvent( "grenade_bounce" );
if ( event )
{
event->SetInt( "userid", player->GetUserID() );
event->SetFloat( "x", GetAbsOrigin().x );
event->SetFloat( "y", GetAbsOrigin().y );
event->SetFloat( "z", GetAbsOrigin().z );
gameeventmanager->FireEvent( event );
}
}
}
void CBaseCSGrenadeProjectile::SetupInitialTransmittedGrenadeVelocity( const Vector &velocity )
{
m_vInitialVelocity = velocity;
}
#define MAX_WATER_SURFACE_DISTANCE 512
void CBaseCSGrenadeProjectile::Splash()
{
Vector centerPoint = GetAbsOrigin();
Vector normal( 0, 0, 1 );
// Find our water surface by tracing up till we're out of the water
trace_t tr;
Vector vecTrace( 0, 0, MAX_WATER_SURFACE_DISTANCE );
UTIL_TraceLine( centerPoint, centerPoint + vecTrace, MASK_WATER, NULL, COLLISION_GROUP_NONE, &tr );
// If we didn't start in water, we're above it
if ( tr.startsolid == false )
{
// Look downward to find the surface
vecTrace.Init( 0, 0, -MAX_WATER_SURFACE_DISTANCE );
UTIL_TraceLine( centerPoint, centerPoint + vecTrace, MASK_WATER, NULL, COLLISION_GROUP_NONE, &tr );
// If we hit it, setup the explosion
if ( tr.fraction < 1.0f )
{
centerPoint = tr.endpos;
}
else
{
//NOTENOTE: We somehow got into a splash without being near water?
Assert( 0 );
}
}
else if ( tr.fractionleftsolid )
{
// Otherwise we came out of the water at this point
centerPoint = centerPoint + (vecTrace * tr.fractionleftsolid);
}
else
{
// Use default values, we're really deep
}
CEffectData data;
data.m_vOrigin = centerPoint;
data.m_vNormal = normal;
data.m_flScale = random->RandomFloat( 1.0f, 2.0f );
if ( GetWaterType() & CONTENTS_SLIME )
{
data.m_fFlags |= FX_WATER_IN_SLIME;
}
DispatchEffect( "gunshotsplash", data );
}
#endif // !CLIENT_DLL
@@ -1,88 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef BASECSGRENADE_PROJECTILE_H
#define BASECSGRENADE_PROJECTILE_H
#ifdef _WIN32
#pragma once
#endif
#include "basegrenade_shared.h"
#ifdef CLIENT_DLL
#define CBaseCSGrenadeProjectile C_BaseCSGrenadeProjectile
#else
class CCSWeaponInfo;
#endif
class CBaseCSGrenadeProjectile : public CBaseGrenade
{
public:
DECLARE_CLASS( CBaseCSGrenadeProjectile, CBaseGrenade );
DECLARE_NETWORKCLASS();
virtual void Spawn();
public:
// This gets sent to the client and placed in the client's interpolation history
// so the projectile starts out moving right off the bat.
CNetworkVector( m_vInitialVelocity );
#ifdef CLIENT_DLL
CBaseCSGrenadeProjectile() {}
CBaseCSGrenadeProjectile( const CBaseCSGrenadeProjectile& ) {}
virtual int DrawModel( int flags );
virtual void PostDataUpdate( DataUpdateType_t type );
float m_flSpawnTime;
#else
DECLARE_DATADESC();
virtual void PostConstructor( const char *className );
virtual ~CBaseCSGrenadeProjectile();
//Constants for all CS Grenades
static inline float GetGrenadeGravity() { return 0.4f; }
static inline const float GetGrenadeFriction() { return 0.2f; }
static inline const float GetGrenadeElasticity() { return 0.45f; }
//Think function to emit danger sounds for the AI
void DangerSoundThink( void );
virtual float GetShakeAmplitude( void ) { return 0.0f; }
virtual void Splash();
// Specify what velocity we want the grenade to have on the client immediately.
// Without this, the entity wouldn't have an interpolation history initially, so it would
// sit still until it had gotten a few updates from the server.
void SetupInitialTransmittedGrenadeVelocity( const Vector &velocity );
// [jpaquin] give grenade projectiles a link back to the type
// of weapon they are
CCSWeaponInfo *m_pWeaponInfo;
protected:
//Set the time to detonate ( now + timer )
void SetDetonateTimerLength( float timer );
private:
//Custom collision to allow for constant elasticity on hit surfaces
virtual void ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity );
float m_flDetonateTime;
#endif
};
#endif // BASECSGRENADE_PROJECTILE_H
-109
View File
@@ -1,109 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Author: Michael S. Booth (mike@turtlerockstudios.com), Leon Hartwig, 2003
#include "cbase.h"
#include "basegrenade_shared.h"
#include "bot.h"
#include "bot_util.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
/// @todo Remove this nasty hack - CreateFakeClient() calls CBot::Spawn, which needs the profile and team
const BotProfile *g_botInitProfile = NULL;
int g_botInitTeam = 0;
//
// NOTE: Because CBot had to be templatized, the code was moved into bot.h
//
//--------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------
ActiveGrenade::ActiveGrenade( CBaseGrenade *grenadeEntity )
{
m_entity = grenadeEntity;
m_detonationPosition = grenadeEntity->GetAbsOrigin();
m_dieTimestamp = 0.0f;
m_radius = HEGrenadeRadius;
m_isSmoke = FStrEq( grenadeEntity->GetClassname(), "smokegrenade_projectile" );
if ( m_isSmoke )
{
m_radius = SmokeGrenadeRadius;
}
m_isFlashbang = FStrEq( grenadeEntity->GetClassname(), "flashbang_projectile" );
if ( m_isFlashbang )
{
m_radius = FlashbangGrenadeRadius;
}
}
//--------------------------------------------------------------------------------------------------------------
/**
* Called when the grenade in the world goes away
*/
void ActiveGrenade::OnEntityGone( void )
{
if (m_isSmoke)
{
// smoke lingers after grenade is gone
const float smokeLingerTime = 4.0f;
m_dieTimestamp = gpGlobals->curtime + smokeLingerTime;
}
m_entity = NULL;
}
//--------------------------------------------------------------------------------------------------------------
void ActiveGrenade::Update( void )
{
if (m_entity != NULL)
{
m_detonationPosition = m_entity->GetAbsOrigin();
}
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if this grenade is valid
*/
bool ActiveGrenade::IsValid( void ) const
{
if ( m_isSmoke )
{
if ( m_entity == NULL && gpGlobals->curtime > m_dieTimestamp )
{
return false;
}
}
else
{
if ( m_entity == NULL )
{
return false;
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------
const Vector &ActiveGrenade::GetPosition( void ) const
{
// smoke grenades can vanish before the smoke itself does - refer to the detonation position
if (m_entity == NULL)
return GetDetonationPosition();
return m_entity->GetAbsOrigin();
}
File diff suppressed because it is too large Load Diff
-40
View File
@@ -1,40 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Author: Matthew D. Campbell (matt@turtlerockstudios.com), 2003
#ifndef BOT_CONSTANTS_H
#define BOT_CONSTANTS_H
/// version number is MAJOR.MINOR
#define BOT_VERSION_MAJOR 1
#define BOT_VERSION_MINOR 50
//--------------------------------------------------------------------------------------------------------
/**
* Difficulty levels
*/
enum BotDifficultyType
{
BOT_EASY = 0,
BOT_NORMAL = 1,
BOT_HARD = 2,
BOT_EXPERT = 3,
NUM_DIFFICULTY_LEVELS
};
#ifdef DEFINE_DIFFICULTY_NAMES
const char *BotDifficultyName[] =
{
"EASY", "NORMAL", "HARD", "EXPERT", NULL
};
#else
extern const char *BotDifficultyName[];
#endif
#endif // BOT_CONSTANTS_H
-490
View File
@@ -1,490 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// bot_hide.cpp
// Mechanisms for using Hiding Spots in the Navigation Mesh
// Author: Michael Booth, 2003-2004
#include "cbase.h"
#include "bot.h"
#include "cs_nav_pathfind.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//--------------------------------------------------------------------------------------------------------------
/**
* If a player is at the given spot, return true
*/
bool IsSpotOccupied( CBaseEntity *me, const Vector &pos )
{
const float closeRange = 75.0f; // 50
// is there a player in this spot
float range;
CBasePlayer *player = UTIL_GetClosestPlayer( pos, &range );
if (player != me)
{
if (player && range < closeRange)
return true;
}
// is there is a hostage in this spot
// BOTPORT: Implement hostage manager
/*
if (g_pHostages)
{
CHostage *hostage = g_pHostages->GetClosestHostage( *pos, &range );
if (hostage && hostage != me && range < closeRange)
return true;
}
*/
return false;
}
//--------------------------------------------------------------------------------------------------------------
class CollectHidingSpotsFunctor
{
public:
CollectHidingSpotsFunctor( CBaseEntity *me, const Vector &origin, float range, int flags, Place place = UNDEFINED_PLACE ) : m_origin( origin )
{
m_me = me;
m_count = 0;
m_range = range;
m_flags = (unsigned char)flags;
m_place = place;
m_totalWeight = 0;
}
enum { MAX_SPOTS = 256 };
bool operator() ( CNavArea *area )
{
// if a place is specified, only consider hiding spots from areas in that place
if (m_place != UNDEFINED_PLACE && area->GetPlace() != m_place)
return true;
// collect all the hiding spots in this area
const HidingSpotVector *pSpots = area->GetHidingSpots();
FOR_EACH_VEC( (*pSpots), it )
{
const HidingSpot *spot = (*pSpots)[ it ];
// if we've filled up, stop searching
if (m_count == MAX_SPOTS)
{
return false;
}
// make sure hiding spot is in range
if (m_range > 0.0f)
{
if ((spot->GetPosition() - m_origin).IsLengthGreaterThan( m_range ))
{
continue;
}
}
// if a Player is using this hiding spot, don't consider it
if (IsSpotOccupied( m_me, spot->GetPosition() ))
{
// player is in hiding spot
/// @todo Check if player is moving or sitting still
continue;
}
if (spot->GetArea() && (spot->GetArea()->GetAttributes() & NAV_MESH_DONT_HIDE))
{
// the area has been marked as DONT_HIDE since the last analysis, so let's ignore it
continue;
}
// only collect hiding spots with matching flags
if (m_flags & spot->GetFlags())
{
m_hidingSpot[ m_count ] = &spot->GetPosition();
m_hidingSpotWeight[ m_count ] = m_totalWeight;
// if it's an 'avoid' area, give it a low weight
if ( spot->GetArea() && ( spot->GetArea()->GetAttributes() & NAV_MESH_AVOID ) )
{
m_totalWeight += 1;
}
else
{
m_totalWeight += 2;
}
++m_count;
}
}
return (m_count < MAX_SPOTS);
}
/**
* Remove the spot at index "i"
*/
void RemoveSpot( int i )
{
if (m_count == 0)
return;
for( int j=i+1; j<m_count; ++j )
m_hidingSpot[j-1] = m_hidingSpot[j];
--m_count;
}
int GetRandomHidingSpot( void )
{
int weight = RandomInt( 0, m_totalWeight-1 );
for ( int i=0; i<m_count-1; ++i )
{
// if the next spot's starting weight is over the target weight, this spot is the one
if ( m_hidingSpotWeight[i+1] >= weight )
{
return i;
}
}
// if we didn't find any, it's the last one
return m_count - 1;
}
CBaseEntity *m_me;
const Vector &m_origin;
float m_range;
const Vector *m_hidingSpot[ MAX_SPOTS ];
int m_hidingSpotWeight[ MAX_SPOTS ];
int m_totalWeight;
int m_count;
unsigned char m_flags;
Place m_place;
};
/**
* Do a breadth-first search to find a nearby hiding spot and return it.
* Don't pick a hiding spot that a Player is currently occupying.
* @todo Clean up this mess
*/
const Vector *FindNearbyHidingSpot( CBaseEntity *me, const Vector &pos, float maxRange, bool isSniper, bool useNearest )
{
CNavArea *startArea = TheNavMesh->GetNearestNavArea( pos );
if (startArea == NULL)
return NULL;
// collect set of nearby hiding spots
if (isSniper)
{
CollectHidingSpotsFunctor collector( me, pos, maxRange, HidingSpot::IDEAL_SNIPER_SPOT );
SearchSurroundingAreas( startArea, pos, collector, maxRange );
if (collector.m_count)
{
int which = collector.GetRandomHidingSpot();
return collector.m_hidingSpot[ which ];
}
else
{
// no ideal sniping spots, look for "good" sniping spots
CollectHidingSpotsFunctor collector( me, pos, maxRange, HidingSpot::GOOD_SNIPER_SPOT );
SearchSurroundingAreas( startArea, pos, collector, maxRange );
if (collector.m_count)
{
int which = collector.GetRandomHidingSpot();
return collector.m_hidingSpot[ which ];
}
// no sniping spots at all.. fall through and pick a normal hiding spot
}
}
// collect hiding spots with decent "cover"
CollectHidingSpotsFunctor collector( me, pos, maxRange, HidingSpot::IN_COVER );
SearchSurroundingAreas( startArea, pos, collector, maxRange );
if (collector.m_count == 0)
{
// no hiding spots at all - if we're not a sniper, try to find a sniper spot to use instead
if (!isSniper)
{
return FindNearbyHidingSpot( me, pos, maxRange, true, useNearest );
}
return NULL;
}
if (useNearest)
{
// return closest hiding spot
const Vector *closest = NULL;
float closeRangeSq = 9999999999.9f;
for( int i=0; i<collector.m_count; ++i )
{
float rangeSq = (*collector.m_hidingSpot[i] - pos).LengthSqr();
if (rangeSq < closeRangeSq)
{
closeRangeSq = rangeSq;
closest = collector.m_hidingSpot[i];
}
}
return closest;
}
// select a hiding spot at random
int which = collector.GetRandomHidingSpot();
return collector.m_hidingSpot[ which ];
}
//--------------------------------------------------------------------------------------------------------------
/**
* Select a random hiding spot among the nav areas that are tagged with the given place
*/
const Vector *FindRandomHidingSpot( CBaseEntity *me, Place place, bool isSniper )
{
// collect set of nearby hiding spots
if (isSniper)
{
CollectHidingSpotsFunctor collector( me, me->GetAbsOrigin(), -1.0f, HidingSpot::IDEAL_SNIPER_SPOT, place );
TheNavMesh->ForAllAreas( collector );
if (collector.m_count)
{
int which = RandomInt( 0, collector.m_count-1 );
return collector.m_hidingSpot[ which ];
}
else
{
// no ideal sniping spots, look for "good" sniping spots
CollectHidingSpotsFunctor collector( me, me->GetAbsOrigin(), -1.0f, HidingSpot::GOOD_SNIPER_SPOT, place );
TheNavMesh->ForAllAreas( collector );
if (collector.m_count)
{
int which = RandomInt( 0, collector.m_count-1 );
return collector.m_hidingSpot[ which ];
}
// no sniping spots at all.. fall through and pick a normal hiding spot
}
}
// collect hiding spots with decent "cover"
CollectHidingSpotsFunctor collector( me, me->GetAbsOrigin(), -1.0f, HidingSpot::IN_COVER, place );
TheNavMesh->ForAllAreas( collector );
if (collector.m_count == 0)
return NULL;
// select a hiding spot at random
int which = RandomInt( 0, collector.m_count-1 );
return collector.m_hidingSpot[ which ];
}
//--------------------------------------------------------------------------------------------------------------------
/**
* Select a nearby retreat spot.
* Don't pick a hiding spot that a Player is currently occupying.
* If "avoidTeam" is nonzero, avoid getting close to members of that team.
*/
const Vector *FindNearbyRetreatSpot( CBaseEntity *me, const Vector &start, float maxRange, int avoidTeam )
{
CNavArea *startArea = TheNavMesh->GetNearestNavArea( start );
if (startArea == NULL)
return NULL;
// collect hiding spots with decent "cover"
CollectHidingSpotsFunctor collector( me, start, maxRange, HidingSpot::IN_COVER );
SearchSurroundingAreas( startArea, start, collector, maxRange );
if (collector.m_count == 0)
return NULL;
// find the closest unoccupied hiding spot that crosses the least lines of fire and has the best cover
for( int i=0; i<collector.m_count; ++i )
{
// check if we would have to cross a line of fire to reach this hiding spot
if (IsCrossingLineOfFire( start, *collector.m_hidingSpot[i], me ))
{
collector.RemoveSpot( i );
// back up a step, so iteration won't skip a spot
--i;
continue;
}
// check if there is someone on the avoidTeam near this hiding spot
if (avoidTeam)
{
float range;
if (UTIL_GetClosestPlayer( *collector.m_hidingSpot[i], avoidTeam, &range ))
{
const float dangerRange = 150.0f;
if (range < dangerRange)
{
// there is an avoidable player too near this spot - remove it
collector.RemoveSpot( i );
// back up a step, so iteration won't skip a spot
--i;
continue;
}
}
}
}
if (collector.m_count <= 0)
return NULL;
// all remaining spots are ok - pick one at random
int which = RandomInt( 0, collector.m_count-1 );
return collector.m_hidingSpot[ which ];
}
//--------------------------------------------------------------------------------------------------------------------
/**
* Functor to collect all hiding spots in range that we can reach before the enemy arrives.
* NOTE: This only works for the initial rush.
*/
class CollectArriveFirstSpotsFunctor
{
public:
CollectArriveFirstSpotsFunctor( CBaseEntity *me, const Vector &searchOrigin, float enemyArriveTime, float range, int flags ) : m_searchOrigin( searchOrigin )
{
m_me = me;
m_count = 0;
m_range = range;
m_flags = (unsigned char)flags;
m_enemyArriveTime = enemyArriveTime;
}
enum { MAX_SPOTS = 256 };
bool operator() ( CNavArea *area )
{
// collect all the hiding spots in this area
const HidingSpotVector *pSpots = area->GetHidingSpots();
FOR_EACH_VEC( (*pSpots), it )
{
const HidingSpot *spot = (*pSpots)[ it ];
// make sure hiding spot is in range
if (m_range > 0.0f)
{
if ((spot->GetPosition() - m_searchOrigin).IsLengthGreaterThan( m_range ))
{
continue;
}
}
// if a Player is using this hiding spot, don't consider it
if (IsSpotOccupied( m_me, spot->GetPosition() ))
{
// player is in hiding spot
/// @todo Check if player is moving or sitting still
continue;
}
// only collect hiding spots with matching flags
if (!(m_flags & spot->GetFlags()))
{
continue;
}
// only collect this hiding spot if we can reach it before the enemy arrives
// NOTE: This assumes the area is fairly small and the difference of moving to the corner vs the center is small
const float settleTime = 1.0f;
if (spot->GetArea()->GetEarliestOccupyTime( m_me->GetTeamNumber() ) + settleTime < m_enemyArriveTime)
{
m_hidingSpot[ m_count++ ] = spot;
}
}
// if we've filled up, stop searching
if (m_count == MAX_SPOTS)
return false;
return true;
}
CBaseEntity *m_me;
const Vector &m_searchOrigin;
float m_range;
float m_enemyArriveTime;
unsigned char m_flags;
const HidingSpot *m_hidingSpot[ MAX_SPOTS ];
int m_count;
};
/**
* Select a hiding spot that we can reach before the enemy arrives.
* NOTE: This only works for the initial rush.
*/
const HidingSpot *FindInitialEncounterSpot( CBaseEntity *me, const Vector &searchOrigin, float enemyArriveTime, float maxRange, bool isSniper )
{
CNavArea *startArea = TheNavMesh->GetNearestNavArea( searchOrigin );
if (startArea == NULL)
return NULL;
// collect set of nearby hiding spots
if (isSniper)
{
CollectArriveFirstSpotsFunctor collector( me, searchOrigin, enemyArriveTime, maxRange, HidingSpot::IDEAL_SNIPER_SPOT );
SearchSurroundingAreas( startArea, searchOrigin, collector, maxRange );
if (collector.m_count)
{
int which = RandomInt( 0, collector.m_count-1 );
return collector.m_hidingSpot[ which ];
}
else
{
// no ideal sniping spots, look for "good" sniping spots
CollectArriveFirstSpotsFunctor collector( me, searchOrigin, enemyArriveTime, maxRange, HidingSpot::GOOD_SNIPER_SPOT );
SearchSurroundingAreas( startArea, searchOrigin, collector, maxRange );
if (collector.m_count)
{
int which = RandomInt( 0, collector.m_count-1 );
return collector.m_hidingSpot[ which ];
}
// no sniping spots at all.. fall through and pick a normal hiding spot
}
}
// collect hiding spots with decent "cover"
CollectArriveFirstSpotsFunctor collector( me, searchOrigin, enemyArriveTime, maxRange, HidingSpot::IN_COVER | HidingSpot::EXPOSED );
SearchSurroundingAreas( startArea, searchOrigin, collector, maxRange );
if (collector.m_count == 0)
return NULL;
// select a hiding spot at random
int which = RandomInt( 0, collector.m_count-1 );
return collector.m_hidingSpot[ which ];
}
-402
View File
@@ -1,402 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003
#include "cbase.h"
#include "bot.h"
#include "bot_manager.h"
#include "nav_area.h"
#include "bot_util.h"
#include "basegrenade_shared.h"
#include "cs_bot.h"
#include "tier0/vprof.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
float g_BotUpkeepInterval = 0.0f;
float g_BotUpdateInterval = 0.0f;
//--------------------------------------------------------------------------------------------------------------
CBotManager::CBotManager()
{
InitBotTrig();
}
//--------------------------------------------------------------------------------------------------------------
CBotManager::~CBotManager()
{
}
//--------------------------------------------------------------------------------------------------------------
/**
* Invoked when the round is restarting
*/
void CBotManager::RestartRound( void )
{
DestroyAllGrenades();
ClearDebugMessages();
}
//--------------------------------------------------------------------------------------------------------------
/**
* Invoked at the start of each frame
*/
void CBotManager::StartFrame( void )
{
VPROF_BUDGET( "CBotManager::StartFrame", VPROF_BUDGETGROUP_NPCS );
ValidateActiveGrenades();
// debug smoke grenade visualization
if (cv_bot_debug.GetInt() == 5)
{
Vector edge, lastEdge;
FOR_EACH_LL( m_activeGrenadeList, it )
{
ActiveGrenade *ag = m_activeGrenadeList[ it ];
const Vector &pos = ag->GetDetonationPosition();
UTIL_DrawBeamPoints( pos, pos + Vector( 0, 0, 50 ), 1, 255, 100, 0 );
lastEdge = Vector( ag->GetRadius() + pos.x, pos.y, pos.z );
float angle;
for( angle=0.0f; angle <= 180.0f; angle += 22.5f )
{
edge.x = ag->GetRadius() * BotCOS( angle ) + pos.x;
edge.y = pos.y;
edge.z = ag->GetRadius() * BotSIN( angle ) + pos.z;
UTIL_DrawBeamPoints( edge, lastEdge, 1, 255, 50, 0 );
lastEdge = edge;
}
lastEdge = Vector( pos.x, ag->GetRadius() + pos.y, pos.z );
for( angle=0.0f; angle <= 180.0f; angle += 22.5f )
{
edge.x = pos.x;
edge.y = ag->GetRadius() * BotCOS( angle ) + pos.y;
edge.z = ag->GetRadius() * BotSIN( angle ) + pos.z;
UTIL_DrawBeamPoints( edge, lastEdge, 1, 255, 50, 0 );
lastEdge = edge;
}
}
}
// set frame duration
g_BotUpkeepInterval = m_frameTimer.GetElapsedTime();
m_frameTimer.Start();
g_BotUpdateInterval = (g_BotUpdateSkipCount+1) * g_BotUpkeepInterval;
//
// Process each active bot
//
for( int i = 1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );
if (!player)
continue;
// Hack for now so the temp bot code works. The temp bots are very useful for debugging
// because they can be setup to mimic the player's usercmds.
if (player->IsBot() && IsEntityValid( player ) )
{
// EVIL: Messes up vtables
//CBot< CBasePlayer > *bot = static_cast< CBot< CBasePlayer > * >( player );
CCSBot *bot = dynamic_cast< CCSBot * >( player );
if ( bot )
{
bot->Upkeep();
if (((gpGlobals->tickcount + bot->entindex()) % g_BotUpdateSkipCount) == 0)
{
bot->ResetCommand();
bot->Update();
}
bot->UpdatePlayer();
}
}
}
}
//--------------------------------------------------------------------------------------------------------------
/**
* Add an active grenade to the bot's awareness
*/
void CBotManager::AddGrenade( CBaseGrenade *grenade )
{
ActiveGrenade *ag = new ActiveGrenade( grenade );
m_activeGrenadeList.AddToTail( ag );
}
//--------------------------------------------------------------------------------------------------------------
/**
* The grenade entity in the world is going away
*/
void CBotManager::RemoveGrenade( CBaseGrenade *grenade )
{
FOR_EACH_LL( m_activeGrenadeList, it )
{
ActiveGrenade *ag = m_activeGrenadeList[ it ];
if (ag->IsEntity( grenade ))
{
ag->OnEntityGone();
return;
}
}
}
//--------------------------------------------------------------------------------------------------------------
/**
* The grenade entity has changed its radius
*/
void CBotManager::SetGrenadeRadius( CBaseGrenade *grenade, float radius )
{
FOR_EACH_LL( m_activeGrenadeList, it )
{
ActiveGrenade *ag = m_activeGrenadeList[ it ];
if (ag->IsEntity( grenade ))
{
ag->SetRadius( radius );
return;
}
}
}
//--------------------------------------------------------------------------------------------------------------
/**
* Destroy any invalid active grenades
*/
void CBotManager::ValidateActiveGrenades( void )
{
int it = m_activeGrenadeList.Head();
while( it != m_activeGrenadeList.InvalidIndex() )
{
ActiveGrenade *ag = m_activeGrenadeList[ it ];
int current = it;
it = m_activeGrenadeList.Next( it );
// lazy validation
if (!ag->IsValid())
{
m_activeGrenadeList.Remove( current );
delete ag;
continue;
}
else
{
ag->Update();
}
}
}
//--------------------------------------------------------------------------------------------------------------
void CBotManager::DestroyAllGrenades( void )
{
m_activeGrenadeList.PurgeAndDeleteElements();
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if position is inside a smoke cloud
*/
bool CBotManager::IsInsideSmokeCloud( const Vector *pos )
{
int it = m_activeGrenadeList.Head();
while( it != m_activeGrenadeList.InvalidIndex() )
{
ActiveGrenade *ag = m_activeGrenadeList[ it ];
int current = it;
it = m_activeGrenadeList.Next( it );
// lazy validation
if (!ag->IsValid())
{
m_activeGrenadeList.Remove( current );
delete ag;
continue;
}
if (ag->IsSmoke())
{
const Vector &smokeOrigin = ag->GetDetonationPosition();
if ((smokeOrigin - *pos).IsLengthLessThan( ag->GetRadius() ))
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if line intersects smoke volume
* Determine the length of the line of sight covered by each smoke cloud,
* and sum them (overlap is additive for obstruction).
* If the overlap exceeds the threshold, the bot can't see through.
*/
bool CBotManager::IsLineBlockedBySmoke( const Vector &from, const Vector &to, float grenadeBloat )
{
VPROF_BUDGET( "CBotManager::IsLineBlockedBySmoke", VPROF_BUDGETGROUP_NPCS );
float totalSmokedLength = 0.0f; // distance along line of sight covered by smoke
// compute unit vector and length of line of sight segment
Vector sightDir = to - from;
float sightLength = sightDir.NormalizeInPlace();
FOR_EACH_LL( m_activeGrenadeList, it )
{
ActiveGrenade *ag = m_activeGrenadeList[ it ];
const float smokeRadiusSq = ag->GetRadius() * ag->GetRadius() * grenadeBloat * grenadeBloat;
if (ag->IsSmoke())
{
const Vector &smokeOrigin = ag->GetDetonationPosition();
Vector toGrenade = smokeOrigin - from;
float alongDist = DotProduct( toGrenade, sightDir );
// compute closest point to grenade along line of sight ray
Vector close;
// constrain closest point to line segment
if (alongDist < 0.0f)
close = from;
else if (alongDist >= sightLength)
close = to;
else
close = from + sightDir * alongDist;
// if closest point is within smoke radius, the line overlaps the smoke cloud
Vector toClose = close - smokeOrigin;
float lengthSq = toClose.LengthSqr();
if (lengthSq < smokeRadiusSq)
{
// some portion of the ray intersects the cloud
float fromSq = toGrenade.LengthSqr();
float toSq = (smokeOrigin - to).LengthSqr();
if (fromSq < smokeRadiusSq)
{
if (toSq < smokeRadiusSq)
{
// both 'from' and 'to' lie within the cloud
// entire length is smoked
totalSmokedLength += (to - from).Length();
}
else
{
// 'from' is inside the cloud, 'to' is outside
// compute half of total smoked length as if ray crosses entire cloud chord
float halfSmokedLength = (float)sqrt( smokeRadiusSq - lengthSq );
if (alongDist > 0.0f)
{
// ray goes thru 'close'
totalSmokedLength += halfSmokedLength + (close - from).Length();
}
else
{
// ray starts after 'close'
totalSmokedLength += halfSmokedLength - (close - from).Length();
}
}
}
else if (toSq < smokeRadiusSq)
{
// 'from' is outside the cloud, 'to' is inside
// compute half of total smoked length as if ray crosses entire cloud chord
float halfSmokedLength = (float)sqrt( smokeRadiusSq - lengthSq );
Vector v = to - smokeOrigin;
if (DotProduct( v, sightDir ) > 0.0f)
{
// ray goes thru 'close'
totalSmokedLength += halfSmokedLength + (close - to).Length();
}
else
{
// ray ends before 'close'
totalSmokedLength += halfSmokedLength - (close - to).Length();
}
}
else
{
// 'from' and 'to' lie outside of the cloud - the line of sight completely crosses it
// determine the length of the chord that crosses the cloud
float smokedLength = 2.0f * (float)sqrt( smokeRadiusSq - lengthSq );
totalSmokedLength += smokedLength;
}
}
}
}
// define how much smoke a bot can see thru
const float maxSmokedLength = 0.7f * SmokeGrenadeRadius;
// return true if the total length of smoke-covered line-of-sight is too much
return (totalSmokedLength > maxSmokedLength);
}
//--------------------------------------------------------------------------------------------------------------
void CBotManager::ClearDebugMessages( void )
{
m_debugMessageCount = 0;
m_currentDebugMessage = -1;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Add a new debug message to the message history
*/
void CBotManager::AddDebugMessage( const char *msg )
{
if (++m_currentDebugMessage >= MAX_DBG_MSGS)
{
m_currentDebugMessage = 0;
}
if (m_debugMessageCount < MAX_DBG_MSGS)
{
++m_debugMessageCount;
}
Q_strncpy( m_debugMessage[ m_currentDebugMessage ].m_string, msg, MAX_DBG_MSG_SIZE );
m_debugMessage[ m_currentDebugMessage ].m_age.Start();
}
-195
View File
@@ -1,195 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003
#ifndef BASE_CONTROL_H
#define BASE_CONTROL_H
#pragma warning( disable : 4530 ) // STL uses exceptions, but we are not compiling with them - ignore warning
extern float g_BotUpkeepInterval; ///< duration between bot upkeeps
extern float g_BotUpdateInterval; ///< duration between bot updates
const int g_BotUpdateSkipCount = 2; ///< number of upkeep periods to skip update
class CNavArea;
/// TODO: move CS-specific defines into CSBot files
enum
{
SmokeGrenadeRadius = 155,
FlashbangGrenadeRadius = 115,
HEGrenadeRadius = 115,
};
//--------------------------------------------------------------------------------------------------------------
class CBaseGrenade;
/**
* An ActiveGrenade is a representation of a grenade in the world
* NOTE: Currently only used for smoke grenade line-of-sight testing
* @todo Use system allow bots to avoid HE and Flashbangs
*/
class ActiveGrenade
{
public:
ActiveGrenade( CBaseGrenade *grenadeEntity );
void OnEntityGone( void ); ///< called when the grenade in the world goes away
void Update( void ); ///< called every frame
bool IsValid( void ) const ; ///< return true if this grenade is valid
bool IsEntity( CBaseGrenade *grenade ) const { return (grenade == m_entity) ? true : false; }
CBaseGrenade *GetEntity( void ) const { return m_entity; }
const Vector &GetDetonationPosition( void ) const { return m_detonationPosition; }
const Vector &GetPosition( void ) const;
bool IsSmoke( void ) const { return m_isSmoke; }
bool IsFlashbang( void ) const { return m_isFlashbang; }
CBaseGrenade *GetGrenade( void ) { return m_entity; }
float GetRadius( void ) const { return m_radius; }
void SetRadius( float radius ) { m_radius = radius; }
private:
CBaseGrenade *m_entity; ///< the entity
Vector m_detonationPosition; ///< the location where the grenade detonated (smoke)
float m_dieTimestamp; ///< time this should go away after m_entity is NULL
bool m_isSmoke; ///< true if this is a smoke grenade
bool m_isFlashbang; ///< true if this is a flashbang grenade
float m_radius;
};
typedef CUtlLinkedList<ActiveGrenade *> ActiveGrenadeList;
//--------------------------------------------------------------------------------------------------------------
/**
* This class manages all active bots, propagating events to them and updating them.
*/
class CBotManager
{
public:
CBotManager();
virtual ~CBotManager();
CBasePlayer *AllocateAndBindBotEntity( edict_t *ed ); ///< allocate the appropriate entity for the bot and bind it to the given edict
virtual CBasePlayer *AllocateBotEntity( void ) = 0; ///< factory method to allocate the appropriate entity for the bot
virtual void ClientDisconnect( CBaseEntity *entity ) = 0;
virtual bool ClientCommand( CBasePlayer *player, const CCommand &args ) = 0;
virtual void ServerActivate( void ) = 0;
virtual void ServerDeactivate( void ) = 0;
virtual bool ServerCommand( const char * pcmd ) = 0;
virtual void RestartRound( void ); ///< (EXTEND) invoked when a new round begins
virtual void StartFrame( void ); ///< (EXTEND) called each frame
virtual unsigned int GetPlayerPriority( CBasePlayer *player ) const = 0; ///< return priority of player (0 = max pri)
void AddGrenade( CBaseGrenade *grenade ); ///< add an active grenade to the bot's awareness
void RemoveGrenade( CBaseGrenade *grenade ); ///< the grenade entity in the world is going away
void SetGrenadeRadius( CBaseGrenade *grenade, float radius ); ///< the radius of the grenade entity (or associated smoke cloud)
void ValidateActiveGrenades( void ); ///< destroy any invalid active grenades
void DestroyAllGrenades( void );
bool IsLineBlockedBySmoke( const Vector &from, const Vector &to, float grenadeBloat = 1.0f ); ///< return true if line intersects smoke volume, with grenade radius increased by the grenadeBloat factor
bool IsInsideSmokeCloud( const Vector *pos ); ///< return true if position is inside a smoke cloud
//
// Invoke functor on all active grenades.
// If any functor call return false, return false. Otherwise, return true.
//
template < typename T >
bool ForEachGrenade( T &func )
{
int it = m_activeGrenadeList.Head();
while( it != m_activeGrenadeList.InvalidIndex() )
{
ActiveGrenade *ag = m_activeGrenadeList[ it ];
int current = it;
it = m_activeGrenadeList.Next( it );
// lazy validation
if (!ag->IsValid())
{
m_activeGrenadeList.Remove( current );
delete ag;
continue;
}
else
{
if (func( ag ) == false)
{
return false;
}
}
}
return true;
}
enum { MAX_DBG_MSG_SIZE = 1024 };
struct DebugMessage
{
char m_string[ MAX_DBG_MSG_SIZE ];
IntervalTimer m_age;
};
// debug message history -------------------------------------------------------------------------------
int GetDebugMessageCount( void ) const; ///< get number of debug messages in history
const DebugMessage *GetDebugMessage( int which = 0 ) const; ///< return the debug message emitted by the bot (0 = most recent)
void ClearDebugMessages( void );
void AddDebugMessage( const char *msg );
private:
ActiveGrenadeList m_activeGrenadeList;///< the list of active grenades the bots are aware of
enum { MAX_DBG_MSGS = 6 };
DebugMessage m_debugMessage[ MAX_DBG_MSGS ]; ///< debug message history
int m_debugMessageCount;
int m_currentDebugMessage;
IntervalTimer m_frameTimer; ///< for measuring each frame's duration
};
inline CBasePlayer *CBotManager::AllocateAndBindBotEntity( edict_t *ed )
{
CBasePlayer::s_PlayerEdict = ed;
return AllocateBotEntity();
}
inline int CBotManager::GetDebugMessageCount( void ) const
{
return m_debugMessageCount;
}
inline const CBotManager::DebugMessage *CBotManager::GetDebugMessage( int which ) const
{
if (which >= m_debugMessageCount)
return NULL;
int i = m_currentDebugMessage - which;
if (i < 0)
i += MAX_DBG_MSGS;
return &m_debugMessage[ i ];
}
// global singleton to create and control bots
extern CBotManager *TheBots;
#endif
-704
View File
@@ -1,704 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003
#include "cbase.h"
#pragma warning( disable : 4530 ) // STL uses exceptions, but we are not compiling with them - ignore warning
#define DEFINE_DIFFICULTY_NAMES
#include "bot_profile.h"
#include "shared_util.h"
#include "bot.h"
#include "bot_util.h"
#include "cs_bot.h" // BOTPORT: Remove this CS dependency
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BotProfileManager *TheBotProfiles = NULL;
//--------------------------------------------------------------------------------------------------------
/**
* Generates a filename-decorated skin name
*/
static const char * GetDecoratedSkinName( const char *name, const char *filename )
{
const int BufLen = _MAX_PATH + 64;
static char buf[BufLen];
Q_snprintf( buf, sizeof( buf ), "%s/%s", filename, name );
return buf;
}
//--------------------------------------------------------------------------------------------------------------
const char* BotProfile::GetWeaponPreferenceAsString( int i ) const
{
if ( i < 0 || i >= m_weaponPreferenceCount )
return NULL;
return WeaponIDToAlias( m_weaponPreference[ i ] );
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if this profile has a primary weapon preference
*/
bool BotProfile::HasPrimaryPreference( void ) const
{
for( int i=0; i<m_weaponPreferenceCount; ++i )
{
if (IsPrimaryWeapon( m_weaponPreference[i] ))
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if this profile has a pistol weapon preference
*/
bool BotProfile::HasPistolPreference( void ) const
{
for( int i=0; i<m_weaponPreferenceCount; ++i )
if (IsSecondaryWeapon( m_weaponPreference[i] ))
return true;
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if this profile is valid for the specified team
*/
bool BotProfile::IsValidForTeam( int team ) const
{
return ( team == TEAM_UNASSIGNED || m_teams == TEAM_UNASSIGNED || team == m_teams );
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if this profile inherits from the specified template
*/
bool BotProfile::InheritsFrom( const char *name ) const
{
if ( WildcardMatch( name, GetName() ) )
return true;
for ( int i=0; i<m_templates.Count(); ++i )
{
const BotProfile *queryTemplate = m_templates[i];
if ( queryTemplate->InheritsFrom( name ) )
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Constructor
*/
BotProfileManager::BotProfileManager( void )
{
m_nextSkin = 0;
for (int i=0; i<NumCustomSkins; ++i)
{
m_skins[i] = NULL;
m_skinFilenames[i] = NULL;
m_skinModelnames[i] = NULL;
}
}
//--------------------------------------------------------------------------------------------------------------
/**
* Load the bot profile database
*/
void BotProfileManager::Init( const char *filename, unsigned int *checksum )
{
FileHandle_t file = filesystem->Open( filename, "r" );
if (!file)
{
if ( true ) // UTIL_IsGame( "czero" ) )
{
CONSOLE_ECHO( "WARNING: Cannot access bot profile database '%s'\n", filename );
}
return;
}
int dataLength = filesystem->Size( filename );
char *dataPointer = new char[ dataLength ];
int dataReadLength = filesystem->Read( dataPointer, dataLength, file );
filesystem->Close( file );
if ( dataReadLength > 0 )
{
// NULL-terminate based on the length read in, since Read() can transform \r\n to \n and
// return fewer bytes than we were expecting.
dataPointer[ dataReadLength - 1 ] = 0;
}
const char *dataFile = dataPointer;
// compute simple checksum
if (checksum)
{
*checksum = 0; // ComputeSimpleChecksum( (const unsigned char *)dataPointer, dataLength );
}
BotProfile defaultProfile;
//
// Parse the BotProfile.db into BotProfile instances
//
while( true )
{
dataFile = SharedParse( dataFile );
if (!dataFile)
break;
char *token = SharedGetToken();
bool isDefault = (!stricmp( token, "Default" ));
bool isTemplate = (!stricmp( token, "Template" ));
bool isCustomSkin = (!stricmp( token, "Skin" ));
if ( isCustomSkin )
{
const int BufLen = 64;
char skinName[BufLen];
// get skin name
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing %s - expected skin name\n", filename );
delete [] dataPointer;
return;
}
token = SharedGetToken();
Q_snprintf( skinName, sizeof( skinName ), "%s", token );
// get attribute name
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing %s - expected 'Model'\n", filename );
delete [] dataPointer;
return;
}
token = SharedGetToken();
if (stricmp( "Model", token ))
{
CONSOLE_ECHO( "Error parsing %s - expected 'Model'\n", filename );
delete [] dataPointer;
return;
}
// eat '='
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing %s - expected '='\n", filename );
delete [] dataPointer;
return;
}
token = SharedGetToken();
if (strcmp( "=", token ))
{
CONSOLE_ECHO( "Error parsing %s - expected '='\n", filename );
delete [] dataPointer;
return;
}
// get attribute value
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing %s - expected attribute value\n", filename );
delete [] dataPointer;
return;
}
token = SharedGetToken();
const char *decoratedName = GetDecoratedSkinName( skinName, filename );
bool skinExists = GetCustomSkinIndex( decoratedName ) > 0;
if ( m_nextSkin < NumCustomSkins && !skinExists )
{
// decorate the name
m_skins[ m_nextSkin ] = CloneString( decoratedName );
// construct the model filename
m_skinModelnames[ m_nextSkin ] = CloneString( token );
m_skinFilenames[ m_nextSkin ] = new char[ strlen(token)*2 + strlen("models/player//.mdl") + 1 ];
Q_snprintf( m_skinFilenames[ m_nextSkin ], sizeof( m_skinFilenames[ m_nextSkin ] ), "models/player/%s/%s.mdl", token, token );
++m_nextSkin;
}
// eat 'End'
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing %s - expected 'End'\n", filename );
delete [] dataPointer;
return;
}
token = SharedGetToken();
if (strcmp( "End", token ))
{
CONSOLE_ECHO( "Error parsing %s - expected 'End'\n", filename );
delete [] dataPointer;
return;
}
continue; // it's just a custom skin - no need to do inheritance on a bot profile, etc.
}
// encountered a new profile
BotProfile *profile;
if (isDefault)
{
profile = &defaultProfile;
}
else
{
profile = new BotProfile;
// always inherit from Default
*profile = defaultProfile;
}
// do inheritance in order of appearance
if (!isTemplate && !isDefault)
{
const BotProfile *inherit = NULL;
// template names are separated by "+"
while(true)
{
char *c = strchr( token, '+' );
if (c)
*c = '\000';
// find the given template name
FOR_EACH_LL( m_templateList, it )
{
BotProfile *profile = m_templateList[ it ];
if (!stricmp( profile->GetName(), token ))
{
inherit = profile;
break;
}
}
if (inherit == NULL)
{
CONSOLE_ECHO( "Error parsing '%s' - invalid template reference '%s'\n", filename, token );
delete [] dataPointer;
return;
}
// inherit the data
profile->Inherit( inherit, &defaultProfile );
if (c == NULL)
break;
token = c+1;
}
}
// get name of this profile
if (!isDefault)
{
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing '%s' - expected name\n", filename );
delete [] dataPointer;
return;
}
profile->m_name = CloneString( SharedGetToken() );
/**
* HACK HACK
* Until we have a generalized means of storing bot preferences, we're going to hardcode the bot's
* preference towards silencers based on his name.
*/
if ( profile->m_name[0] % 2 )
{
profile->m_prefersSilencer = true;
}
}
// read attributes for this profile
bool isFirstWeaponPref = true;
while( true )
{
// get next token
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing %s - expected 'End'\n", filename );
delete [] dataPointer;
return;
}
token = SharedGetToken();
// check for End delimiter
if (!stricmp( token, "End" ))
break;
// found attribute name - keep it
char attributeName[64];
strcpy( attributeName, token );
// eat '='
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing %s - expected '='\n", filename );
delete [] dataPointer;
return;
}
token = SharedGetToken();
if (strcmp( "=", token ))
{
CONSOLE_ECHO( "Error parsing %s - expected '='\n", filename );
delete [] dataPointer;
return;
}
// get attribute value
dataFile = SharedParse( dataFile );
if (!dataFile)
{
CONSOLE_ECHO( "Error parsing %s - expected attribute value\n", filename );
delete [] dataPointer;
return;
}
token = SharedGetToken();
// store value in appropriate attribute
if (!stricmp( "Aggression", attributeName ))
{
profile->m_aggression = (float)atof(token) / 100.0f;
}
else if (!stricmp( "Skill", attributeName ))
{
profile->m_skill = (float)atof(token) / 100.0f;
}
else if (!stricmp( "Skin", attributeName ))
{
profile->m_skin = atoi(token);
if ( profile->m_skin == 0 )
{
// atoi() failed - try to look up a custom skin by name
profile->m_skin = GetCustomSkinIndex( token, filename );
}
}
else if (!stricmp( "Teamwork", attributeName ))
{
profile->m_teamwork = (float)atof(token) / 100.0f;
}
else if (!stricmp( "Cost", attributeName ))
{
profile->m_cost = atoi(token);
}
else if (!stricmp( "VoicePitch", attributeName ))
{
profile->m_voicePitch = atoi(token);
}
else if (!stricmp( "VoiceBank", attributeName ))
{
profile->m_voiceBank = FindVoiceBankIndex( token );
}
else if (!stricmp( "WeaponPreference", attributeName ))
{
// weapon preferences override parent prefs
if (isFirstWeaponPref)
{
isFirstWeaponPref = false;
profile->m_weaponPreferenceCount = 0;
}
if (!stricmp( token, "none" ))
{
profile->m_weaponPreferenceCount = 0;
}
else
{
if (profile->m_weaponPreferenceCount < BotProfile::MAX_WEAPON_PREFS)
{
profile->m_weaponPreference[ profile->m_weaponPreferenceCount++ ] = AliasToWeaponID( token );
}
}
}
else if (!stricmp( "ReactionTime", attributeName ))
{
profile->m_reactionTime = (float)atof(token);
#ifndef GAMEUI_EXPORTS
// subtract off latency due to "think" update rate.
// In GameUI, we don't really care.
//profile->m_reactionTime -= g_BotUpdateInterval;
#endif
}
else if (!stricmp( "AttackDelay", attributeName ))
{
profile->m_attackDelay = (float)atof(token);
}
else if (!stricmp( "Difficulty", attributeName ))
{
// override inheritance
profile->m_difficultyFlags = 0;
// parse bit flags
while(true)
{
char *c = strchr( token, '+' );
if (c)
*c = '\000';
for( int i=0; i<NUM_DIFFICULTY_LEVELS; ++i )
if (!stricmp( BotDifficultyName[i], token ))
profile->m_difficultyFlags |= (1 << i);
if (c == NULL)
break;
token = c+1;
}
}
else if (!stricmp( "Team", attributeName ))
{
if ( !stricmp( token, "T" ) )
{
profile->m_teams = TEAM_TERRORIST;
}
else if ( !stricmp( token, "CT" ) )
{
profile->m_teams = TEAM_CT;
}
else
{
profile->m_teams = TEAM_UNASSIGNED;
}
}
else
{
CONSOLE_ECHO( "Error parsing %s - unknown attribute '%s'\n", filename, attributeName );
}
}
if (!isDefault)
{
if (isTemplate)
{
// add to template list
m_templateList.AddToTail( profile );
}
else
{
// add profile to the master list
m_profileList.AddToTail( profile );
}
}
}
delete [] dataPointer;
}
//--------------------------------------------------------------------------------------------------------------
BotProfileManager::~BotProfileManager( void )
{
Reset();
}
//--------------------------------------------------------------------------------------------------------------
/**
* Free all bot profiles
*/
void BotProfileManager::Reset( void )
{
m_profileList.PurgeAndDeleteElements();
m_templateList.PurgeAndDeleteElements();
int i;
for (i=0; i<NumCustomSkins; ++i)
{
if ( m_skins[i] )
{
delete[] m_skins[i];
m_skins[i] = NULL;
}
if ( m_skinFilenames[i] )
{
delete[] m_skinFilenames[i];
m_skinFilenames[i] = NULL;
}
if ( m_skinModelnames[i] )
{
delete[] m_skinModelnames[i];
m_skinModelnames[i] = NULL;
}
}
for ( i=0; i<m_voiceBanks.Count(); ++i )
{
delete[] m_voiceBanks[i];
}
m_voiceBanks.RemoveAll();
}
//--------------------------------------------------------------------------------------------------------
/**
* Returns custom skin name at a particular index
*/
const char * BotProfileManager::GetCustomSkin( int index )
{
if ( index < FirstCustomSkin || index > LastCustomSkin )
{
return NULL;
}
return m_skins[ index - FirstCustomSkin ];
}
//--------------------------------------------------------------------------------------------------------
/**
* Returns custom skin filename at a particular index
*/
const char * BotProfileManager::GetCustomSkinFname( int index )
{
if ( index < FirstCustomSkin || index > LastCustomSkin )
{
return NULL;
}
return m_skinFilenames[ index - FirstCustomSkin ];
}
//--------------------------------------------------------------------------------------------------------
/**
* Returns custom skin modelname at a particular index
*/
const char * BotProfileManager::GetCustomSkinModelname( int index )
{
if ( index < FirstCustomSkin || index > LastCustomSkin )
{
return NULL;
}
return m_skinModelnames[ index - FirstCustomSkin ];
}
//--------------------------------------------------------------------------------------------------------
/**
* Looks up a custom skin index by filename-decorated name (will decorate the name if filename is given)
*/
int BotProfileManager::GetCustomSkinIndex( const char *name, const char *filename )
{
const char * skinName = name;
if ( filename )
{
skinName = GetDecoratedSkinName( name, filename );
}
for (int i=0; i<NumCustomSkins; ++i)
{
if ( m_skins[i] )
{
if ( !stricmp( skinName, m_skins[i] ) )
{
return FirstCustomSkin + i;
}
}
}
return 0;
}
//--------------------------------------------------------------------------------------------------------
/**
* return index of the (custom) bot phrase db, inserting it if needed
*/
int BotProfileManager::FindVoiceBankIndex( const char *filename )
{
int index = 0;
for ( int i=0; i<m_voiceBanks.Count(); ++i )
{
if ( !stricmp( filename, m_voiceBanks[i] ) )
{
return index;
}
}
m_voiceBanks.AddToTail( CloneString( filename ) );
return index;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return random unused profile that matches the given difficulty level
*/
const BotProfile *BotProfileManager::GetRandomProfile( BotDifficultyType difficulty, int team, CSWeaponType weaponType ) const
{
// count up valid profiles
CUtlVector< const BotProfile * > profiles;
FOR_EACH_LL( m_profileList, it )
{
const BotProfile *profile = m_profileList[ it ];
// Match difficulty
if ( !profile->IsDifficulty( difficulty ) )
continue;
// Prevent duplicate names
if ( UTIL_IsNameTaken( profile->GetName() ) )
continue;
// Match team choice
if ( !profile->IsValidForTeam( team ) )
continue;
// Match desired weapon
if ( weaponType != WEAPONTYPE_UNKNOWN )
{
if ( !profile->GetWeaponPreferenceCount() )
continue;
if ( weaponType != WeaponClassFromWeaponID( (CSWeaponID)profile->GetWeaponPreference( 0 ) ) )
continue;
}
profiles.AddToTail( profile );
}
if ( !profiles.Count() )
return NULL;
// select one at random
int which = RandomInt( 0, profiles.Count()-1 );
return profiles[which];
}
-251
View File
@@ -1,251 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003
#ifndef _BOT_PROFILE_H_
#define _BOT_PROFILE_H_
#pragma warning( disable : 4786 ) // long STL names get truncated in browse info.
#include "bot_constants.h"
#include "bot_util.h"
#include "cs_weapon_parse.h"
enum
{
FirstCustomSkin = 100,
NumCustomSkins = 100,
LastCustomSkin = FirstCustomSkin + NumCustomSkins - 1,
};
//--------------------------------------------------------------------------------------------------------------
/**
* A BotProfile describes the "personality" of a given bot
*/
class BotProfile
{
public:
BotProfile( void )
{
m_name = NULL;
m_aggression = 0.0f;
m_skill = 0.0f;
m_teamwork = 0.0f;
m_weaponPreferenceCount = 0;
m_cost = 0;
m_skin = 0;
m_difficultyFlags = 0;
m_voicePitch = 100;
m_reactionTime = 0.3f;
m_attackDelay = 0.0f;
m_teams = TEAM_UNASSIGNED;
m_voiceBank = 0;
m_prefersSilencer = false;
}
~BotProfile( void )
{
if ( m_name )
delete [] m_name;
}
const char *GetName( void ) const { return m_name; } ///< return bot's name
float GetAggression( void ) const { return m_aggression; }
float GetSkill( void ) const { return m_skill; }
float GetTeamwork( void ) const { return m_teamwork; }
CSWeaponID GetWeaponPreference( int i ) const { return m_weaponPreference[ i ]; }
const char *GetWeaponPreferenceAsString( int i ) const;
int GetWeaponPreferenceCount( void ) const { return m_weaponPreferenceCount; }
bool HasPrimaryPreference( void ) const; ///< return true if this profile has a primary weapon preference
bool HasPistolPreference( void ) const; ///< return true if this profile has a pistol weapon preference
int GetCost( void ) const { return m_cost; }
int GetSkin( void ) const { return m_skin; }
bool IsDifficulty( BotDifficultyType diff ) const; ///< return true if this profile can be used for the given difficulty level
int GetVoicePitch( void ) const { return m_voicePitch; }
float GetReactionTime( void ) const { return m_reactionTime; }
float GetAttackDelay( void ) const { return m_attackDelay; }
int GetVoiceBank() const { return m_voiceBank; }
bool IsValidForTeam( int team ) const;
bool PrefersSilencer() const { return m_prefersSilencer; }
bool InheritsFrom( const char *name ) const;
private:
friend class BotProfileManager; ///< for loading profiles
void Inherit( const BotProfile *parent, const BotProfile *baseline ); ///< copy values from parent if they differ from baseline
char *m_name; ///< the bot's name
float m_aggression; ///< percentage: 0 = coward, 1 = berserker
float m_skill; ///< percentage: 0 = terrible, 1 = expert
float m_teamwork; ///< percentage: 0 = rogue, 1 = complete obeyance to team, lots of comm
enum { MAX_WEAPON_PREFS = 16 };
CSWeaponID m_weaponPreference[ MAX_WEAPON_PREFS ]; ///< which weapons this bot likes to use, in order of priority
int m_weaponPreferenceCount;
int m_cost; ///< reputation point cost for career mode
int m_skin; ///< "skin" index
unsigned char m_difficultyFlags; ///< bits set correspond to difficulty levels this is valid for
int m_voicePitch; ///< the pitch shift for bot chatter (100 = normal)
float m_reactionTime; //< our reaction time in seconds
float m_attackDelay; ///< time in seconds from when we notice an enemy to when we open fire
int m_teams; ///< teams for which this profile is valid
bool m_prefersSilencer; ///< does the bot prefer to use silencers?
int m_voiceBank; ///< Index of the BotChatter.db voice bank this profile uses (0 is the default)
CUtlVector< const BotProfile * > m_templates; ///< List of templates we inherit from
};
typedef CUtlLinkedList<BotProfile *> BotProfileList;
inline bool BotProfile::IsDifficulty( BotDifficultyType diff ) const
{
return (m_difficultyFlags & (1 << diff)) ? true : false;
}
/**
* Copy in data from parent if it differs from the baseline
*/
inline void BotProfile::Inherit( const BotProfile *parent, const BotProfile *baseline )
{
if (parent->m_aggression != baseline->m_aggression)
m_aggression = parent->m_aggression;
if (parent->m_skill != baseline->m_skill)
m_skill = parent->m_skill;
if (parent->m_teamwork != baseline->m_teamwork)
m_teamwork = parent->m_teamwork;
if (parent->m_weaponPreferenceCount != baseline->m_weaponPreferenceCount)
{
m_weaponPreferenceCount = parent->m_weaponPreferenceCount;
for( int i=0; i<parent->m_weaponPreferenceCount; ++i )
m_weaponPreference[i] = parent->m_weaponPreference[i];
}
if (parent->m_cost != baseline->m_cost)
m_cost = parent->m_cost;
if (parent->m_skin != baseline->m_skin)
m_skin = parent->m_skin;
if (parent->m_difficultyFlags != baseline->m_difficultyFlags)
m_difficultyFlags = parent->m_difficultyFlags;
if (parent->m_voicePitch != baseline->m_voicePitch)
m_voicePitch = parent->m_voicePitch;
if (parent->m_reactionTime != baseline->m_reactionTime)
m_reactionTime = parent->m_reactionTime;
if (parent->m_attackDelay != baseline->m_attackDelay)
m_attackDelay = parent->m_attackDelay;
if (parent->m_teams != baseline->m_teams)
m_teams = parent->m_teams;
if (parent->m_voiceBank != baseline->m_voiceBank)
m_voiceBank = parent->m_voiceBank;
m_templates.AddToTail( parent );
}
//--------------------------------------------------------------------------------------------------------------
/**
* The BotProfileManager defines the interface to accessing BotProfiles
*/
class BotProfileManager
{
public:
BotProfileManager( void );
~BotProfileManager( void );
void Init( const char *filename, unsigned int *checksum = NULL );
void Reset( void );
/// given a name, return a profile
const BotProfile *GetProfile( const char *name, int team ) const
{
FOR_EACH_LL( m_profileList, it )
{
BotProfile *profile = m_profileList[ it ];
if ( !stricmp( name, profile->GetName() ) && profile->IsValidForTeam( team ) )
return profile;
}
return NULL;
}
/// given a template name and difficulty, return a profile
const BotProfile *GetProfileMatchingTemplate( const char *profileName, int team, BotDifficultyType difficulty ) const
{
FOR_EACH_LL( m_profileList, it )
{
BotProfile *profile = m_profileList[ it ];
if ( !profile->InheritsFrom( profileName ) )
continue;
if ( !profile->IsValidForTeam( team ) )
continue;
if ( !profile->IsDifficulty( difficulty ) )
continue;
if ( UTIL_IsNameTaken( profile->GetName() ) )
continue;
return profile;
}
return NULL;
}
const BotProfileList *GetProfileList( void ) const { return &m_profileList; } ///< return list of all profiles
const BotProfile *GetRandomProfile( BotDifficultyType difficulty, int team, CSWeaponType weaponType ) const; ///< return random unused profile that matches the given difficulty level
const char * GetCustomSkin( int index ); ///< Returns custom skin name at a particular index
const char * GetCustomSkinModelname( int index ); ///< Returns custom skin modelname at a particular index
const char * GetCustomSkinFname( int index ); ///< Returns custom skin filename at a particular index
int GetCustomSkinIndex( const char *name, const char *filename = NULL ); ///< Looks up a custom skin index by name
typedef CUtlVector<char *> VoiceBankList;
const VoiceBankList *GetVoiceBanks( void ) const { return &m_voiceBanks; }
int FindVoiceBankIndex( const char *filename ); ///< return index of the (custom) bot phrase db, inserting it if needed
protected:
BotProfileList m_profileList; ///< the list of all bot profiles
BotProfileList m_templateList; ///< the list of all bot templates
VoiceBankList m_voiceBanks;
char *m_skins[ NumCustomSkins ]; ///< Custom skin names
char *m_skinModelnames[ NumCustomSkins ]; ///< Custom skin modelnames
char *m_skinFilenames[ NumCustomSkins ]; ///< Custom skin filenames
int m_nextSkin; ///< Next custom skin to allocate
};
/// the global singleton for accessing BotProfiles
extern BotProfileManager *TheBotProfiles;
#endif // _BOT_PROFILE_H_
-604
View File
@@ -1,604 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003
#include "cbase.h"
#include "cs_shareddefs.h"
#include "engine/IEngineSound.h"
#include "KeyValues.h"
#include "bot.h"
#include "bot_util.h"
#include "bot_profile.h"
#include "cs_bot.h"
#include <ctype.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static int s_iBeamSprite = 0;
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if given name is already in use by another player
*/
bool UTIL_IsNameTaken( const char *name, bool ignoreHumans )
{
for ( int i = 1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );
if (player == NULL)
continue;
if (player->IsPlayer() && player->IsBot())
{
// bots can have prefixes so we need to check the name
// against the profile name instead.
CCSBot *bot = dynamic_cast<CCSBot *>(player);
if ( bot && bot->GetProfile()->GetName() && FStrEq(name, bot->GetProfile()->GetName()))
{
return true;
}
}
else
{
if (!ignoreHumans)
{
if (FStrEq( name, player->GetPlayerName() ))
return true;
}
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
int UTIL_ClientsInGame( void )
{
int count = 0;
for ( int i = 1; i <= gpGlobals->maxClients; ++i )
{
CBaseEntity *player = UTIL_PlayerByIndex( i );
if (player == NULL)
continue;
count++;
}
return count;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return the number of non-bots on the given team
*/
int UTIL_HumansOnTeam( int teamID, bool isAlive )
{
int count = 0;
for ( int i = 1; i <= gpGlobals->maxClients; ++i )
{
CBaseEntity *entity = UTIL_PlayerByIndex( i );
if ( entity == NULL )
continue;
CBasePlayer *player = static_cast<CBasePlayer *>( entity );
if (player->IsBot())
continue;
if (player->GetTeamNumber() != teamID)
continue;
if (isAlive && !player->IsAlive())
continue;
count++;
}
return count;
}
//--------------------------------------------------------------------------------------------------------------
int UTIL_BotsInGame( void )
{
int count = 0;
for (int i = 1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex( i ));
if ( player == NULL )
continue;
if ( !player->IsBot() )
continue;
count++;
}
return count;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Kick a bot from the given team. If no bot exists on the team, return false.
*/
bool UTIL_KickBotFromTeam( int kickTeam )
{
int i;
// try to kick a dead bot first
for ( i = 1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );
if (player == NULL)
continue;
if (!player->IsBot())
continue;
if (!player->IsAlive() && player->GetTeamNumber() == kickTeam)
{
// its a bot on the right team - kick it
engine->ServerCommand( UTIL_VarArgs( "kick \"%s\"\n", player->GetPlayerName() ) );
return true;
}
}
// no dead bots, kick any bot on the given team
for ( i = 1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );
if (player == NULL)
continue;
if (!player->IsBot())
continue;
if (player->GetTeamNumber() == kickTeam)
{
// its a bot on the right team - kick it
engine->ServerCommand( UTIL_VarArgs( "kick \"%s\"\n", player->GetPlayerName() ) );
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if all of the members of the given team are bots
*/
bool UTIL_IsTeamAllBots( int team )
{
int botCount = 0;
for( int i=1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );
if (player == NULL)
continue;
// skip players on other teams
if (player->GetTeamNumber() != team)
continue;
// if not a bot, fail the test
if (!player->IsBot())
return false;
// is a bot on given team
++botCount;
}
// if team is empty, there are no bots
return (botCount) ? true : false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return the closest active player to the given position.
* If 'distance' is non-NULL, the distance to the closest player is returned in it.
*/
extern CBasePlayer *UTIL_GetClosestPlayer( const Vector &pos, float *distance )
{
CBasePlayer *closePlayer = NULL;
float closeDistSq = 999999999999.9f;
for ( int i = 1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );
if (!IsEntityValid( player ))
continue;
if (!player->IsAlive())
continue;
Vector playerOrigin = GetCentroid( player );
float distSq = (playerOrigin - pos).LengthSqr();
if (distSq < closeDistSq)
{
closeDistSq = distSq;
closePlayer = static_cast<CBasePlayer *>( player );
}
}
if (distance)
*distance = (float)sqrt( closeDistSq );
return closePlayer;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return the closest active player on the given team to the given position.
* If 'distance' is non-NULL, the distance to the closest player is returned in it.
*/
extern CBasePlayer *UTIL_GetClosestPlayer( const Vector &pos, int team, float *distance )
{
CBasePlayer *closePlayer = NULL;
float closeDistSq = 999999999999.9f;
for ( int i = 1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );
if (!IsEntityValid( player ))
continue;
if (!player->IsAlive())
continue;
if (player->GetTeamNumber() != team)
continue;
Vector playerOrigin = GetCentroid( player );
float distSq = (playerOrigin - pos).LengthSqr();
if (distSq < closeDistSq)
{
closeDistSq = distSq;
closePlayer = static_cast<CBasePlayer *>( player );
}
}
if (distance)
*distance = (float)sqrt( closeDistSq );
return closePlayer;
}
//--------------------------------------------------------------------------------------------------------------
// Takes the bot pointer and constructs the net name using the current bot name prefix.
void UTIL_ConstructBotNetName( char *name, int nameLength, const BotProfile *profile )
{
if (profile == NULL)
{
name[0] = 0;
return;
}
// if there is no bot prefix just use the profile name.
if ((cv_bot_prefix.GetString() == NULL) || (strlen(cv_bot_prefix.GetString()) == 0))
{
Q_strncpy( name, profile->GetName(), nameLength );
return;
}
// find the highest difficulty
const char *diffStr = BotDifficultyName[0];
for ( int i=BOT_EXPERT; i>0; --i )
{
if ( profile->IsDifficulty( (BotDifficultyType)i ) )
{
diffStr = BotDifficultyName[i];
break;
}
}
const char *weaponStr = NULL;
if ( profile->GetWeaponPreferenceCount() )
{
weaponStr = profile->GetWeaponPreferenceAsString( 0 );
const char *translatedAlias = GetTranslatedWeaponAlias( weaponStr );
char wpnName[128];
Q_snprintf( wpnName, sizeof( wpnName ), "weapon_%s", translatedAlias );
WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( wpnName );
if ( hWpnInfo != GetInvalidWeaponInfoHandle() )
{
CCSWeaponInfo *pWeaponInfo = dynamic_cast< CCSWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) );
if ( pWeaponInfo )
{
CSWeaponType weaponType = pWeaponInfo->m_WeaponType;
weaponStr = WeaponClassAsString( weaponType );
}
}
}
if ( !weaponStr )
{
weaponStr = "";
}
char skillStr[16];
Q_snprintf( skillStr, sizeof( skillStr ), "%.0f", profile->GetSkill()*100 );
char temp[MAX_PLAYER_NAME_LENGTH*2];
char prefix[MAX_PLAYER_NAME_LENGTH*2];
Q_strncpy( temp, cv_bot_prefix.GetString(), sizeof( temp ) );
Q_StrSubst( temp, "<difficulty>", diffStr, prefix, sizeof( prefix ) );
Q_StrSubst( prefix, "<weaponclass>", weaponStr, temp, sizeof( temp ) );
Q_StrSubst( temp, "<skill>", skillStr, prefix, sizeof( prefix ) );
Q_snprintf( name, nameLength, "%s %s", prefix, profile->GetName() );
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if anyone on the given team can see the given spot
*/
bool UTIL_IsVisibleToTeam( const Vector &spot, int team )
{
for( int i = 1; i <= gpGlobals->maxClients; ++i )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );
if (player == NULL)
continue;
if (!player->IsAlive())
continue;
if (player->GetTeamNumber() != team)
continue;
trace_t result;
UTIL_TraceLine( player->EyePosition(), spot, CONTENTS_SOLID, player, COLLISION_GROUP_NONE, &result );
if (result.fraction == 1.0f)
return true;
}
return false;
}
//------------------------------------------------------------------------------------------------------------
void UTIL_DrawBeamFromEnt( int i, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue )
{
/* BOTPORT: What is the replacement for MESSAGE_BEGIN?
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecEnd ); // vecEnd = origin???
WRITE_BYTE( TE_BEAMENTPOINT );
WRITE_SHORT( i );
WRITE_COORD( vecEnd.x );
WRITE_COORD( vecEnd.y );
WRITE_COORD( vecEnd.z );
WRITE_SHORT( s_iBeamSprite );
WRITE_BYTE( 0 ); // startframe
WRITE_BYTE( 0 ); // framerate
WRITE_BYTE( iLifetime ); // life
WRITE_BYTE( 10 ); // width
WRITE_BYTE( 0 ); // noise
WRITE_BYTE( bRed ); // r, g, b
WRITE_BYTE( bGreen ); // r, g, b
WRITE_BYTE( bBlue ); // r, g, b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // speed
MESSAGE_END();
*/
}
//------------------------------------------------------------------------------------------------------------
void UTIL_DrawBeamPoints( Vector vecStart, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue )
{
NDebugOverlay::Line( vecStart, vecEnd, bRed, bGreen, bBlue, true, 0.1f );
/*
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecStart );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD( vecStart.x );
WRITE_COORD( vecStart.y );
WRITE_COORD( vecStart.z );
WRITE_COORD( vecEnd.x );
WRITE_COORD( vecEnd.y );
WRITE_COORD( vecEnd.z );
WRITE_SHORT( s_iBeamSprite );
WRITE_BYTE( 0 ); // startframe
WRITE_BYTE( 0 ); // framerate
WRITE_BYTE( iLifetime ); // life
WRITE_BYTE( 10 ); // width
WRITE_BYTE( 0 ); // noise
WRITE_BYTE( bRed ); // r, g, b
WRITE_BYTE( bGreen ); // r, g, b
WRITE_BYTE( bBlue ); // r, g, b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // speed
MESSAGE_END();
*/
}
//------------------------------------------------------------------------------------------------------------
void CONSOLE_ECHO( const char * pszMsg, ... )
{
va_list argptr;
static char szStr[1024];
va_start( argptr, pszMsg );
vsprintf( szStr, pszMsg, argptr );
va_end( argptr );
Msg( "%s", szStr );
}
//------------------------------------------------------------------------------------------------------------
void BotPrecache( void )
{
s_iBeamSprite = CBaseEntity::PrecacheModel( "sprites/smoke.spr" );
}
//------------------------------------------------------------------------------------------------------------
#define COS_TABLE_SIZE 256
static float cosTable[ COS_TABLE_SIZE ];
void InitBotTrig( void )
{
for( int i=0; i<COS_TABLE_SIZE; ++i )
{
float angle = (float)(2.0f * M_PI * i / (float)(COS_TABLE_SIZE-1));
cosTable[i] = (float)cos( angle );
}
}
float BotCOS( float angle )
{
angle = AngleNormalizePositive( angle );
int i = (int)( angle * (COS_TABLE_SIZE-1) / 360.0f );
return cosTable[i];
}
float BotSIN( float angle )
{
angle = AngleNormalizePositive( angle - 90 );
int i = (int)( angle * (COS_TABLE_SIZE-1) / 360.0f );
return cosTable[i];
}
//--------------------------------------------------------------------------------------------------------------
/**
* Send a "hint" message to all players, dead or alive.
*/
void HintMessageToAllPlayers( const char *message )
{
hudtextparms_t textParms;
textParms.x = -1.0f;
textParms.y = -1.0f;
textParms.fadeinTime = 1.0f;
textParms.fadeoutTime = 5.0f;
textParms.holdTime = 5.0f;
textParms.fxTime = 0.0f;
textParms.r1 = 100;
textParms.g1 = 255;
textParms.b1 = 100;
textParms.r2 = 255;
textParms.g2 = 255;
textParms.b2 = 255;
textParms.effect = 0;
textParms.channel = 0;
UTIL_HudMessageAll( textParms, message );
}
//--------------------------------------------------------------------------------------------------------------------
/**
* Return true if moving from "start" to "finish" will cross a player's line of fire.
* The path from "start" to "finish" is assumed to be a straight line.
* "start" and "finish" are assumed to be points on the ground.
*/
bool IsCrossingLineOfFire( const Vector &start, const Vector &finish, CBaseEntity *ignore, int ignoreTeam )
{
for ( int p=1; p <= gpGlobals->maxClients; ++p )
{
CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( p ) );
if (!IsEntityValid( player ))
continue;
if (player == ignore)
continue;
if (!player->IsAlive())
continue;
if (ignoreTeam && player->GetTeamNumber() == ignoreTeam)
continue;
// compute player's unit aiming vector
Vector viewForward;
AngleVectors( player->EyeAngles() + player->GetPunchAngle(), &viewForward );
const float longRange = 5000.0f;
Vector playerOrigin = GetCentroid( player );
Vector playerTarget = playerOrigin + longRange * viewForward;
Vector result( 0, 0, 0 );
if (IsIntersecting2D( start, finish, playerOrigin, playerTarget, &result ))
{
// simple check to see if intersection lies in the Z range of the path
float loZ, hiZ;
if (start.z < finish.z)
{
loZ = start.z;
hiZ = finish.z;
}
else
{
loZ = finish.z;
hiZ = start.z;
}
if (result.z >= loZ && result.z <= hiZ + HumanHeight)
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Performs a simple case-insensitive string comparison, honoring trailing * wildcards
*/
bool WildcardMatch( const char *query, const char *test )
{
if ( !query || !test )
return false;
while ( *test && *query )
{
char nameChar = *test;
char queryChar = *query;
if ( tolower(nameChar) != tolower(queryChar) ) // case-insensitive
break;
++test;
++query;
}
if ( *query == 0 && *test == 0 )
return true;
// Support trailing *
if ( *query == '*' )
return true;
return false;
}
-167
View File
@@ -1,167 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BOT_UTIL_H
#define BOT_UTIL_H
#include "convar.h"
#include "util.h"
//--------------------------------------------------------------------------------------------------------------
enum PriorityType
{
PRIORITY_LOW, PRIORITY_MEDIUM, PRIORITY_HIGH, PRIORITY_UNINTERRUPTABLE
};
extern ConVar cv_bot_traceview;
extern ConVar cv_bot_stop;
extern ConVar cv_bot_show_nav;
extern ConVar cv_bot_walk;
extern ConVar cv_bot_difficulty;
extern ConVar cv_bot_debug;
extern ConVar cv_bot_debug_target;
extern ConVar cv_bot_quota;
extern ConVar cv_bot_quota_mode;
extern ConVar cv_bot_prefix;
extern ConVar cv_bot_allow_rogues;
extern ConVar cv_bot_allow_pistols;
extern ConVar cv_bot_allow_shotguns;
extern ConVar cv_bot_allow_sub_machine_guns;
extern ConVar cv_bot_allow_rifles;
extern ConVar cv_bot_allow_machine_guns;
extern ConVar cv_bot_allow_grenades;
extern ConVar cv_bot_allow_snipers;
extern ConVar cv_bot_allow_shield;
extern ConVar cv_bot_join_team;
extern ConVar cv_bot_join_after_player;
extern ConVar cv_bot_auto_vacate;
extern ConVar cv_bot_zombie;
extern ConVar cv_bot_defer_to_human;
extern ConVar cv_bot_chatter;
extern ConVar cv_bot_profile_db;
extern ConVar cv_bot_dont_shoot;
extern ConVar cv_bot_eco_limit;
extern ConVar cv_bot_auto_follow;
extern ConVar cv_bot_flipout;
#define RAD_TO_DEG( deg ) ((deg) * 180.0 / M_PI)
#define DEG_TO_RAD( rad ) ((rad) * M_PI / 180.0)
#define SIGN( num ) (((num) < 0) ? -1 : 1)
#define ABS( num ) (SIGN(num) * (num))
#define CREATE_FAKE_CLIENT ( *g_engfuncs.pfnCreateFakeClient )
#define GET_USERINFO ( *g_engfuncs.pfnGetInfoKeyBuffer )
#define SET_KEY_VALUE ( *g_engfuncs.pfnSetKeyValue )
#define SET_CLIENT_KEY_VALUE ( *g_engfuncs.pfnSetClientKeyValue )
class BotProfile;
extern void BotPrecache( void );
extern int UTIL_ClientsInGame( void );
extern bool UTIL_IsNameTaken( const char *name, bool ignoreHumans = false ); ///< return true if given name is already in use by another player
#define IS_ALIVE true
extern int UTIL_HumansOnTeam( int teamID, bool isAlive = false );
extern int UTIL_BotsInGame( void );
extern bool UTIL_IsTeamAllBots( int team );
extern void UTIL_DrawBeamFromEnt( int iIndex, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue );
extern void UTIL_DrawBeamPoints( Vector vecStart, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue );
extern CBasePlayer *UTIL_GetClosestPlayer( const Vector &pos, float *distance = NULL );
extern CBasePlayer *UTIL_GetClosestPlayer( const Vector &pos, int team, float *distance = NULL );
extern bool UTIL_KickBotFromTeam( int kickTeam ); ///< kick a bot from the given team. If no bot exists on the team, return false.
extern bool UTIL_IsVisibleToTeam( const Vector &spot, int team ); ///< return true if anyone on the given team can see the given spot
/// return true if moving from "start" to "finish" will cross a player's line of fire.
extern bool IsCrossingLineOfFire( const Vector &start, const Vector &finish, CBaseEntity *ignore = NULL, int ignoreTeam = 0 );
extern void UTIL_ConstructBotNetName(char *name, int nameLength, const BotProfile *bot); ///< constructs a complete name including prefix
/**
* Echos text to the console, and prints it on the client's screen. This is NOT tied to the developer cvar.
* If you are adding debugging output in cstrike, use UTIL_DPrintf() (debug.h) instead.
*/
extern void CONSOLE_ECHO( PRINTF_FORMAT_STRING const char * pszMsg, ... );
extern void InitBotTrig( void );
extern float BotCOS( float angle );
extern float BotSIN( float angle );
extern void HintMessageToAllPlayers( const char *message );
bool WildcardMatch( const char *query, const char *test ); ///< Performs a simple case-insensitive string comparison, honoring trailing * wildcards
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if the given entity is valid
*/
inline bool IsEntityValid( CBaseEntity *entity )
{
if (entity == NULL)
return false;
if (FNullEnt( entity->edict() ))
return false;
return true;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Given two line segments: startA to endA, and startB to endB, return true if they intesect
* and put the intersection point in "result".
* Note that this computes the intersection of the 2D (x,y) projection of the line segments.
*/
inline bool IsIntersecting2D( const Vector &startA, const Vector &endA,
const Vector &startB, const Vector &endB,
Vector *result = NULL )
{
float denom = (endA.x - startA.x) * (endB.y - startB.y) - (endA.y - startA.y) * (endB.x - startB.x);
if (denom == 0.0f)
{
// parallel
return false;
}
float numS = (startA.y - startB.y) * (endB.x - startB.x) - (startA.x - startB.x) * (endB.y - startB.y);
if (numS == 0.0f)
{
// coincident
return true;
}
float numT = (startA.y - startB.y) * (endA.x - startA.x) - (startA.x - startB.x) * (endA.y - startA.y);
float s = numS / denom;
if (s < 0.0f || s > 1.0f)
{
// intersection is not within line segment of startA to endA
return false;
}
float t = numT / denom;
if (t < 0.0f || t > 1.0f)
{
// intersection is not within line segment of startB to endB
return false;
}
// compute intesection point
if (result)
*result = startA + s * (endA - startA);
return true;
}
#endif
@@ -1,57 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// improv_locomotor.h
// Interface for moving Improvs along computed paths
// Author: Michael Booth, July 2004
#ifndef _IMPROV_LOCOMOTOR_H_
#define _IMPROV_LOCOMOTOR_H_
// TODO: Remove duplicate methods from CImprov, and update CImprov to use this class
/**
* A locomotor owns the movement of an Improv
*/
class CImprovLocomotor
{
public:
virtual const Vector &GetCentroid( void ) const = 0;
virtual const Vector &GetFeet( void ) const = 0; ///< return position of "feet" - point below centroid of improv at feet level
virtual const Vector &GetEyes( void ) const = 0;
virtual float GetMoveAngle( void ) const = 0; ///< return direction of movement
virtual CNavArea *GetLastKnownArea( void ) const = 0;
virtual bool GetSimpleGroundHeightWithFloor( const Vector &pos, float *height, Vector *normal = NULL ) = 0; ///< find "simple" ground height, treating current nav area as part of the floor
virtual void Crouch( void ) = 0;
virtual void StandUp( void ) = 0; ///< "un-crouch"
virtual bool IsCrouching( void ) const = 0;
virtual void Jump( void ) = 0; ///< initiate a jump
virtual bool IsJumping( void ) const = 0;
virtual void Run( void ) = 0; ///< set movement speed to running
virtual void Walk( void ) = 0; ///< set movement speed to walking
virtual bool IsRunning( void ) const = 0;
virtual void StartLadder( const CNavLadder *ladder, NavTraverseType how, const Vector &approachPos, const Vector &departPos ) = 0; ///< invoked when a ladder is encountered while following a path
virtual bool TraverseLadder( const CNavLadder *ladder, NavTraverseType how, const Vector &approachPos, const Vector &departPos, float deltaT ) = 0; ///< traverse given ladder
virtual bool IsUsingLadder( void ) const = 0;
enum MoveToFailureType
{
FAIL_INVALID_PATH,
FAIL_STUCK,
FAIL_FELL_OFF,
};
virtual void TrackPath( const Vector &pathGoal, float deltaT ) = 0; ///< move along path by following "pathGoal"
virtual void OnMoveToSuccess( const Vector &goal ) { } ///< invoked when an improv reaches its MoveTo goal
virtual void OnMoveToFailure( const Vector &goal, MoveToFailureType reason ) { } ///< invoked when an improv fails to reach a MoveTo goal
};
#endif // _IMPROV_LOCOMOTOR_H_
File diff suppressed because it is too large Load Diff
-246
View File
@@ -1,246 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// nav_path.h
// Navigation Path encapsulation
// Author: Michael S. Booth (mike@turtlerockstudios.com), November 2003
#ifndef _NAV_PATH_H_
#define _NAV_PATH_H_
#include "cs_nav_area.h"
#include "bot_util.h"
class CImprovLocomotor;
//--------------------------------------------------------------------------------------------------------
/**
* The CNavPath class encapsulates a path through space
*/
class CNavPath
{
public:
CNavPath( void )
{
m_segmentCount = 0;
}
struct PathSegment
{
CNavArea *area; ///< the area along the path
NavTraverseType how; ///< how to enter this area from the previous one
Vector pos; ///< our movement goal position at this point in the path
const CNavLadder *ladder; ///< if "how" refers to a ladder, this is it
};
const PathSegment * operator[] ( int i ) const { return (i >= 0 && i < m_segmentCount) ? &m_path[i] : NULL; }
const PathSegment *GetSegment( int i ) const { return (i >= 0 && i < m_segmentCount) ? &m_path[i] : NULL; }
int GetSegmentCount( void ) const { return m_segmentCount; }
const Vector &GetEndpoint( void ) const { return m_path[ m_segmentCount-1 ].pos; }
bool IsAtEnd( const Vector &pos ) const; ///< return true if position is at the end of the path
float GetLength( void ) const; ///< return length of path from start to finish
bool GetPointAlongPath( float distAlong, Vector *pointOnPath ) const; ///< return point a given distance along the path - if distance is out of path bounds, point is clamped to start/end
/// return the node index closest to the given distance along the path without going over - returns (-1) if error
int GetSegmentIndexAlongPath( float distAlong ) const;
bool IsValid( void ) const { return (m_segmentCount > 0); }
void Invalidate( void ) { m_segmentCount = 0; }
void Draw( const Vector &color = Vector( 1.0f, 0.3f, 0 ) ); ///< draw the path for debugging
/// compute closest point on path to given point
bool FindClosestPointOnPath( const Vector *worldPos, int startIndex, int endIndex, Vector *close ) const;
void Optimize( void );
/**
* Compute shortest path from 'start' to 'goal' via A* algorithm.
* If returns true, path was build to the goal position.
* If returns false, path may either be invalid (use IsValid() to check), or valid but
* doesn't reach all the way to the goal.
*/
template< typename CostFunctor >
bool Compute( const Vector &start, const Vector &goal, CostFunctor &costFunc )
{
Invalidate();
CNavArea *startArea = TheNavMesh->GetNearestNavArea( start + Vector( 0.0f, 0.0f, 1.0f ) );
if (startArea == NULL)
{
return false;
}
CNavArea *goalArea = TheNavMesh->GetNavArea( goal );
// if we are already in the goal area, build trivial path
if (startArea == goalArea)
{
BuildTrivialPath( start, goal );
return true;
}
// make sure path end position is on the ground
Vector pathEndPosition = goal;
if (goalArea)
{
pathEndPosition.z = goalArea->GetZ( pathEndPosition );
}
else
{
TheNavMesh->GetGroundHeight( pathEndPosition, &pathEndPosition.z );
}
//
// Compute shortest path to goal
//
CNavArea *closestArea;
bool pathResult = NavAreaBuildPath( startArea, goalArea, &goal, costFunc, &closestArea );
//
// Build path by following parent links
//
// get count
int count = 0;
CNavArea *area;
for( area = closestArea; area; area = area->GetParent() )
{
++count;
}
// save room for endpoint
if (count > MAX_PATH_SEGMENTS-1)
{
count = MAX_PATH_SEGMENTS-1;
}
if (count == 0)
{
return false;
}
if (count == 1)
{
BuildTrivialPath( start, goal );
return true;
}
// build path
m_segmentCount = count;
for( area = closestArea; count && area; area = area->GetParent() )
{
--count;
m_path[ count ].area = area;
m_path[ count ].how = area->GetParentHow();
}
// compute path positions
if (ComputePathPositions() == false)
{
//PrintIfWatched( "CNavPath::Compute: Error building path\n" );
Invalidate();
return false;
}
// append path end position
m_path[ m_segmentCount ].area = closestArea;
m_path[ m_segmentCount ].pos = pathEndPosition;
m_path[ m_segmentCount ].ladder = NULL;
m_path[ m_segmentCount ].how = NUM_TRAVERSE_TYPES;
++m_segmentCount;
return pathResult;
}
private:
enum { MAX_PATH_SEGMENTS = 256 };
PathSegment m_path[ MAX_PATH_SEGMENTS ];
int m_segmentCount;
bool ComputePathPositions( void ); ///< determine actual path positions
bool BuildTrivialPath( const Vector &start, const Vector &goal ); ///< utility function for when start and goal are in the same area
int FindNextOccludedNode( int anchor ); ///< used by Optimize()
};
//--------------------------------------------------------------------------------------------------------
/**
* Monitor improv movement and determine if it becomes stuck
*/
class CStuckMonitor
{
public:
CStuckMonitor( void );
void Reset( void );
void Update( CImprovLocomotor *improv );
bool IsStuck( void ) const { return m_isStuck; }
float GetDuration( void ) const { return (m_isStuck) ? m_stuckTimer.GetElapsedTime() : 0.0f; }
private:
bool m_isStuck; ///< if true, we are stuck
Vector m_stuckSpot; ///< the location where we became stuck
IntervalTimer m_stuckTimer; ///< how long we have been stuck
enum { MAX_VEL_SAMPLES = 5 };
float m_avgVel[ MAX_VEL_SAMPLES ];
int m_avgVelIndex;
int m_avgVelCount;
Vector m_lastCentroid;
float m_lastTime;
};
//--------------------------------------------------------------------------------------------------------
/**
* The CNavPathFollower class implements path following behavior
*/
class CNavPathFollower
{
public:
CNavPathFollower( void );
void SetImprov( CImprovLocomotor *improv ) { m_improv = improv; }
void SetPath( CNavPath *path ) { m_path = path; }
void Reset( void );
#define DONT_AVOID_OBSTACLES false
void Update( float deltaT, bool avoidObstacles = true ); ///< move improv along path
void Debug( bool status ) { m_isDebug = status; } ///< turn debugging on/off
bool IsStuck( void ) const { return m_stuckMonitor.IsStuck(); } ///< return true if improv is stuck
void ResetStuck( void ) { m_stuckMonitor.Reset(); }
float GetStuckDuration( void ) const { return m_stuckMonitor.GetDuration(); } ///< return how long we've been stuck
void FeelerReflexAdjustment( Vector *goalPosition, float height = -1.0f ); ///< adjust goal position if "feelers" are touched
private:
CImprovLocomotor *m_improv; ///< who is doing the path following
CNavPath *m_path; ///< the path being followed
int m_segmentIndex; ///< the point on the path the improv is moving towards
int m_behindIndex; ///< index of the node on the path just behind us
Vector m_goal; ///< last computed follow goal
bool m_isLadderStarted;
bool m_isDebug;
int FindOurPositionOnPath( Vector *close, bool local ) const; ///< return the closest point to our current position on current path
int FindPathPoint( float aheadRange, Vector *point, int *prevIndex ); ///< compute a point a fixed distance ahead along our path.
CStuckMonitor m_stuckMonitor;
};
#endif // _NAV_PATH_H_
-207
View File
@@ -1,207 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: dll-agnostic routines (no dll dependencies here)
//
// $NoKeywords: $
//=============================================================================//
// Author: Matthew D. Campbell (matt@turtlerockstudios.com), 2003
#include "cbase.h"
#include <ctype.h>
#include "shared_util.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static char s_shared_token[ 1500 ];
static char s_shared_quote = '\"';
//--------------------------------------------------------------------------------------------------------------
char * SharedVarArgs(const char *format, ...)
{
va_list argptr;
const int BufLen = 1024;
const int NumBuffers = 4;
static char string[NumBuffers][BufLen];
static int curstring = 0;
curstring = ( curstring + 1 ) % NumBuffers;
va_start (argptr, format);
V_vsprintf_safe( string[curstring], format, argptr );
va_end (argptr);
return string[curstring];
}
//--------------------------------------------------------------------------------------------------------------
char * BufPrintf(char *buf, int& len, const char *fmt, ...)
{
if (len <= 0)
return NULL;
va_list argptr;
va_start(argptr, fmt);
_vsnprintf(buf, len, fmt, argptr);
buf[ len - 1 ] = 0;
va_end(argptr);
len -= strlen(buf);
return buf + strlen(buf);
}
//--------------------------------------------------------------------------------------------------------------
wchar_t * BufWPrintf(wchar_t *buf, int& len, const wchar_t *fmt, ...)
{
if (len <= 0)
return NULL;
va_list argptr;
va_start(argptr, fmt);
#ifdef WIN32
_vsnwprintf(buf, len, fmt, argptr);
#else
vswprintf( buf, len, fmt, argptr );
#endif
buf[ len - 1 ] = 0;
va_end(argptr);
len -= wcslen(buf);
return buf + wcslen(buf);
}
//--------------------------------------------------------------------------------------------------------------
const wchar_t * NumAsWString( int val )
{
const int BufLen = 16;
static wchar_t buf[BufLen];
int len = BufLen;
BufWPrintf( buf, len, L"%d", val );
return buf;
}
//--------------------------------------------------------------------------------------------------------------
const char * NumAsString( int val )
{
const int BufLen = 16;
static char buf[BufLen];
int len = BufLen;
BufPrintf( buf, len, "%d", val );
return buf;
}
//--------------------------------------------------------------------------------------------------------
/**
* Returns the token parsed by SharedParse()
*/
char *SharedGetToken( void )
{
return s_shared_token;
}
//--------------------------------------------------------------------------------------------------------
/**
* Returns the token parsed by SharedParse()
*/
void SharedSetQuoteChar( char c )
{
s_shared_quote = c;
}
//--------------------------------------------------------------------------------------------------------
/**
* Parse a token out of a string
*/
const char *SharedParse( const char *data )
{
int c;
int len;
len = 0;
s_shared_token[0] = 0;
if (!data)
return NULL;
// skip whitespace
skipwhite:
while ( (c = *data) <= ' ')
{
if (c == 0)
return NULL; // end of file;
data++;
}
// skip // comments
if (c=='/' && data[1] == '/')
{
while (*data && *data != '\n')
data++;
goto skipwhite;
}
// handle quoted strings specially
if (c == s_shared_quote)
{
data++;
while (1)
{
c = *data++;
if (c==s_shared_quote || !c)
{
s_shared_token[len] = 0;
return data;
}
s_shared_token[len] = c;
len++;
}
}
// parse single characters
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c == ',' )
{
s_shared_token[len] = c;
len++;
s_shared_token[len] = 0;
return data+1;
}
// parse a regular word
do
{
s_shared_token[len] = c;
data++;
len++;
c = *data;
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c == ',' )
break;
} while (c>32);
s_shared_token[len] = 0;
return data;
}
//--------------------------------------------------------------------------------------------------------
/**
* Returns true if additional data is waiting to be processed on this line
*/
bool SharedTokenWaiting( const char *buffer )
{
const char *p;
p = buffer;
while ( *p && *p!='\n')
{
if ( !isspace( *p ) || isalnum( *p ) )
return true;
p++;
}
return false;
}
-83
View File
@@ -1,83 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: dll-agnostic routines (no dll dependencies here)
//
// $NoKeywords: $
//=============================================================================//
// Author: Matthew D. Campbell (matt@turtlerockstudios.com), 2003
#ifndef SHARED_UTIL_H
#define SHARED_UTIL_H
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//--------------------------------------------------------------------------------------------------------
/**
* Returns the token parsed by SharedParse()
*/
char *SharedGetToken( void );
//--------------------------------------------------------------------------------------------------------
/**
* Sets the character used to delimit quoted strings. Default is '\"'. Be sure to set it back when done.
*/
void SharedSetQuoteChar( char c );
//--------------------------------------------------------------------------------------------------------
/**
* Parse a token out of a string
*/
const char *SharedParse( const char *data );
//--------------------------------------------------------------------------------------------------------
/**
* Returns true if additional data is waiting to be processed on this line
*/
bool SharedTokenWaiting( const char *buffer );
//--------------------------------------------------------------------------------------------------------
/**
* Simple utility function to allocate memory and duplicate a string
*/
inline char *CloneString( const char *str )
{
char *cloneStr = new char [ strlen(str)+1 ];
strcpy( cloneStr, str );
return cloneStr;
}
//--------------------------------------------------------------------------------------------------------------
/**
* snprintf-alike that allows multiple prints into a buffer
*/
char * BufPrintf(char *buf, int& len, PRINTF_FORMAT_STRING const char *fmt, ...);
//--------------------------------------------------------------------------------------------------------------
/**
* wide char version of BufPrintf
*/
wchar_t * BufWPrintf(wchar_t *buf, int& len, PRINTF_FORMAT_STRING const wchar_t *fmt, ...);
//--------------------------------------------------------------------------------------------------------------
/**
* convenience function that prints an int into a static wchar_t*
*/
const wchar_t * NumAsWString( int val );
//--------------------------------------------------------------------------------------------------------------
/**
* convenience function that prints an int into a static char*
*/
const char * NumAsString( int val );
//--------------------------------------------------------------------------------------------------------------
/**
* convenience function that composes a string into a static char*
*/
char * SharedVarArgs(PRINTF_FORMAT_STRING const char *format, ...);
#include "tier0/memdbgoff.h"
#endif // SHARED_UTIL_H
@@ -1,54 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//-------------------------------------------------------------
// File: cs_achievement_constants.h
// Desc: Declare contants used by achievements (mostly) in one location for simpler tweaking
// Author: Peter Freese <peter@hiddenpath.com>
// Date: 2009/03/11
// Copyright: © 2009 Hidden Path Entertainment
//-------------------------------------------------------------
#ifndef CS_ACHIEVEMENT_CONSTANTS_H
#define CS_ACHIEVEMENT_CONSTANTS_H
#ifdef _WIN32
#pragma once
#endif
namespace AchievementConsts
{
const int DefaultMinOpponentsForAchievement = 5;
const int KillingSpree_Kills = 5;
const float KillingSpree_WindowTime = 15.0f;
const float KillingSpreeEnder_TimeWindow = 5.0f;
const int KillEnemyTeam_MinKills = 5;
const int LastPlayerAlive_MinPlayersOnTeam = 5;
const int KillsWithMultipleGuns_MinWeapons = 5;
const float BombDefuseCloseCall_MaxTimeRemaining = 1.0f;
const int KillLowDamage_MaxHealthLeft = 5;
const int DamageNoKill_MaxHealthLeftOnKill = 5;
const float BombDefuseNeededKit_MaxTime = 5.0f;
const float FastBombPlant_Time = 25.0f;
const int KillEnemiesWhileBlind_Kills = 1;
const int KillEnemiesWhileBlindHard_Kills = 2;
const int SurviveGrenade_MinDamage = 80;
const int KillWhenAtLowHealth_MaxHealth = 1;
const int GrenadeMultiKill_MinKills = 3;
const int BombMultiKill_MinKills = 5;
const float FastRoundWin_Time = 30.0f;
const int UnstoppableForce_Kills = 10;
const int BreakPropsInRound_Props = 15;
const int HeadshotsInRound_Kills = 5;
const int BreakWindowsInOfficeRound_Windows = 14;
const float FastHostageRescue_Time = 90.0f;
const int SurviveManyAttacks_NumberDamagingPlayers = 5;
const float KillInAir_MinimumHeight = 100.0f; //100-120 is probably best. Also used for killing while in the air
const float KillBombPickup_MaxTime = 3.0f;
const int WinRoundsWithoutBuying_Rounds = 10;
const int ConcurrentDominations_MinDominations = 3;
const int ExtendedDomination_AdditionalKills = 4;
const int SameUniform_MinPlayers = 5;
const int FriendsSameUniform_MinPlayers = 4;
const float KillEnemyNearBomb_MaxDistance = 480.0f;
const int GrenadeDamage_MinDamage = 200;
}
#endif // CS_ACHIEVEMENT_CONSTANTS_H
-210
View File
@@ -1,210 +0,0 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Shared CS definitions.
//
//=============================================================================//
#ifndef CS_ACHIEVEMENTDEFS_H
#define CS_ACHIEVEMENTDEFS_H
#ifdef _WIN32
#pragma once
#endif
//=============================================================================
// Achievement ID Definitions
//=============================================================================
typedef enum
{
CSInvalidAchievement = -1,
// Bomb-related Achievements
CSBombAchievementsStart = 1000, // First bomb-related achievement
CSWinBombPlant,
CSWinBombDefuse,
CSDefuseAndNeededKit,
CSBombDefuseCloseCall,
CSKilledDefuser,
CSPlantBombWithin25Seconds,
CSKillBombPickup,
CSBombMultikill,
CSGooseChase,
CSWinBombPlantAfterRecovery,
CSDefuseDefense,
CSPlantBombsLow,
CSDefuseBombsLow,
CSBombAchievementsEnd, // Must be after last bomb-related achievement
// Hostage-related Achievements
CSHostageAchievementsStart = 2000, // First hostage-related achievement
CSRescueAllHostagesInARound,
CSKilledRescuer,
CSFastHostageRescue,
CSRescueHostagesLow,
CSRescueHostagesMid,
CSHostageAchievmentEnd, // Must be after last hostage-related achievement
// General Kill Achievements
CSKillAchievementsStart = 3000, // First kill-related achievement
CSEnemyKillsLow,
CSEnemyKillsMed,
CSEnemyKillsHigh,
CSSurvivedHeadshotDueToHelmet,
CSKillEnemyReloading,
CSKillingSpree,
CSKillsWithMultipleGuns,
CSHeadshots,
CSAvengeFriend,
CSSurviveGrenade,
CSDominationsLow,
CSDominationsHigh,
CSRevengesLow,
CSRevengesHigh,
CSDominationOverkillsLow,
CSDominationOverkillsHigh,
CSDominationOverkillsMatch,
CSExtendedDomination,
CSConcurrentDominations,
CSKillEnemyBlinded,
CSKillEnemiesWhileBlind,
CSKillEnemiesWhileBlindHard,
CSKillsEnemyWeapon,
CSKillWithEveryWeapon,
CSWinKnifeFightsLow,
CSWinKnifeFightsHigh,
CSKilledDefuserWithGrenade,
CSKillSniperWithSniper,
CSKillSniperWithKnife,
CSHipShot,
CSKillSnipers,
CSKillWhenAtLowHealth,
CSPistolRoundKnifeKill,
CSWinDualDuel,
CSGrenadeMultikill,
CSKillWhileInAir,
CSKillEnemyInAir,
CSKillerAndEnemyInAir,
CSKillEnemyWithFormerGun,
CSKillTwoWithOneShot,
CSSnipeTwoFromSameSpot,
CSKillAchievementEnd, // Must be after last kill-related achievement
// Weapon-related Achievements
CSWeaponAchievementsStart = 4000, // First weapon-related achievement
CSEnemyKillsDeagle,
CSEnemyKillsUSP,
CSEnemyKillsGlock,
CSEnemyKillsP228,
CSEnemyKillsElite,
CSEnemyKillsFiveSeven,
CSEnemyKillsAWP,
CSEnemyKillsAK47,
CSEnemyKillsM4A1,
CSEnemyKillsAUG,
CSEnemyKillsSG552,
CSEnemyKillsSG550,
CSEnemyKillsGALIL,
CSEnemyKillsFAMAS,
CSEnemyKillsScout,
CSEnemyKillsG3SG1,
CSEnemyKillsP90,
CSEnemyKillsMP5NAVY,
CSEnemyKillsTMP,
CSEnemyKillsMAC10,
CSEnemyKillsUMP45,
CSEnemyKillsM3,
CSEnemyKillsXM1014,
CSEnemyKillsM249,
CSEnemyKillsKnife,
CSEnemyKillsHEGrenade,
CSMetaPistol,
CSMetaRifle,
CSMetaSMG,
CSMetaShotgun,
CSMetaWeaponMaster,
CSWeaponAchievementsEnd, // Must be after last weapon-related achievement
// General Achievements
CSGeneralAchievementsStart = 5000, // First general achievement
CSWinRoundsLow,
CSWinRoundsMed,
CSWinRoundsHigh,
CSMoneyEarnedLow,
CSMoneyEarnedMed,
CSMoneyEarnedHigh,
CSGiveDamageLow,
CSGiveDamageMed,
CSGiveDamageHigh,
CSPosthumousGrenadeKill,
CSKillEnemyTeam,
CSLastPlayerAlive,
CSKillEnemyLastBullet,
CSKillingSpreeEnder,
CSDamageNoKill,
CSKillLowDamage,
CSSurviveManyAttacks,
CSLosslessExtermination,
CSFlawlessVictory,
CSDecalSprays,
CSBreakWindows,
CSBreakProps,
CSUnstoppableForce,
CSImmovableObject,
CSHeadshotsInRound,
CSWinPistolRoundsLow,
CSWinPistolRoundsMed,
CSWinPistolRoundsHigh,
CSFastRoundWin,
CSNightvisionDamage,
CSSilentWin,
CSBloodlessVictory,
CSDonateWeapons,
CSWinRoundsWithoutBuying,
CSSameUniform,
CSFriendsSameUniform,
CSCauseFriendlyFireWithFlashbang,
CSWinClanMatch,
CSCollectHolidayGifts,
CSGeneralAchievementsEnd, // Must be after last general achievement
CSWinMapAchievementsStart = 6000,
CSWinMapCS_ASSAULT,
CSWinMapCS_COMPOUND,
CSWinMapCS_HAVANA,
CSWinMapCS_ITALY,
CSWinMapCS_MILITIA,
CSWinMapCS_OFFICE,
CSWinMapDE_AZTEC,
CSWinMapDE_CBBLE,
CSWinMapDE_CHATEAU,
CSWinMapDE_DUST,
CSWinMapDE_DUST2,
CSWinMapDE_INFERNO,
CSWinMapDE_NUKE,
CSWinMapDE_PIRANESI,
CSWinMapDE_PORT,
CSWinMapDE_PRODIGY,
CSWinMapDE_TIDES,
CSWinMapDE_TRAIN,
CSWinMapAchievementsEnd //Must be after last map-based achievement
} eCSAchievementType;
#endif // CS_ACHIEVEMENTDEFS_H

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