this got me interested because i want to let fakeclients DO something. I guess its vital to run this but the question is , IS it really built in? Why do i wonder about this?
1. It is used on normal clients
2. it is used for prediction matters (client.dll)
3. The function itself is coded, while in HL1 this was a built in engine function
THough the arguments of the function is not clear to me yet, let me share the information i have:
"PlayerRunCommand" is found in the following files:
src\dlls\hl2_dll\hl2_player.cpp
src\dlls\hl2_dll\hl2_player.h
src\dlls\player.cpp
src\dlls\player.h
Contents of hl2_player.cpp
Code:
void CHL2_Player::PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper)
{
// Handle FL_FROZEN.
if ( m_afPhysicsFlags & PFLAG_ONBARNACLE )
{
ucmd->forwardmove = 0;
ucmd->sidemove = 0;
ucmd->upmove = 0;
ucmd->buttons &= ~IN_USE;
}
// Can't use stuff while dead
if ( IsDead() )
{
ucmd->buttons &= ~IN_USE;
}
//Update our movement information
if ( ( ucmd->forwardmove != 0 ) || ( ucmd->sidemove != 0 ) || ( ucmd->upmove != 0 ) )
{
m_flIdleTime -= TICK_INTERVAL * 2.0f;
if ( m_flIdleTime < 0.0f )
{
m_flIdleTime = 0.0f;
}
m_flMoveTime += TICK_INTERVAL;
if ( m_flMoveTime > 4.0f )
{
m_flMoveTime = 4.0f;
}
}
else
{
m_flIdleTime += TICK_INTERVAL;
if ( m_flIdleTime > 4.0f )
{
m_flIdleTime = 4.0f;
}
m_flMoveTime -= TICK_INTERVAL * 2.0f;
if ( m_flMoveTime < 0.0f )
{
m_flMoveTime = 0.0f;
}
}
//Msg("Player time: [ACTIVE: %f]\t[IDLE: %f]\n", m_flMoveTime, m_flIdleTime );
BaseClass::PlayerRunCommand( ucmd, moveHelper );
}
contents of player.cpp
It gets called a few times in other functions
Code:
//-----------------------------------------------------------------------------
// Purpose:
// Input : *ucmd -
// *moveHelper -
//-----------------------------------------------------------------------------
void CBasePlayer::PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper)
{
m_touchedPhysObject = false;
if ( pl.fixangle == FIXANGLE_NONE)
{
VectorCopy ( ucmd->viewangles, pl.v_angle );
}
// Handle FL_FROZEN.
// Prevent player moving for some seconds after New Game, so that they pick up everything
if( GetFlags() & FL_FROZEN ||
(developer.GetInt() == 0 && gpGlobals->eLoadType == MapLoad_NewGame && gpGlobals->curtime < 3.0 ) )
{
ucmd->forwardmove = 0;
ucmd->sidemove = 0;
ucmd->upmove = 0;
ucmd->buttons = 0;
ucmd->impulse = 0;
VectorCopy ( pl.v_angle, ucmd->viewangles );
}
PlayerMove()->RunCommand(this, ucmd, moveHelper);
}
The current conclusion i can think off, is that the function has a "UserCmdList" (user command list), a set of properties that have to be done(?). And a set of properties for moving around... (MoveHelper)
let me search for the definitions on the .h files (player.h, hl2_player.h)
hl2_player.h (as part of class HL2_Player : public cBasePlayer)
Code:
virtual void PlayerRunCommand( CUserCmd *ucmd, IMoveHelper *moveHelper);
and for player.h (as part of class cBasePlayer)
Code:
// Run a user command. The default implementation calls ::PlayerRunCommand. In TF, this controls a vehicle if
// the player is in one.
virtual void PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper);
both have 'CUserCMD' and 'IMovehelper'
I see for both there are files in game_shared... usercmd.h and imovehelper.h
content of imovehelper.h
Code:
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IMOVEHELPER_H
#define IMOVEHELPER_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
enum PLAYER_ANIM;
class IPhysicsSurfaceProps;
class Vector;
struct model_t;
struct cmodel_t;
struct vcollide_t;
class CGameTrace;
enum soundlevel_t;
//-----------------------------------------------------------------------------
// Purpose: Identifies how submerged in water a player is.
//-----------------------------------------------------------------------------
enum
{
WL_NotInWater=0,
WL_Feet,
WL_Waist,
WL_Eyes
};
//-----------------------------------------------------------------------------
// An entity identifier that works in both game + client dlls
//-----------------------------------------------------------------------------
typedef CBaseHandle EntityHandle_t;
#define INVALID_ENTITY_HANDLE INVALID_EHANDLE_INDEX
//-----------------------------------------------------------------------------
// Functions the engine provides to IGameMovement to assist in its movement.
//-----------------------------------------------------------------------------
class IMoveHelper
{
public:
// Call this to set the singleton
static IMoveHelper* GetSingleton( ) { return sm_pSingleton; }
// Methods associated with a particular entity
virtual char const* GetName( EntityHandle_t handle ) const = 0;
// Adds the trace result to touch list, if contact is not already in list.
virtual void ResetTouchList( void ) = 0;
virtual bool AddToTouched( const CGameTrace& tr, const Vector& impactvelocity ) = 0;
virtual void ProcessImpacts( void ) = 0;
// Numbered line printf
virtual void Con_NPrintf( int idx, char const* fmt, ... ) = 0;
// These have separate server vs client impementations
virtual void StartSound( const Vector& origin, int channel, char const* sample, float volume, soundlevel_t soundlevel, int fFlags, int pitch ) = 0;
virtual void StartSound( const Vector& origin, const char *soundname ) = 0;
virtual void PlaybackEventFull( int flags, int clientindex, unsigned short eventindex, float delay, Vector& origin, Vector& angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ) = 0;
// Apply falling damage to m_pHostPlayer based on m_pHostPlayer->m_flFallVelocity.
virtual bool PlayerFallingDamage( void ) = 0;
// Apply falling damage to m_pHostPlayer based on m_pHostPlayer->m_flFallVelocity.
virtual void PlayerSetAnimation( PLAYER_ANIM playerAnim ) = 0;
virtual IPhysicsSurfaceProps *GetSurfaceProps( void ) = 0;
virtual bool IsWorldEntity( const CBaseHandle &handle ) = 0;
protected:
// Inherited classes can call this to set the singleton
static void SetSingleton( IMoveHelper* pMoveHelper ) { sm_pSingleton = pMoveHelper; }
// Clients shouldn't call delete directly
virtual ~IMoveHelper() {}
// The global instance
static IMoveHelper* sm_pSingleton;
};
//-----------------------------------------------------------------------------
// Add this to the CPP file that implements the IMoveHelper
//-----------------------------------------------------------------------------
#define IMPLEMENT_MOVEHELPER() \
IMoveHelper* IMoveHelper::sm_pSingleton = 0
//-----------------------------------------------------------------------------
// Call this to set the singleton
//-----------------------------------------------------------------------------
inline IMoveHelper* MoveHelper( )
{
return IMoveHelper::GetSingleton();
}
#endif // IMOVEHELPER_H
i still can't make a thing out of it? Some kind of helper to know / get information about the player / entity attached to it? (any movable entity?)
and now the usercmd.h
Code:
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined( USERCMD_H )
#define USERCMD_H
#ifdef _WIN32
#pragma once
#endif
#include "vector.h"
#include "utlvector.h"
#include "imovehelper.h"
class bf_read;
class bf_write;
class CEntityGroundContact
{
public:
int entindex;
float minheight;
float maxheight;
};
class CUserCmd
{
public:
CUserCmd()
{
Reset();
}
virtual ~CUserCmd() { };
void Reset()
{
command_number = 0;
tick_count = 0;
viewangles.Init();
forwardmove = 0.0f;
sidemove = 0.0f;
upmove = 0.0f;
buttons = 0;
impulse = 0;
weaponselect = 0;
weaponsubtype = 0;
random_seed = 0;
mousedx = 0;
mousedy = 0;
hasbeenpredicted = false;
#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL )
entitygroundcontact.RemoveAll();
#endif
}
CUserCmd& operator =( const CUserCmd& src )
{
if ( this == &src )
return *this;
command_number = src.command_number;
tick_count = src.tick_count;
viewangles = src.viewangles;
forwardmove = src.forwardmove;
sidemove = src.sidemove;
upmove = src.upmove;
buttons = src.buttons;
impulse = src.impulse;
weaponselect = src.weaponselect;
weaponsubtype = src.weaponsubtype;
random_seed = src.random_seed;
mousedx = src.mousedx;
mousedy = src.mousedy;
hasbeenpredicted = src.hasbeenpredicted;
#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL )
entitygroundcontact = src.entitygroundcontact;
#endif
return *this;
}
// For matching server and client commands for debugging
int command_number;
// the tick the client created this command
int tick_count;
// Player instantaneous view angles.
QAngle viewangles;
// Intended velocities
// forward velocity.
float forwardmove;
// sideways velocity.
float sidemove;
// upward velocity.
float upmove;
// Attack button states
int buttons;
// Impulse command issued.
byte impulse;
// Current weapon id
int weaponselect;
int weaponsubtype;
int random_seed; // For shared random functions
short mousedx; // mouse accum in x from create move
short mousedy; // mouse accum in y from create move
// Client only, tracks whether we've predicted this command at least once
bool hasbeenpredicted;
// Back channel to communicate IK state
#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL )
CUtlVector< CEntityGroundContact > entitygroundcontact;
#endif
};
void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from );
void WriteUsercmd( bf_write *buf, CUserCmd *to, CUserCmd *from );
#endif // USERCMD_H
This looks mor einteresting, about moving, and such for clients. Yet, does this still aply for bots? Or do we have to create our own function for this? Its so much code i can't understand it at once yet. But maybe someone can help me with this, and with this forum thread we can figure this out actively (instead of all trying to figure it out ourselves, alone, in a dark space, with one computer monitor
)