mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
upload "kind" alien swarm
This commit is contained in:
@@ -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.
|
||||
//
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Client-server neutral effects interface
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
|
||||
@@ -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() );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
|
||||
@@ -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,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.
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
|
||||
+579
-207
File diff suppressed because it is too large
Load Diff
+57
-61
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
|
||||
+751
-901
File diff suppressed because it is too large
Load Diff
+69
-109
@@ -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
|
||||
@@ -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
|
||||
|
||||
+67
-1073
File diff suppressed because it is too large
Load Diff
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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 :
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 )
|
||||
|
||||
@@ -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 ) \
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+349
-313
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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())
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
|
||||
+76
-109
@@ -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
@@ -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
|
||||
|
||||
@@ -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( ¬Used );
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
|
||||
+51
-50
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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 ];
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user