Quake 4 integrated with DoomRTX

This commit is contained in:
Justin Marshall
2026-05-09 22:10:40 -07:00
parent 8c4a087aa9
commit d37f87e493
436 changed files with 277587 additions and 10254 deletions
File diff suppressed because it is too large Load Diff
+416
View File
@@ -0,0 +1,416 @@
//----------------------------------------------------------------
// Vehicle.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#ifndef __GAME_VEHICLE_H__
#define __GAME_VEHICLE_H__
class rvVehiclePosition {
public:
rvVehiclePosition( void );
virtual ~rvVehiclePosition( void );
usercmd_t mInputCmd;
idAngles mInputAngles;
usercmd_t mOldInputCmd;
idAngles mOldInputAngles;
int mOldInputFlags;
int mCurrentWeapon;
idEntityPtr<idActor> mDriver;
idEntityPtr<rvVehicle> mParent;
rvVehiclePartList_t mParts;
rvVehiclePartList_t mWeapons;
idVec3 mEyeOrigin;
idMat3 mEyeAxis;
jointHandle_t mEyeJoint;
idVec3 mEyeOffset;
idMat3 mEyeJointTransform;
idAngles mDeltaEyeAxisScale;
int mEyeJointAxisMap[3];
int mEyeJointDirMap[3];
idMat3 mAxisOffset;
jointHandle_t mDriverJoint;
idVec3 mDriverOffset;
idMat3 mDriverJointTransform;
idAngles mDeltaDriverAxisScale;
int mDriverJointAxisMap[3];
int mDriverJointDirMap[3];
idVec3 mExitPosOffset;
idMat3 mExitAxisOffset;
idStr mDriverAnim;
idStr mInternalSurface;
struct positionFlags_s {
bool inputValid :1;
bool engine :1;
bool driverVisible :1;
bool depthHack :1;
bool internalView :1;
bool bindDriver :1;
bool stalled :1;
} fl;
void Init ( rvVehicle* parent, const idDict& args );
int AddPart ( const idTypeInfo &classdef, const idDict& args );
rvVehiclePart* GetPart ( int partIndex );
bool IsOccupied ( void ) const;
bool IsEngine ( void ) const;
bool SetDriver ( idActor* driver );
void SetInput ( const usercmd_t& cmd, const idAngles& newAngles );
void GetInput ( usercmd_t& cmd, idAngles& newAngles ) const;
bool EjectDriver ( bool force = false );
void RunPrePhysics ( void );
void RunPostPhysics ( void );
void SelectWeapon ( int weapon );
void UpdateHUD ( idUserInterface* gui );
void UpdateCursorGUI ( idUserInterface* gui );
void UpdateInternalView ( bool force = false );
virtual idMat3 GetAxis ( void ) const;
virtual idVec3 GetOrigin ( const idVec3& offset = vec3_zero ) const;
const idVec3& GetEyeOrigin ( void ) const;
const idMat3& GetEyeAxis ( void ) const;
rvVehicle* GetParent ( void ) const;
idActor* GetDriver ( void ) const;
void Save ( idSaveGame* savefile ) const;
void Restore ( idRestoreGame* savefile );
void WriteToSnapshot ( idBitMsgDelta &msg ) const;
void ReadFromSnapshot ( const idBitMsgDelta &msg );
void GetEyePosition ( idVec3& origin, idMat3& axis ) const;
void GetDriverPosition ( idVec3& origin, idMat3& axis ) const;
void GetPosition ( const jointHandle_t jointHandle, const idVec3& offset, const idMat3& jointTransform, const idAngles& scale, const int axisMap[], const int dirMap[], idVec3& origin, idMat3& axis ) const;
void FireWeapon ( void );
rvVehicleWeapon * GetWeapon ( int weaponIndex );
rvVehicleWeapon * GetActiveWeapon ( void );
private:
void SetParts ( const idDict& args );
void ActivateParts ( bool active );
int mSoundPart;
float mSoundMaxSpeed;
};
typedef struct rvVehicleFuncs_s {
rvScriptFuncUtility enter; // script to run when the vehicle becomes occupied
rvScriptFuncUtility exit; // script to run when the vehicle becomes unoccupied
} rvVehicleFuncs_t;
class rvVehicle : public idActor {
public:
CLASS_PROTOTYPE( rvVehicle );
rvVehicle ( void );
~rvVehicle ( void );
void Spawn ( void );
void Think ( void );
bool Give ( const char *statname, const char *value );
virtual void Hide ( void );
virtual void Show ( void );
void ClientPredictionThink ( void );
void WriteToSnapshot ( idBitMsgDelta &msg ) const;
void ReadFromSnapshot ( const idBitMsgDelta &msg );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
virtual void Damage ( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
virtual void Killed ( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual void AddDamageEffect ( const trace_t &collision, const idVec3 &velocity, const char *damageDefName, idEntity* inflictor );
virtual bool GetPhysicsToVisualTransform ( idVec3 &origin, idMat3 &axis ) { return false; }
virtual const idMat3& GetAxis ( int id = 0 ) const;
virtual const idVec3& GetOrigin ( int id = 0 ) const;
virtual int AddDriver ( int position, idActor* driver );
virtual bool RemoveDriver ( int position, bool force = false );
virtual void EjectAllDrivers ( bool force = false );
rvVehiclePosition* GetPosition ( int index );
const rvVehiclePosition* GetPosition ( int index ) const;
int GetPositionIndex ( const rvVehiclePosition* position ) const;
int GetNumPositions ( void ) const;
int GetNumDrivers ( void ) const;
bool HasOpenPositions ( void ) const;
bool Collide ( const trace_t &collision, const idVec3 &velocity );
virtual void UpdateState ();
float GetEngineOffTime ( void ) const;
float GetEngineOnTime ( void ) const;
bool IsFlipped ( void ) const;
bool IsFrozen ( void ) const;
bool IsLocked ( void ) const;
bool HasDrivers ( void ) const;
bool IsShootingEnabled ( void ) const;
bool IsMovementEnabled ( void ) const;
void Lock ( void );
void Unlock ( void );
void AutoRight ( idEntity* activator );
virtual bool FindClearExitPoint ( int pos, idVec3& origin, idMat3& axis ) const;
void GetDriverPosition ( int position, idVec3& origin, idMat3& axis );
virtual void GetEyePosition ( int position, idVec3& origin, idMat3& axis );
void DrawHUD ( int position );
idUserInterface* GetHud ( void );
void UpdateCursorGUI ( int position, idUserInterface* ui );
virtual void SetInput ( int position, const usercmd_t& cmd, const idAngles& newAngles );
void GetInput ( int position, usercmd_t& cmd, idAngles& newAngles ) const;
void IssueHazardWarning ( void );
void IssueLockedWarning ( void );
void AddToBounds ( const idVec3& vec );
virtual void UpdateHUD ( idActor* driver, idUserInterface* gui ) {}
float FocusLength ( void ) const { return spawnArgs.GetFloat("focusLength_enter", "60"); }
bool IsAutoCorrecting ( void ) const { return autoCorrectionBegin != 0; }
bool IsStalled ( void ) const { return vfl.stalled; }
void OnEnter ( void ) { funcs.enter.CallFunc( NULL ); fl.exitedVehicle=false; };
void OnExit ( void ) { if ( !fl.exitedVehicle ) { fl.exitedVehicle=true; funcs.exit.CallFunc( NULL );} };
bool IsStrafing ( void ) const { return vfl.strafe; }
// void PlayAnim ( int channel, const char *name, int blendFrames );
virtual void GuidedProjectileIncoming( idGuidedProjectile * projectile );
protected:
void SelectWeapon ( int weapon );
void UpdateDrivers ( int delta );
virtual void UpdateHUD ( int position, idUserInterface* gui );
void SetPositions ( void );
void SetCombatModel ( void );
void LinkCombat ( void );
// twhitaker:
friend class rvVehicleDriver;
virtual void RunPrePhysics ( void ) { }
virtual void RunPostPhysics ( void ) { }
idList<rvVehiclePosition> positions;
int drivers;
idUserInterface * hud;
float crashSpeedSmall;
float crashSpeedMedium;
float crashSpeedLarge;
idStr crashDamage;
rvClientEffectPtr crashEffect;
int crashNextSound;
int crashTime;
float autoRightDir;
bool autoRight;
// twhitaker: for rvVehicleDriver, to avoid getting stuck.
unsigned autoCorrectionBegin; // time when obstacle avoidance state began (0 if not correcting)
struct vehicleFlags_s {
bool forward :1;
bool backward :1;
bool left :1;
bool right :1;
bool driver :1;
bool locked :1;
bool godmode :1;
bool frozen :1;
bool disableWeapons :1;
bool disableMovement :1;
bool scripted :1;
bool endWithIdle :1;
bool flipEject :1;
bool dead :1;
bool strafe :1;
bool missileWarningOn :1;
bool stalled :1;
} vfl;
float damageStaticChance;
// Shields
float shieldMaxHealth;
idInterpolate<int> shieldHealth;
int shieldHitTime;
float shieldRegenTime;
int shieldRegenDelay;
idClipModel* shieldModel;
int healthRegenDelay;
int healthRegenRate;
idInterpolate<int> healthRegenAmount;
int hazardWarningTime;
int lockWarningTime;
int healthMax;
int healthLow;
int godModeDamage;
int cachedContents;
rvVehicleFuncs_t funcs;
float crashVelocitySmall;
float crashVelocityMedium;
float crashVelocityLarge;
bool alwaysImpactDamage;
void UpdateIncomingProjectiles( void );
public:
idList< idEntityPtr< idGuidedProjectile > > incomingProjectiles;
private:
void Event_Lock ( bool locked );
void Event_IsLocked ( void );
void Event_EnableWeapon ( void );
void Event_DisableWeapon ( void );
void Event_EnableMovement ( void );
void Event_DisableMovement ( void );
void Event_EnableClip ( void );
void Event_DisableClip ( void );
void Event_Activate ( idEntity* activator );
void Event_LaunchProjectiles ( const idList<idStr>* parms );
void Event_SetScript ( const char* scriptName, const char* funcName );
void Event_SetHealth ( float health );
void Event_HUDShockWarningOff( void );
void Event_StalledRestart ( float shield, float damage );
void Event_GetViewAngles ( void );
virtual void OnDeath ( void ) { }
stateResult_t State_Wait_Driver ( int blendFrames );
CLASS_STATES_PROTOTYPE( rvVehicle );
};
/*
===============
rvVehiclePosition inlines
===============
*/
ID_INLINE bool rvVehiclePosition::IsOccupied ( void ) const { return mDriver.IsValid();}
ID_INLINE bool rvVehiclePosition::IsEngine ( void ) const { return fl.engine; }
ID_INLINE const idVec3& rvVehiclePosition::GetEyeOrigin ( void ) const { return mEyeOrigin; }
ID_INLINE const idMat3& rvVehiclePosition::GetEyeAxis ( void ) const { return mEyeAxis; }
ID_INLINE rvVehicle* rvVehiclePosition::GetParent ( void ) const { return mParent; }
ID_INLINE idActor* rvVehiclePosition::GetDriver ( void ) const { return mDriver; }
ID_INLINE rvVehiclePart* rvVehiclePosition::GetPart ( int partIndex ) { return mParts[partIndex]; }
ID_INLINE rvVehicleWeapon* rvVehiclePosition::GetWeapon ( int weaponIndex ){ return ( weaponIndex >= 0 && weaponIndex < mWeapons.Num() ) ? static_cast<rvVehicleWeapon*>(mWeapons[weaponIndex]) : 0; }
ID_INLINE rvVehicleWeapon* rvVehiclePosition::GetActiveWeapon ( void ) { return GetWeapon( mCurrentWeapon ); }
/*
===============
rvVehicle inlines
===============
*/
ID_INLINE bool rvVehicle::IsFlipped( void ) const {
return (( !vfl.flipEject ) ? false :
idMath::Fabs( idMath::AngleNormalize180( renderEntity.axis.ToAngles().roll ) ) > 60.f ||
idMath::Fabs( idMath::AngleNormalize180( renderEntity.axis.ToAngles().pitch ) > 60.0f ));
}
ID_INLINE bool rvVehicle::IsFrozen( void ) const {
return vfl.frozen;
}
ID_INLINE idUserInterface* rvVehicle::GetHud ( void ) {
return hud;
}
ID_INLINE bool rvVehicle::IsLocked ( void ) const {
return vfl.locked || hazardWarningTime != 0;
}
ID_INLINE rvVehiclePosition* rvVehicle::GetPosition ( int index ) {
return &positions[index];
}
ID_INLINE const rvVehiclePosition* rvVehicle::GetPosition ( int index ) const {
return &positions[index];
}
ID_INLINE void rvVehicle::SetInput ( int position, const usercmd_t& cmd, const idAngles& newAngles ) {
GetPosition(position)->SetInput ( cmd, newAngles );
}
ID_INLINE void rvVehicle::GetInput( int position, usercmd_t& cmd, idAngles& newAngles ) const {
GetPosition(position)->GetInput( cmd, newAngles );
}
ID_INLINE bool rvVehicle::HasDrivers ( void ) const {
return drivers > 0;
}
ID_INLINE void rvVehicle::AddToBounds ( const idVec3& vec ) {
renderEntity.bounds.AddPoint ( (vec-renderEntity.origin) * GetPhysics()->GetAxis().Transpose() );
}
ID_INLINE bool rvVehicle::IsShootingEnabled ( void ) const {
return !vfl.disableWeapons;
}
ID_INLINE bool rvVehicle::IsMovementEnabled ( void ) const {
return !vfl.disableMovement;
}
ID_INLINE int rvVehicle::GetNumPositions ( void ) const {
return positions.Num();
}
ID_INLINE int rvVehicle::GetNumDrivers ( void ) const {
return drivers;
}
ID_INLINE bool rvVehicle::HasOpenPositions ( void ) const {
return GetNumPositions() > GetNumDrivers();
}
#endif // __GAME_VEHICLE_H__
+237
View File
@@ -0,0 +1,237 @@
// Vehicle.cpp
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "VehicleAnimated.h"
CLASS_DECLARATION( rvVehicle, rvVehicleAnimated )
END_CLASS
rvVehicleAnimated::rvVehicleAnimated ( void ) {
}
rvVehicleAnimated::~rvVehicleAnimated ( void ) {
SetPhysics( NULL );
}
/*
================
rvVehicleAnimated::Spawn
================
*/
void rvVehicleAnimated::Spawn( void ) {
turnRate = spawnArgs.GetFloat ( "turnRate", "90" );
viewAngles = GetPhysics()->GetAxis ( ).ToAngles ( );
viewAxis = viewAngles.ToMat3();
// Initialize the physics object
physicsObj.SetSelf( this );
physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
physicsObj.SetContents( CONTENTS_BODY );
physicsObj.SetClipMask( MASK_PLAYERSOLID|CONTENTS_VEHICLECLIP );
physicsObj.SetMaxStepHeight( spawnArgs.GetFloat ( "stepheight", "14" ) );
// Start just a tad above the floor
physicsObj.SetOrigin( GetPhysics()->GetOrigin() + idVec3( 0, 0, CM_CLIP_EPSILON ) );
physicsObj.SetMass( spawnArgs.GetFloat( "mass", "100" ) );
physicsObj.SetDelta( vec3_origin );
// Gravity
idVec3 gravity = spawnArgs.GetVector( "gravityDir", "0 0 -1" );
gravity *= g_gravity.GetFloat ( );
physicsObj.SetGravity( gravity );
SetPhysics( &physicsObj );
animator.RemoveOriginOffset( true );
additionalDelta.Zero();
BecomeActive( TH_THINK );
}
/*
================
rvVehicleAnimated::ClientPredictionThink
================
*/
void rvVehicleAnimated::ClientPredictionThink ( void ) {
Think();
}
/*
================
rvVehicleAnimated::Think
================
*/
void rvVehicleAnimated::Think ( void ) {
rvVehicle::Think();
float rate = 0.0f;
usercmd_t& cmd = positions[0].mInputCmd;
idVec3 delta;
if( positions[0].IsOccupied() && !IsFrozen() && IsMovementEnabled() ) {
if (( g_vehicleMode.GetInteger() == 0 && !( cmd.buttons & BUTTON_STRAFE )) || // If we're in the old driving mode and we aren't strafing or...
( g_vehicleMode.GetInteger() != 0 && ( cmd.buttons & BUTTON_STRAFE ))) // If we're in the new driving mode and we are strafing
{
rate = SignZero(cmd.forwardmove) * turnRate;
rate *= idMath::MidPointLerp( 0.0f, 0.9f, 1.0f, idMath::Fabs(cmd.rightmove) / 127.0f );
viewAngles.yaw += Sign(cmd.rightmove) * rate * MS2SEC(gameLocal.GetMSec());
}
}
viewAngles.Normalize360();
animator.GetDelta( gameLocal.time - gameLocal.GetMSec(), gameLocal.time, delta );
delta += additionalDelta;
idStr alignmentJoint;
if ( g_vehicleMode.GetInteger() != 0 && spawnArgs.GetString( "alignment_joint", 0, alignmentJoint ) ) {
idVec3 offset;
idMat3 axis;
GetJointWorldTransform( animator.GetJointHandle( alignmentJoint ), gameLocal.time, offset, axis );
delta *= axis;
} else {
viewAxis = viewAngles.ToMat3() * physicsObj.GetGravityAxis();
delta *= viewAxis;
}
physicsObj.SetDelta( delta );
additionalDelta.Zero();
}
/*
================
rvVehicleAnimated::GetAxis
================
*/
const idMat3& rvVehicleAnimated::GetAxis( int id ) const {
return viewAxis;
}
/*
================
rvVehicleAnimated::WriteToSnapshot
================
*/
void rvVehicleAnimated::WriteToSnapshot( idBitMsgDelta &msg ) const {
rvVehicle::WriteToSnapshot ( msg );
physicsObj.WriteToSnapshot( msg );
msg.WriteFloat( viewAngles[0] );
msg.WriteFloat( viewAngles[1] );
msg.WriteFloat( viewAngles[2] );
}
/*
================
rvVehicleAnimated::ReadFromSnapshot
================
*/
void rvVehicleAnimated::ReadFromSnapshot( const idBitMsgDelta &msg ) {
rvVehicle::ReadFromSnapshot ( msg );
physicsObj.ReadFromSnapshot( msg );
viewAngles[0] = msg.ReadFloat( );
viewAngles[1] = msg.ReadFloat( );
viewAngles[2] = msg.ReadFloat( );
}
/*
================
rvVehicleAnimated::Save
================
*/
void rvVehicleAnimated::Save ( idSaveGame *savefile ) const {
savefile->WriteVec3( storedPosition );
savefile->WriteStaticObject ( physicsObj );
savefile->WriteAngles ( viewAngles );
savefile->WriteFloat ( turnRate );
// why are we writing out the viewAxis here???
savefile->WriteMat3 ( viewAxis );
// TEMP
animator.Save( savefile );
}
/*
================
rvVehicleAnimated::Restore
================
*/
void rvVehicleAnimated::Restore ( idRestoreGame *savefile ) {
savefile->ReadVec3( storedPosition );
physicsObj.SetSelf( this );
physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
savefile->ReadStaticObject ( physicsObj );
RestorePhysics ( &physicsObj );
physicsObj.EnableClip();
savefile->ReadAngles ( viewAngles );
savefile->ReadFloat ( turnRate );
savefile->ReadMat3 ( viewAxis );
// TEMP - restore animator, because it was cleared when loading the AF
animator.Restore( savefile );
animator.GetJoints( &renderEntity.numJoints, &renderEntity.joints );
animator.GetBounds( gameLocal.time, renderEntity.bounds );
// TEMP
additionalDelta.Zero();
}
/*
================
rvVehicleAnimated::GetPhysicsToVisualTransform
================
*/
bool rvVehicleAnimated::GetPhysicsToVisualTransform ( idVec3 &origin, idMat3 &axis ) {
origin = modelOffset;
axis = viewAxis;
return true;
}
/*
================
rvVehicleAnimated::RunPrePhysics
================
*/
void rvVehicleAnimated::RunPrePhysics ( void ) {
storedPosition = physicsObj.GetOrigin();
}
/*
================
rvVehicleAnimated::RunPostPhysics
================
*/
void rvVehicleAnimated::RunPostPhysics ( void ) {
if ( autoCorrectionBegin + 3000 > static_cast<unsigned>( gameLocal.time )) {
autoCorrectionBegin = 0;
idVec3 delta;
idVec3 actualDelta = physicsObj.GetOrigin() - storedPosition;
animator.GetDelta( gameLocal.time - gameLocal.GetMSec(), gameLocal.time, delta );
if ( !autoCorrectionBegin && delta.LengthSqr() * 0.2f > actualDelta.LengthSqr() ) {
autoCorrectionBegin = gameLocal.time;
}
}
}
+49
View File
@@ -0,0 +1,49 @@
//----------------------------------------------------------------
// VehicleAnimated.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#ifndef __GAME_VEHICLEANIMATED_H__
#define __GAME_VEHICLEANIMATED_H__
#include "Vehicle.h"
#include "../physics/Physics_Monster.h"
class rvVehicleAnimated : public rvVehicle {
public:
CLASS_PROTOTYPE( rvVehicleAnimated );
rvVehicleAnimated ( void );
~rvVehicleAnimated ( void );
void Spawn ( void );
void Think ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
virtual const idMat3& GetAxis ( int id = 0 ) const;
void ClientPredictionThink ( void );
void WriteToSnapshot ( idBitMsgDelta &msg ) const;
void ReadFromSnapshot ( const idBitMsgDelta &msg );
virtual bool GetPhysicsToVisualTransform ( idVec3 &origin, idMat3 &axis );
protected:
// twhitaker:
virtual void RunPrePhysics ( void );
virtual void RunPostPhysics ( void );
idVec3 storedPosition;
// end twhitaker:
idPhysics_Monster physicsObj;
idAngles viewAngles;
float turnRate;
idVec3 additionalDelta;
};
#endif // __GAME_VEHICLEANIMATED_H__
@@ -0,0 +1,301 @@
//----------------------------------------------------------------
// VehicleController.cpp
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "VehicleController.h"
#include "Vehicle.h"
/*
=====================
rvVehicleController::rvVehicleController
=====================
*/
rvVehicleController::rvVehicleController ( void ) {
mVehicle = NULL;
//mDriver = NULL;
mPosition = 0;
}
/*
=====================
rvVehicleController::Save
=====================
*/
void rvVehicleController::Save ( idSaveGame *savefile ) const {
mVehicle.Save ( savefile );
savefile->WriteInt ( mPosition );
}
/*
=====================
rvVehicleController::Restore
=====================
*/
void rvVehicleController::Restore ( idRestoreGame *savefile ) {
mVehicle.Restore ( savefile );
savefile->ReadInt ( mPosition );
}
/*
=====================
rvVehicleController::Drive
=====================
*/
bool rvVehicleController::Drive ( rvVehicle* vehicle, idActor* driver ) {
assert ( vehicle && driver );
// Flip the vehicle back over?
if ( vehicle->IsFlipped ( ) ) {
vehicle->AutoRight ( vehicle );
return false;
}
// Add the driver to the vehicle and cache the position it was added.
if ( -1 == (mPosition = vehicle->AddDriver ( 0, driver ) ) ) {
return false;
}
mVehicle = vehicle;
//twhitaker: for scripted callback events
vehicle->OnEnter();
if ( driver->IsType( idPlayer::GetClassType() ) ) {
idPlayer * player = static_cast< idPlayer *>( driver );
if ( player->GetHud() ) {
GetHud()->Activate( true, gameLocal.time );
GetHud()->HandleNamedEvent( "showExitmessage" );
}
}
return true;
}
/*
=====================
rvVehicleController::Eject
=====================
*/
bool rvVehicleController::Eject ( bool force ) {
if ( !GetVehicle() ) {
return true;
}
if ( GetDriver()->IsType( idPlayer::GetClassType() ) ) {
idPlayer * player = static_cast< idPlayer *>( GetDriver() );
if ( player->GetHud() ) {
GetHud()->HandleNamedEvent( "hideExitmessage" );
}
}
if ( mVehicle->RemoveDriver ( GetPosition(), force ) ) {
mVehicle->OnExit();
mVehicle = NULL;
return true;
}
return false;
}
/*
=====================
rvVehicleController::FindClearExitPoint
=====================
*/
bool rvVehicleController::FindClearExitPoint( idVec3& origin, idMat3& axis ) const {
return GetVehicle()->FindClearExitPoint( mPosition, origin, axis );
}
/*
=====================
rvVehicleController::KillVehicles
=====================
*/
void rvVehicleController::KillVehicles ( void ) {
KillEntities( idCmdArgs(), rvVehicle::GetClassType() );
}
/*
=====================
rvVehicleController::DrawHUD
=====================
*/
void rvVehicleController::DrawHUD ( void ) {
assert ( mVehicle );
if ( GetDriver() && GetDriver()->IsType( idPlayer::GetClassType() ) ) {
idPlayer * player = static_cast<idPlayer*>( GetDriver() );
rvVehicleWeapon * weapon = mVehicle->GetPosition( mPosition )->GetActiveWeapon();
if ( weapon ) {
if ( weapon->CanZoom() && player->IsZoomed() && player == gameLocal.GetLocalPlayer() ) {
weapon->GetZoomGui()->Redraw( gameLocal.time );
}
// if ( mVehicle->GetHud() ) {
// mVehicle->GetHud()->SetStateFloat( "tram_heatpct", weapon->GetOverheatPercent());
// mVehicle->GetHud()->SetStateFloat( "tram_overheat", weapon->GetOverheatState());
// }
}
}
mVehicle->DrawHUD ( mPosition );
}
/*
=====================
rvVehicleController::StartRadioChatter
=====================
*/
void rvVehicleController::StartRadioChatter ( void ) {
assert ( mVehicle );
if ( mVehicle->GetHud () ) {
mVehicle->GetHud ()->HandleNamedEvent( "radioChatterUp" );
}
}
/*
=====================
rvVehicleController::StopRadioChatter
=====================
*/
void rvVehicleController::StopRadioChatter ( void ) {
assert ( mVehicle );
if ( mVehicle->GetHud () ) {
mVehicle->GetHud ()->HandleNamedEvent( "radioChatterDown" );
}
}
/*
=====================
rvVehicleController::Give
=====================
*/
void rvVehicleController::Give ( const char* statname, const char* value ) {
if( mVehicle.IsValid() ) {
mVehicle->Give ( statname, value );
}
}
/*
=====================
rvVehicleController::GetEyePosition
=====================
*/
void rvVehicleController::GetEyePosition ( idVec3& origin, idMat3& axis ) const {
if( mVehicle.IsValid() ) {
mVehicle->GetEyePosition ( mPosition, origin, axis );
}
}
/*
=====================
rvVehicleController::GetDriverPosition
=====================
*/
void rvVehicleController::GetDriverPosition ( idVec3& origin, idMat3& axis ) const {
if( mVehicle.IsValid() ) {
mVehicle->GetDriverPosition ( mPosition, origin, axis );
}
}
/*
=====================
rvVehicleController::GetVehicle
=====================
*/
rvVehicle* rvVehicleController::GetVehicle ( void ) const {
return mVehicle;
}
idActor* rvVehicleController::GetDriver ( void ) const {
return (GetVehicle()) ? GetVehicle()->GetPosition(GetPosition())->GetDriver() : NULL;
}
/*
=====================
rvVehicleController::SetInput
=====================
*/
void rvVehicleController::SetInput ( const usercmd_t& cmd, const idAngles &angles ) {
if( mVehicle.IsValid() ) {
mVehicle->SetInput ( mPosition, cmd, angles );
}
}
/*
=====================
rvVehicleController::GetInput
=====================
*/
void rvVehicleController::GetInput( usercmd_t& cmd, idAngles &newAngles ) const {
if( mVehicle.IsValid() ) {
mVehicle->GetInput( mPosition, cmd, newAngles );
}
}
/*
================
rvVehicleController::GetHud
================
*/
idUserInterface* rvVehicleController::GetHud( void ) {
return (IsDriving()) ? mVehicle->GetHud() : NULL;
}
/*
================
rvVehicleController::GetHud
================
*/
const idUserInterface* rvVehicleController::GetHud( void ) const {
return (IsDriving()) ? mVehicle->GetHud() : NULL;
}
/*
================
rvVehicleController::WriteToSnapshot
================
*/
void rvVehicleController::WriteToSnapshot ( idBitMsgDelta &msg ) const {
msg.WriteLong ( mPosition );
msg.WriteLong ( mVehicle.GetSpawnId ( ) );
}
/*
================
rvVehicleController::ReadFromSnapshot
================
*/
void rvVehicleController::ReadFromSnapshot ( const idBitMsgDelta &msg ) {
mPosition = msg.ReadLong ( );
mVehicle.SetSpawnId ( msg.ReadLong ( ) );
}
/*
================
rvVehicleController::UpdateCursorGUI
================
*/
void rvVehicleController::UpdateCursorGUI ( idUserInterface* ui ) {
assert ( mVehicle );
mVehicle->UpdateCursorGUI ( mPosition, ui );
}
/*
================
rvVehicleController::SelectWeapon
================
*/
void rvVehicleController::SelectWeapon ( int weapon ) {
if( mVehicle.IsValid() ) {
mVehicle->GetPosition( mPosition )->SelectWeapon( weapon );
}
}
@@ -0,0 +1,69 @@
//----------------------------------------------------------------
// VehicleController.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#ifndef __GAME_VEHICLECONTROLLER_H__
#define __GAME_VEHICLECONTROLLER_H__
class rvVehicle;
class rvVehiclePosition;
class rvVehicleController {
public:
rvVehicleController ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
bool Drive ( rvVehicle* vehicle, idActor* driver );
bool Eject ( bool force = false );
bool FindClearExitPoint ( idVec3& origin, idMat3& axis ) const;
bool IsDriving ( void ) const;
rvVehicle* GetVehicle ( void ) const;
idActor* GetDriver ( void ) const;
int GetPosition ( void ) const;
void SetInput ( const usercmd_t& cmd, const idAngles &newAngles );
void GetInput ( usercmd_t& cmd, idAngles &newAngles ) const;
idUserInterface* GetHud ( void );
const idUserInterface* GetHud ( void ) const;
void DrawHUD ( void );
void UpdateCursorGUI ( idUserInterface* ui );
void StartRadioChatter ( void );
void StopRadioChatter ( void );
void Give ( const char* statname, const char* value );
void GetEyePosition ( idVec3& origin, idMat3& axis ) const;
void GetDriverPosition ( idVec3& origin, idMat3& axis ) const;
static void KillVehicles ( void );
void WriteToSnapshot ( idBitMsgDelta &msg ) const;
void ReadFromSnapshot ( const idBitMsgDelta &msg );
void SelectWeapon ( int weapon );
protected:
idEntityPtr<rvVehicle> mVehicle;
int mPosition;
};
ID_INLINE bool rvVehicleController::IsDriving ( void ) const {
return mVehicle.IsValid ( );
}
ID_INLINE int rvVehicleController::GetPosition ( void ) const {
return mPosition;
}
#endif // __GAME_VEHICLECONTROLLER_H__
+836
View File
@@ -0,0 +1,836 @@
// VehicleDriver.cpp
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include <cfloat>
const idEventDef VD_ChoosePathTarget( "choosePathTarget", "e", 'e' );
const idEventDef EV_FollowOffset( "followOffset", "v" );
const idEventDef EV_FireWeapon ( "fireWeapon", "ff" );
CLASS_DECLARATION( idActor, rvVehicleDriver )
EVENT( EV_PostSpawn , rvVehicleDriver::Event_PostSpawn )
EVENT( AI_EnterVehicle , rvVehicleDriver::Event_EnterVehicle )
EVENT( AI_ExitVehicle , rvVehicleDriver::Event_ExitVehicle )
EVENT( AI_ScriptedMove , rvVehicleDriver::Event_ScriptedMove )
EVENT( AI_ScriptedDone , rvVehicleDriver::Event_ScriptedDone )
EVENT( AI_ScriptedStop , rvVehicleDriver::Event_ScriptedStop )
EVENT( EV_Activate , rvVehicleDriver::Event_Trigger )
EVENT( EV_Speed , rvVehicleDriver::Event_SetSpeed )
EVENT( EV_FireWeapon , rvVehicleDriver::Event_FireWeapon )
EVENT( AI_FaceEntity , rvVehicleDriver::Event_FaceEntity )
EVENT( AI_LookAt , rvVehicleDriver::Event_LookAt )
EVENT( AI_SetLeader , rvVehicleDriver::Event_SetLeader )
//twhitaker: remove - begin
EVENT( EV_FollowOffset , rvVehicleDriver::Event_SetFollowOffset )
//twhitaker: remove - end
END_CLASS
/*
================
rvVehicleDriver::rvVehicleDriver
================
*/
rvVehicleDriver::rvVehicleDriver ( void ) {
}
/*
================
rvVehicleDriver::Spawn
================
*/
void rvVehicleDriver::Spawn ( void ) {
currentThrottle = 1.0f;
faceTarget = NULL;
lookTarget = NULL;
leader = NULL;
leaderFlags = 0;
decelDistance = 0.0f;
minDistance = 0.0f;
fireEndTime = 0.0f;
isMoving = false;
avoidingLeader = false;
pathingMode = VDPM_Random;
pathingOrigin = vec3_origin;
pathingEntity = NULL;
SIMDProcessor->Memset( &pathTargetInfo, 0, sizeof( PathTargetInfo ) );
SIMDProcessor->Memset( &lastPathTargetInfo, 0, sizeof( PathTargetInfo ) );
PostEventMS( &EV_PostSpawn, 0 );
}
/*
================
rvVehicleDriver::Think
================
*/
void rvVehicleDriver::Think ( void ) {
if ( !IsDriving() ) {
if ( leader ) {
leader->SetLeaderHint( VDLH_Continue );
leader = NULL;
}
return;
}
if ( pathTargetInfo.node ) {
float targetDistance = 0.0f;
float dotForward = 0.0f;
float dotRight = 0.0f;
float desiredThrottle = 1.0f;
idEntity* currentPathTarget = pathTargetInfo.node;
rvVehicle* vehicle = vehicleController.GetVehicle();
idMat3 vehicleAxis = vehicle->GetAxis();
idVec3 targetOrigin;
idVec3 dirToTarget;
usercmd_t cmd;
idAngles ang;
// We may want to hack the auto correction variable based on what the state of the driver and the driver's leader.
UpdateAutoCorrection();
if ( vehicle->IsAutoCorrecting( ) ) {
if ( lastPathTargetInfo.node ) {
currentPathTarget = lastPathTargetInfo.node;
}
if ( g_debugVehicleDriver.GetInteger() != 0 ) {
gameRenderWorld->DebugBounds( colorCyan, vehicle->GetPhysics()->GetAbsBounds().Expand( 30 ) );
}
}
// Touch all the triggers that the vehicle touches
vehicle->TouchTriggers();
GetTargetInfo( currentPathTarget, &targetOrigin, &dirToTarget, &dotForward, &dotRight, &targetDistance );
// The primary purpose of the following portions of code is to set the desiredThrottle variable.
if ( IsMoving() ) {
// if we're slowing down lerp throttle.
if ( pathTargetInfo.throttle < lastPathTargetInfo.throttle ) {
desiredThrottle = idMath::Lerp( lastPathTargetInfo.throttle, pathTargetInfo.throttle, targetDistance / pathTargetInfo.initialDistance );
} else {
// otherwise accelerate rapidly or maintain throttle.
desiredThrottle = pathTargetInfo.throttle;
}
// we could potentially be a leader, so check the leader flags
if ( leaderFlags & VDLH_SlowDown ) {
desiredThrottle = 0.1f;
} else if ( leaderFlags & VDLH_Wait ) {
desiredThrottle = 0.0f;
}
// if we're following a someone ...
if ( leader ) {
bool canSeeLeader = vehicle->CanSee( leader->vehicleController.GetVehicle(), false );
float distanceToLeader = ( leader->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin() ).Length();
avoidingLeader = false;
// update the leaders flags based on distance and visibility
if ( !canSeeLeader ) {
// if we can't see the leader, tell him to stop
leader->SetLeaderHint( VDLH_Wait );
} else if ( distanceToLeader > decelDistance ) {
// if we're too far from the leader, tell him to slow down
leader->SetLeaderHint( VDLH_SlowDown );
} else {
// we're within range of the leader so let him move along at a normal rate
leader->SetLeaderHint( VDLH_Continue );
// if we're too close to the leader, we need to slow ourself down
if ( distanceToLeader < minDistance ) {
desiredThrottle = -0.2f;
avoidingLeader = true;
}
}
}
// the desiredThrottle variable should be set at this point, the only other thing that could change it
// would be in SimulateKeys, if the dotForward < 0.
}
vehicleController.GetInput( cmd, ang );
// Simulate Input
SimulateKeys( cmd, dotForward, dotRight, desiredThrottle * currentThrottle, targetDistance );
SimulateMouseMove( cmd );
SimulateButtons( cmd );
vehicleController.SetInput( cmd, ang );
// Node Transition
if( (!vehicle->IsAutoCorrecting() || !IsValidPathNode( currentPathTarget )) && isMoving ) {
idVec3 point = targetOrigin - dirToTarget * pathTargetInfo.minDistance;
if( vehicle->GetPhysics()->GetAbsBounds().ContainsPoint( point ) ) {
int numTargets = NumValidTargets( currentPathTarget );
lastPathTargetInfo = pathTargetInfo;
//TODO: ponder - should I be setting lastPathTargetInfo.node to pathTargetInfo.node or currentPathTarget???
if( numTargets ) {
Event_ScriptedMove( ChooseNextNode( currentPathTarget ), 0, 0 );
}
if( lastPathTargetInfo.exitVehicle ) {
Event_ExitVehicle( true );
} else if( lastPathTargetInfo.throttle == 0 || !numTargets ) {
Event_ScriptedStop();
if( !numTargets ) {
pathTargetInfo.node = NULL;
}
}
// Debug Output
if ( g_debugVehicleDriver.GetInteger( ) != 0 ) {
gameRenderWorld->DebugBounds( colorRed, idBounds(idVec3(-5, -5, -5), idVec3(5, 5, 5)), point );
}
}
}
} else { // no path
float dotForward;
float dotRight;
usercmd_t cmd;
idAngles ang;
vehicleController.GetInput( cmd, ang );
if ( GetTargetInfo( faceTarget, NULL, NULL, &dotForward, &dotRight, NULL) ) {
if( ( 1.0f - dotForward ) < VECTOR_EPSILON ) {
Event_ScriptedStop();
} else {
SimulateKeys( cmd, dotForward, dotRight, 0.0f );
}
}
SimulateMouseMove( cmd );
SimulateButtons( cmd );
vehicleController.SetInput( cmd, ang );
}
}
/*
================
rvVehicleDriver::GetTargetInfo
================
*/
bool rvVehicleDriver::GetTargetInfo( const idEntity* target, idVec3* targetOrigin, idVec3* dirToTarget, float* dotForward, float* dotRight, float* distance ) const {
if( !target || !IsDriving() ) {
return false;
}
idMat3 vehicleAxis = vehicleController.GetVehicle()->GetAxis();
idVec3 vehicleOrigin = vehicleController.GetVehicle()->GetOrigin();
idVec3 forward = vehicleAxis[ 0 ];
idVec3 localTargetOrigin = target->GetPhysics()->GetOrigin();
localTargetOrigin.z = vehicleOrigin.z;// Find way to include vehicleAxis here
idVec3 vectorToTarget = localTargetOrigin - vehicleOrigin;
idVec3 localDirToTarget = vectorToTarget;
float distToTarget = localDirToTarget.Normalize();
if( targetOrigin ) {
*targetOrigin = localTargetOrigin;
}
if( dirToTarget ) {
*dirToTarget = localDirToTarget;
}
if( distance ) {
*distance = distToTarget;
}
if( dotForward ) {
*dotForward = localDirToTarget * forward;
}
if( dotRight ) {
*dotRight = localDirToTarget * vehicleAxis[ 1 ];
}
// Debug help
if ( g_debugVehicleDriver.GetInteger( ) != 0 ) {
idStr temp;
const idVec3 & origin = GetPhysics()->GetOrigin();
gameRenderWorld->DebugLine( colorBlue, origin, target->GetPhysics()->GetOrigin() );
gameRenderWorld->DebugBounds( colorBlue, GetPhysics()->GetAbsBounds() );
gameRenderWorld->DebugBounds( colorBlue, target->GetPhysics()->GetBounds(), target->GetPhysics()->GetOrigin() );
gameRenderWorld->DrawText( target->GetName(), vehicleOrigin + vectorToTarget + vehicleAxis[2] * 5.0f, 1.0f, colorBlue, gameLocal.GetLocalPlayer()->viewAxis );
gameRenderWorld->DrawText( idStr( "State: " ) + LeaderHintsString( leaderFlags, temp ), origin, 1.0f, colorBlue, gameLocal.GetLocalPlayer()->viewAxis );
if ( vehicleController.GetVehicle()->IsAutoCorrecting() ) {
gameRenderWorld->DebugBounds( colorPurple, vehicleController.GetVehicle()->GetPhysics()->GetAbsBounds() );
gameRenderWorld->DrawText( "Auto-Correcting", vehicleOrigin, 1.0f, colorPurple, gameLocal.GetLocalPlayer()->viewAxis );
}
if ( pathTargetInfo.node && g_debugVehicleDriver.GetInteger( ) == 2 ) {
gameRenderWorld->DebugBounds( colorOrange, pathTargetInfo.node->GetPhysics()->GetBounds() );
for ( int ix = 0; ix < pathTargetInfo.node->targets.Num(); ix++ ) {
gameRenderWorld->DebugLine( colorOrange, pathTargetInfo.node->GetPhysics()->GetOrigin(), pathTargetInfo.node->targets[ ix ]->GetPhysics()->GetOrigin(), 0, true );
}
}
if ( leader ) {
idVec4 & color = colorGreen;
if ( leader->GetLeaderHint() & VDLH_SlowDown ) {
color = colorYellow;
} else if ( leader->GetLeaderHint() & VDLH_Wait ) {
color = colorRed;
}
idStr str = idStr( "decel_distance: " ) + idStr( decelDistance ) + idStr( "\nmin_distance: " ) + idStr( minDistance );
gameRenderWorld->DrawText( str, leader->GetPhysics()->GetOrigin(), 1.0f, color, gameLocal.GetLocalPlayer()->viewAxis, 1, 0, true );
gameRenderWorld->DebugLine( color, GetPhysics()->GetOrigin(), leader->GetPhysics()->GetOrigin(), 0, true );
gameRenderWorld->DebugBounds( color, leader->vehicleController.GetVehicle()->GetPhysics()->GetAbsBounds(), vec3_origin, 0, true );
gameRenderWorld->DebugCircle( color, leader->GetPhysics()->GetOrigin(), idVec3( 0, 0, 1 ), decelDistance, 10, 0, true );
gameRenderWorld->DebugCircle( color, leader->GetPhysics()->GetOrigin(), idVec3( 0, 0, 1 ), minDistance, 10, 0, true );
}
}
return true;
}
/*
================
rvVehicleDriver::ChooseNextNode
================
*/
idEntity* rvVehicleDriver::ChooseNextNode( idEntity* target ) {
if( !target ) {
return NULL;
}
if( func.Init( target->spawnArgs.GetString( "call_nextNode" )) <= 0 ) {
idEntity * best = NULL;
float bestDist;
switch ( pathingMode ) {
case VDPM_MoveTo:
bestDist = FLT_MAX;
for ( int i = target->targets.Num() - 1; i; i -- ) {
float distance = ( target->targets[ i ]->GetPhysics()->GetOrigin() - pathingOrigin ).LengthSqr();
if ( bestDist > distance ) {
bestDist = distance;
best = target->targets[ i ];
}
}
break;
case VDPM_MoveAway:
bestDist = FLT_MIN;
for ( int i = target->targets.Num() - 1; i; i -- ) {
float distance = ( target->targets[ i ]->GetPhysics()->GetOrigin() - pathingOrigin ).LengthSqr();
if ( bestDist < distance ) {
bestDist = distance;
best = target->targets[ i ];
}
}
case VDPM_Custom:
if ( pathingEntity ) {
// best = pathingCallback( target );
pathingEntity->ProcessEvent( &VD_ChoosePathTarget, target );
best = gameLocal.program.GetReturnedEntity();
}
}
return ( best ) ? best : RandomValidTarget( target );
}
func.InsertEntity( this, 0 );
func.CallFunc( &spawnArgs );
func.RemoveIndex( 0 );
return ( func.ReturnsAVal()) ? gameLocal.FindEntity( spawnArgs.GetString( func.GetReturnKey() )) : const_cast<idEntity*>( target );
}
/*
================
rvVehicleDriver::SimulateButtons
================
*/
void rvVehicleDriver::SimulateButtons( usercmd_t& cmd ) {
cmd.buttons = (fireEndTime >= gameLocal.time) ? BUTTON_ATTACK : 0;
}
/*
================
rvVehicleDriver::SimulateMouseMove
================
*/
void rvVehicleDriver::SimulateMouseMove( usercmd_t& cmd ) {
idVec3 origin;
idMat3 axis;
idVec3 vectorToTarget;
idAngles anglesToTarget;
idAngles turretAngles;
idAngles deltaAngles;
if( !lookTarget ) {
for( int ix = 0; ix < 3; ++ix ) {
cmd.angles[ix] = 0;
}
return;
}
vehicleController.GetEyePosition( origin, axis );
vectorToTarget = (lookTarget->GetPhysics()->GetOrigin() - origin).ToNormal();
anglesToTarget = vectorToTarget.ToAngles().Normalize360();
turretAngles = (axis[0]).ToAngles().Normalize360();
deltaAngles = (anglesToTarget - turretAngles).Normalize180();
for( int ix = 0; ix < deltaAngles.GetDimension(); ++ix ) {
cmd.angles[ix] += ANGLE2SHORT( deltaAngles[ix] );
}
// Debug Output
if( g_debugVehicleDriver.GetInteger( ) != 0 ) {
gameRenderWorld->DebugLine( colorGreen, origin, origin + anglesToTarget.ToForward() * 100.0f, 17, true );
gameRenderWorld->DebugLine( colorYellow, origin, origin + turretAngles.ToForward() * 100.0f, 17, true );
}
}
/*
================
rvVehicleDriver::SimulateKeys
================
*/
void rvVehicleDriver::SimulateKeys( usercmd_t& cmd, float dotForward, float dotRight, float speed, float distance ) {
rvVehicle * vehicle = vehicleController.GetVehicle();
if( !vehicle ) {
cmd.forwardmove = 0;
cmd.rightmove = 0;
return;
}
cmd.forwardmove = static_cast< signed char >( (!vehicle->IsAutoCorrecting() ? 127.0f : forwardThrustScale) * dotForward * speed );
cmd.rightmove = static_cast< signed char >( ( ( dotForward < 0.0f ) ? rightThrustScale : -rightThrustScale ) * dotRight );
}
/*
================
rvVehicleDriver::SortValid
================
*/
int rvVehicleDriver::SortValid( const void* a, const void* b ) {
idEntityPtr<idEntity> A = *(idEntityPtr<idEntity>*)a;
idEntityPtr<idEntity> B = *(idEntityPtr<idEntity>*)b;
return rvVehicleDriver::IsValidTarget( B ) - rvVehicleDriver::IsValidTarget( A );
}
/*
================
rvVehicleDriver::SortTargetList
================
*/
int rvVehicleDriver::SortTargetList( idEntity* ent ) const {
if( !ent ) {
return 0;
}
int numValidEntities = 0;
idEntity * target;
ent->RemoveNullTargets();
qsort( ent->targets.Ptr(), NumTargets( ent ), ent->targets.TypeSize(), rvVehicleDriver::SortValid );
for( int ix = NumTargets( ent ) - 1; ix >= 0; --ix ) {
target = GetTarget( ent, ix );
if( IsValidTarget( target ) ) {
++numValidEntities;
}
}
return numValidEntities;
}
/*
================
rvVehicleDriver::RandomValidTarget
================
*/
idEntity* rvVehicleDriver::RandomValidTarget( idEntity* ent ) const {
int numValid = NumValidTargets( ent );
return (!numValid) ? NULL : ent->targets[ rvRandom::irand(0, numValid - 1) ];
}
/*
================
rvVehicleDriver::NumValidTargets
================
*/
int rvVehicleDriver::NumValidTargets( idEntity* ent ) const {
return SortTargetList(ent);
}
/*
================
rvVehicleDriver::NumTargets
================
*/
int rvVehicleDriver::NumTargets( const idEntity* ent ) const {
return (ent) ? ent->targets.Num() : 0;
}
/*
================
rvVehicleDriver::GetTarget
================
*/
idEntity* rvVehicleDriver::GetTarget( const idEntity* ent, int index ) const {
return (ent) ? ent->targets[index] : NULL;
}
/*
================
rvVehicleDriver::IsValidPathNode
================
*/
bool rvVehicleDriver::IsValidPathNode( const idEntity* ent ) {
if( !ent ) {
return false;
}
return ent->IsType( idTarget::GetClassType() );
}
/*
================
rvVehicleDriver::IsValidTarget
================
*/
bool rvVehicleDriver::IsValidTarget( const idEntity* ent ) {
return IsValidPathNode( ent ) || ent->IsType( rvVehicle::GetClassType() ) || ent->IsType( idPlayer::GetClassType() );
}
/*
================
rvVehicleDriver::SetLeader
================
*/
bool rvVehicleDriver::SetLeader( idEntity* ent ) {
if ( !ent || !ent->IsType( rvVehicleDriver::GetClassType() ) ) {
return false;
}
leader = static_cast<rvVehicleDriver*>( ent );
minDistance = leader->spawnArgs.GetFloat( "min_distance", "500" );
idStr decel_distance( minDistance * 3.0f );
decelDistance = leader->spawnArgs.GetFloat( "decel_distance", decel_distance );
return true;
}
/*
================
rvVehicleDriver::Event_PostSpawn
================
*/
void rvVehicleDriver::Event_PostSpawn ( void ) {
for ( int i = targets.Num() - 1; i >= 0; i-- ) {
idEntity * ent = targets[ i ].GetEntity();
if ( ent->IsType( rvVehicle::GetClassType() ) ) {
Event_EnterVehicle( ent );
}
}
for ( int i = targets.Num() - 1; i >= 0; i-- ) {
idEntity * ent = targets[ i ].GetEntity();
if ( ent->IsType( idTarget::GetClassType() ) ) {
Event_ScriptedMove( ent, 0, 0 );
}
if ( ent->IsType( rvVehicleDriver::GetClassType() ) ) {
SetLeader( ent );
}
}
}
/*
================
rvVehicleDriver::Event_EnterVehicle
================
*/
void rvVehicleDriver::Event_EnterVehicle ( idEntity * vehicle ) {
if ( vehicle ) {
forwardThrustScale = vehicle->spawnArgs.GetFloat( "driver_forward_thrust", ".75" ) * 127.0f;
rightThrustScale = vehicle->spawnArgs.GetFloat( "driver_right_thrust", "1" ) * 127.0f;
EnterVehicle( vehicle );
}
}
/*
================
rvVehicleDriver::Event_ExitVehicle
================
*/
void rvVehicleDriver::Event_ExitVehicle( bool force ) {
Event_ScriptedStop();
if( vehicleController.GetVehicle() && force && !ExitVehicle(force) ) {
vehicleController.GetVehicle()->RemoveDriver( vehicleController.GetPosition(), force );
}
pathTargetInfo.node = NULL;
faceTarget = NULL;
lookTarget = NULL;
leader = NULL;
}
/*
================
rvVehicleDriver::Event_ScriptedMove
================
*/
void rvVehicleDriver::Event_ScriptedMove( idEntity *target, float minDist, bool exitVehicle ) {
isMoving = false;
if( !target ) {
return;
}
if( IsValidTarget( target ) ) {
isMoving = true;
faceTarget = NULL;
pathTargetInfo.node = target;
pathTargetInfo.initialDistance = ( target->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin() ).Length();
if ( !target->IsType( idPlayer::GetClassType() ) ) {
pathTargetInfo.minDistance = target->spawnArgs.GetFloat( "min_distance", va("%f", Max(200.0f, minDist)) );
pathTargetInfo.throttle = idMath::ClampFloat( 0.0f, 1.0f, target->spawnArgs.GetFloat( "throttle", "1" ) );
pathTargetInfo.exitVehicle = target->spawnArgs.GetBool( "exit_vehicle", exitVehicle ? "1" : "0" );
if( pathTargetInfo.exitVehicle ) {
pathTargetInfo.throttle = 0.0f;
}
} else {
pathTargetInfo.minDistance = minDist;
pathTargetInfo.throttle = 1.0f;
pathTargetInfo.exitVehicle = false;
}
} else {
SIMDProcessor->Memset( &pathTargetInfo, 0, sizeof( PathTargetInfo ) );
}
}
/*
================
rvVehicleDriver::Event_ScriptedDone
================
*/
void rvVehicleDriver::Event_ScriptedDone( void ) {
idThread::ReturnFloat( !IsMoving() );
}
/*
================
rvVehicleDriver::Event_ScriptedStop
================
*/
void rvVehicleDriver::Event_ScriptedStop( void ) {
if( IsDriving() ) {
usercmd_t cmd = { 0 };
vehicleController.SetInput( cmd, ang_zero );
if( pathTargetInfo.node ) {
if( func.Init( pathTargetInfo.node->spawnArgs.GetString( "call_doneMoving" )) > 0 ) {
func.InsertEntity( this, 0 );
func.CallFunc( &spawnArgs );
func.RemoveIndex( 0 );
}
pathTargetInfo.node->ActivateTargets(this);
pathTargetInfo.node = NULL;
}
isMoving = false;
}
}
/*
================
rvVehicleDriver::Event_Trigger
================
*/
void rvVehicleDriver::Event_Trigger( idEntity *activator ) {
if( IsDriving() && pathTargetInfo.node ) {
isMoving = true;
}
}
/*
================
rvVehicleDriver::Event_SetSpeed
================
*/
void rvVehicleDriver::Event_SetSpeed( float speed ) {
currentThrottle = speed;
}
//twhitaker: remove - begin
/*
================
rvVehicleDriver::Event_SetFollowOffset
================
*/
void rvVehicleDriver::Event_SetFollowOffset( const idVec3 &offset ) {
gameLocal.Warning( "Script Event \"followOffset\" is deprecated, please remove it immediately to avoid errors." );
}
//twhitaker: remove - end
/*
================
rvVehicleDriver::Event_FireWeapon
================
*/
void rvVehicleDriver::Event_FireWeapon( float weapon_index, float time ) {
if( IsDriving() ) {
fireEndTime = gameLocal.GetTime() + SEC2MS( time );
vehicleController.SelectWeapon( weapon_index );
}
}
/*
================
rvVehicleDriver::Event_FaceEntity
================
*/
void rvVehicleDriver::Event_FaceEntity( const idEntity* entity ) {
if( IsMoving() ) {
return;
}
faceTarget = entity;
isMoving = true;
}
/*
================
rvVehicleDriver::Event_LookAt
================
*/
void rvVehicleDriver::Event_LookAt( const idEntity* entity ) {
lookTarget = entity;
}
/*
================
rvVehicleDriver::Event_SetLeader
================
*/
void rvVehicleDriver::Event_SetLeader( idEntity* newLeader ) {
SetLeader( newLeader );
}
/*
================
rvVehicleDriver::UpdateAutoCorrection
================
*/
void rvVehicleDriver::UpdateAutoCorrection ( void ) {
if ( IsDriving() ) {
rvVehicle * vehicle = vehicleController.GetVehicle();
// Disregard your autocorrection state if we're slowing down to avoid collision with the leader.
if ( vehicle->IsAutoCorrecting() ) {
if ( avoidingLeader == true ) {
vehicle->autoCorrectionBegin = 0;
}
}
}
}
/*
================
rvVehicleDriver::Save
================
*/
void rvVehicleDriver::Save ( idSaveGame *savefile ) const {
savefile->Write ( &pathTargetInfo, sizeof ( pathTargetInfo ) );
savefile->Write ( &lastPathTargetInfo, sizeof ( lastPathTargetInfo ) );
savefile->WriteFloat ( currentThrottle );
faceTarget.Save ( savefile );
lookTarget.Save ( savefile );
leader.Save ( savefile );
savefile->WriteInt ( leaderFlags );
savefile->WriteFloat ( decelDistance );
savefile->WriteFloat ( minDistance );
savefile->WriteBool ( avoidingLeader );
savefile->WriteFloat ( fireEndTime );
func.Save ( savefile );
savefile->WriteBool ( isMoving );
savefile->WriteInt ( (int&)pathingMode );
pathingEntity.Save ( savefile );
savefile->WriteVec3 ( pathingOrigin );
savefile->WriteFloat( forwardThrustScale ); // cnicholson: Added unsaved var
savefile->WriteFloat( rightThrustScale ); // cnicholson: Added unsaved var
}
/*
================
rvVehicleDriver::Restore
================
*/
void rvVehicleDriver::Restore ( idRestoreGame *savefile ) {
savefile->Read ( &pathTargetInfo, sizeof ( pathTargetInfo ) );
savefile->Read ( &lastPathTargetInfo, sizeof ( lastPathTargetInfo ) );
savefile->ReadFloat ( currentThrottle );
faceTarget.Restore ( savefile );
lookTarget.Restore ( savefile );
leader.Restore ( savefile );
savefile->ReadInt ( leaderFlags );
savefile->ReadFloat ( decelDistance );
savefile->ReadFloat ( minDistance );
savefile->ReadBool ( avoidingLeader );
savefile->ReadFloat ( fireEndTime );
func.Restore ( savefile );
savefile->ReadBool ( isMoving );
savefile->ReadInt ( (int&)pathingMode );
pathingEntity.Restore ( savefile );
savefile->ReadVec3 ( pathingOrigin );
savefile->ReadFloat( forwardThrustScale ); // cnicholson: Added unrestored var
savefile->ReadFloat( rightThrustScale ); // cnicholson: Added unrestored var
}
+185
View File
@@ -0,0 +1,185 @@
//----------------------------------------------------------------
// VehicleDriver.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
extern const idEventDef VD_ChoosePathTarget;
class rvVehicleDriver : public idActor {
friend class rvVehicleAI;
friend class rvVehicleMonster;
public:
CLASS_PROTOTYPE( rvVehicleDriver );
rvVehicleDriver ( void );
void Think ( void );
void Spawn ( void );
static bool IsValidTarget ( const idEntity* ent ); // valid entity for looking or facing
static bool IsValidPathNode ( const idEntity* ent ); // valid entity for pathing
static bool IsValidLeader ( const idEntity* ent ); // valid entity to set as a leader
static int SortValid ( const void* a, const void* b );
virtual void Present ( void ) { }
protected:
void SimulateKeys ( usercmd_t& cmd, float dotForward, float dotRight, float speed, float distance = 0 );
void SimulateButtons ( usercmd_t& cmd );
void SimulateMouseMove ( usercmd_t& cmd );
bool GetTargetInfo ( const idEntity* target, idVec3* targetOrigin, idVec3* dirToTarget,
float* dotForward, float* dotRight, float* distance ) const;
idEntity* ChooseNextNode ( idEntity* target );
bool IsMoving ( void ) const { return isMoving && IsDriving(); }
bool IsDriving ( void ) const { return vehicleController.IsDriving(); }
bool SetLeader ( idEntity* newLeader );
const idEntity* GetLeader ( void ) const { return leader; }
void SetLeaderHint ( int flags ) { leaderFlags = flags; }
int GetLeaderHint ( void ) const { return leaderFlags; }
int SortTargetList ( idEntity* ent ) const;
idEntity* RandomValidTarget ( idEntity* ent ) const;
int NumValidTargets ( idEntity* ent ) const;
int NumTargets ( const idEntity* ent ) const;
idEntity* GetTarget ( const idEntity* ent, int index ) const;
void UpdateAutoCorrection ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
enum VD_PathingMode {
VDPM_Random = 0,
VDPM_MoveTo = 1,
VDPM_MoveAway = 2,
VDPM_Custom = 4,
};
void SetPathingMode ( VD_PathingMode mode, const idVec3 & origin );
// CustomPathingFunc SetPathingMode ( VD_PathingMode mode, CustomPathingFunc cb );
idEntity * SetPathingMode ( VD_PathingMode mode, idEntity * );
VD_PathingMode GetPathingMode ( void ) const;
const idVec3 & GetPathingOrigin ( void ) const;
// CustomPathingFunc GetPathingCustomCallback ( void ) const;
idEntity * GetPathingEntity ( void ) const;
protected:
void Event_PostSpawn ( void );
void Event_EnterVehicle ( idEntity * vehicle );
void Event_ExitVehicle ( bool force );
void Event_ScriptedMove ( idEntity *target, float minDist, bool exitVehicle );
void Event_ScriptedDone ( void );
void Event_ScriptedStop ( void );
void Event_Trigger ( idEntity *activator );
void Event_SetSpeed ( float speed );
void Event_FireWeapon ( float weapon_index, float time );
void Event_FaceEntity ( const idEntity* entity );
void Event_LookAt ( const idEntity* entity );
void Event_SetLeader ( idEntity* newLeader );
//twhitaker: remove - begin
void Event_SetFollowOffset ( const idVec3 &offset );
//twhitaker: remove - end
// Leader hints : a driver will send the following driving hints to it's leader
enum VD_LeaderHints {
VDLH_SlowDown = 1, // Set when distance is too great
VDLH_Wait = 2, // Set when there is no line of site
VDLH_Continue = 0, // Default following behavior
};
idStr & LeaderHintsString( int hints, idStr & out ) const {
switch ( hints ) {
case VDLH_SlowDown: out = "SlowDown"; break;
case VDLH_Wait: out = "Wait"; break;
default: out = "Continue"; break;
}
return out;
}
// Stores information about a path target
struct PathTargetInfo {
idEntityPtr<idEntity> node; // the target entity
float initialDistance; // the distance to this entity when we first decide to move there
float minDistance; // the range that specifies when this entity has been reached
float throttle; // 0 -> 1 speed setting
bool exitVehicle; // set to true to exit a vehicle when we reach this target
};
struct PathNavigationData {
float dotForward;
float dotRight;
};
// standard movement
PathTargetInfo pathTargetInfo;
PathTargetInfo lastPathTargetInfo;
float currentThrottle;
// facing
idEntityPtr<const idEntity> faceTarget;
idEntityPtr<const idEntity> lookTarget;
// following
idEntityPtr<rvVehicleDriver> leader; //TODO: twhitaker: see if I can make this an rvVehicle (so entities can follow player)
int leaderFlags;
float decelDistance;
float minDistance;
bool avoidingLeader;
// firing
float fireEndTime;
// event callbacks
rvScriptFuncUtility func;
// state
bool isMoving;
VD_PathingMode pathingMode;
// idEntity * (* pathingCallback)( idEntity * );
idEntityPtr<idEntity> pathingEntity;
idVec3 pathingOrigin;
float forwardThrustScale;
float rightThrustScale;
};
ID_INLINE void rvVehicleDriver::SetPathingMode( VD_PathingMode mode, const idVec3 & origin ) {
if ( mode != VDPM_Custom ) {
pathingMode = mode;
pathingOrigin = origin;
}
}
ID_INLINE idEntity * rvVehicleDriver::SetPathingMode( VD_PathingMode mode, idEntity * entity ) {
if ( mode != VDPM_Custom ) {
return NULL;
}
pathingMode = mode;
idEntity * prev = pathingEntity;
pathingEntity = entity;
return prev;
}
ID_INLINE rvVehicleDriver::VD_PathingMode rvVehicleDriver::GetPathingMode ( void ) const {
return pathingMode;
}
ID_INLINE const idVec3 & rvVehicleDriver::GetPathingOrigin ( void ) const {
return pathingOrigin;
}
ID_INLINE idEntity * rvVehicleDriver::GetPathingEntity ( void ) const {
return pathingEntity;
}
+188
View File
@@ -0,0 +1,188 @@
//----------------------------------------------------------------
// Vehicle.cpp
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "VehicleMonster.h"
#include "../ai/VehicleAI.h"
CLASS_DECLARATION( rvVehicle, rvVehicleMonster )
END_CLASS
rvVehicleMonster::rvVehicleMonster ( void ) {
}
rvVehicleMonster::~rvVehicleMonster ( void ) {
}
/*
================
rvVehicleMonster::Spawn
================
*/
void rvVehicleMonster::Spawn( void ) {
idDict dict;
int count = 0;
const idKeyValue * val = NULL;
for (;;) {
val = spawnArgs.MatchPrefix( "target", val );
if ( !val )
break;
dict.Set( "target" + (( count ) ? idStr( count ) : idStr( "" ) ), val->GetValue() );
count++;
}
dict.Set( "bind", name );
dict.SetBool( "hide", true );
driver = static_cast<rvVehicleAI *>( gameLocal.SpawnEntityDef( "ai_vehicle_driver", &dict ) );
if ( driver ) {
driver->SetVehicle( this );
driver->GetPhysics()->SetOrigin( vec3_zero );
} else {
gameLocal.Warning( "Unable to find \"entityDef ai_vehicle_driver\"." );
}
}
/*
================
rvVehicleMonster::SetClipModel
================
*/
void rvVehicleMonster::SetClipModel ( idPhysics & physicsObj ) {
idStr clipModelName;
idTraceModel trm;
float mass;
// rebuild clipmodel
spawnArgs.GetString( "clipmodel", "", clipModelName );
// load the trace model
if ( clipModelName.Length() ) {
if ( !collisionModelManager->TrmFromModel( gameLocal.GetMapName(), clipModelName, trm ) ) {
gameLocal.Error( "rvVehicleMonster '%s': cannot load collision model %s", name.c_str(), clipModelName.c_str() );
return;
}
physicsObj.SetClipModel( new idClipModel( trm ), spawnArgs.GetFloat ( "density", "1" ) );
} else {
physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), spawnArgs.GetFloat ( "density", "1" ) );
}
if ( spawnArgs.GetFloat ( "mass", "0", mass ) && mass > 0 ) {
physicsObj.SetMass ( mass );
}
}
/*
================
rvVehicleMonster::Save
================
*/
void rvVehicleMonster::Save ( idSaveGame *savefile ) const {
driver.Save ( savefile );
}
/*
================
rvVehicleMonster::Restore
================
*/
void rvVehicleMonster::Restore ( idRestoreGame *savefile ) {
driver.Restore ( savefile );
}
/*
================
rvVehicleMonster::Think
================
*/
void rvVehicleMonster::Think ( void ) {
if ( !driver ) {
PostEventMS( &EV_Remove, 0 );
return;
}
stateThread.Execute();
rvVehicle::Think();
}
/*
================
rvVehicleMonster::GetTargetOrigin
================
*/
const idVec3 & rvVehicleMonster::GetTargetOrigin ( void ) {
if ( driver && driver->driver && driver->driver->pathTargetInfo.node ) {
return driver->driver->pathTargetInfo.node->GetPhysics()->GetOrigin();
}
return vec3_origin;
}
/*
================
rvVehicleMonster::GetVectorToTarget
================
*/
idVec3 rvVehicleMonster::GetVectorToTarget ( void ) {
if ( driver && driver->driver && driver->driver->pathTargetInfo.node ) {
return driver->driver->pathTargetInfo.node->GetPhysics()->GetOrigin() - GetOrigin();
}
return vec3_origin;
}
/*
================
rvVehicleMonster::GetEnemyOrigin
================
*/
const idVec3 & rvVehicleMonster::GetEnemyOrigin ( void ) {
if ( driver && driver->enemy.ent ) {
return driver->enemy.ent->GetPhysics()->GetOrigin();
}
return vec3_origin;
}
/*
================
rvVehicleMonster::GetVectorToEnemy
================
*/
idVec3 rvVehicleMonster::GetVectorToEnemy ( void ) {
if ( driver && driver->enemy.ent ) {
//HACK: this is hideous, I'm ashamed.
return ( driver->enemy.ent->GetPhysics()->GetOrigin() + idVec3( 0, 0, 36 ) )- GetOrigin();
}
return vec3_origin;
}
/*
================
rvVehicleMonster::LookAtEntity
================
*/
void rvVehicleMonster::LookAtEntity ( idEntity *ent, float duration ) {
const idVec3 entOrigin = ent->GetPhysics()->GetOrigin();
const idVec3 origin = GetOrigin();
idVec3 toEnt = entOrigin - origin;
toEnt.Normalize();
GetPhysics()->SetAxis( toEnt.ToMat3() );
}
/*
================
rvVehicleMonster::SkipImpulse
================
*/
bool rvVehicleMonster::SkipImpulse( idEntity* ent, int id ) {
return false;
}
+45
View File
@@ -0,0 +1,45 @@
//----------------------------------------------------------------
// VehicleMonster.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#ifndef __GAME_VEHICLEMONSTER_H__
#define __GAME_VEHICLEMONSTER_H__
#ifndef __GAME_VEHICLE_H__
#include "Vehicle.h"
#endif
class rvVehicleAI;
class rvVehicleMonster : public rvVehicle {
friend class rvVehicleAI;
public:
CLASS_PROTOTYPE( rvVehicleMonster );
rvVehicleMonster ( void );
~rvVehicleMonster ( void );
void Spawn ( void );
void Think ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
bool SkipImpulse ( idEntity* ent, int id );
protected:
void SetClipModel ( idPhysics & physicsObj );
const idVec3 & GetTargetOrigin ( void );
idVec3 GetVectorToTarget ( void );
const idVec3 & GetEnemyOrigin ( void );
idVec3 GetVectorToEnemy ( void );
void LookAtEntity ( idEntity *ent, float duration );
idEntityPtr<rvVehicleAI> driver;
};
#endif // __GAME_VEHICLEMONSTER_H__
File diff suppressed because it is too large Load Diff
+444
View File
@@ -0,0 +1,444 @@
//----------------------------------------------------------------
// VehicleParts.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#ifndef __GAME_VEHICLEPARTS_H__
#define __GAME_VEHICLEPARTS_H__
class idWeapon;
class rvVehicle;
class rvVehiclePosition;
class rvEffect;
//----------------------------------------------------------------
// Base Part
//----------------------------------------------------------------
class rvVehiclePart : public idClass
{
public:
ABSTRACT_PROTOTYPE( rvVehiclePart );
virtual ~rvVehiclePart( void ) { }
void Spawn ( void );
void Save ( idSaveGame* saveFile ) const;
void Restore ( idRestoreGame* saveFile );
virtual bool Init ( rvVehiclePosition* position, const idDict& args, s_channelType soundChannel );
virtual void RunPrePhysics ( void ) { }
virtual void RunPhysics ( void ) { }
virtual void RunPostPhysics ( void ) { }
bool IsLeft ( void ) const;
bool IsFront ( void ) const;
bool IsUsingCenterMass ( void ) const;
bool IsActive ( void ) const;
virtual void Activate ( bool activate ) { fl.active = activate; }
virtual void Impulse ( int impulse ) { }
virtual rvVehiclePosition* GetPosition ( void ) const;
const idVec3& GetOrigin ( void ) const;
const idMat3& GetAxis ( void ) const;
protected:
void UpdateOrigin ( void );
typedef struct partFlags_s {
bool active : 1; // Is part active
bool left : 1; // Is part on left side of vehicle
bool front : 1; // Is part on right side of vehicle
bool useCenterMass : 1; // Use center of mass for origin
bool useViewAxis : 1; // Uses parent->viewAxis instead of the physics axis (::UpdateOrigin())
} partFlags_t;
partFlags_t fl;
idDict spawnArgs;
idEntityPtr<rvVehicle> parent;
jointHandle_t joint;
s_channelType soundChannel;
rvVehiclePosition* position;
idVec3 worldOrigin;
idMat3 worldAxis;
idVec3 localOffset;
};
ID_INLINE rvVehiclePosition* rvVehiclePart::GetPosition ( void ) const { return position; }
ID_INLINE const idVec3& rvVehiclePart::GetOrigin ( void ) const { return worldOrigin; }
ID_INLINE const idMat3& rvVehiclePart::GetAxis ( void ) const { return worldAxis; }
ID_INLINE bool rvVehiclePart::IsLeft ( void ) const { return fl.left; }
ID_INLINE bool rvVehiclePart::IsFront ( void ) const { return fl.front; }
ID_INLINE bool rvVehiclePart::IsUsingCenterMass ( void ) const { return fl.useCenterMass; }
ID_INLINE bool rvVehiclePart::IsActive ( void ) const { return fl.active; }
//----------------------------------------------------------------
// Sound
//----------------------------------------------------------------
class rvVehicleSound : public rvVehiclePart {
public:
CLASS_PROTOTYPE( rvVehicleSound );
rvVehicleSound ( void );
~rvVehicleSound ( void );
void Spawn ( void );
void Save ( idSaveGame* saveFile ) const;
void Restore ( idRestoreGame* saveFile );
virtual void RunPostPhysics ( void );
virtual void Activate ( bool active );
bool IsPlaying ( void ) const;
void Play ( void );
void Stop ( void );
void Update ( bool force = false );
void Fade ( int time, float toVolume, float toFreq );
void Attenuate ( float volumeAttenuate, float freqAttenuate );
void SetAutoActivate ( bool activate );
protected:
idVec2 volume;
idVec2 freqShift;
idStr soundName;
refSound_t refSound;
idInterpolate<float> currentVolume;
idInterpolate<float> currentFreqShift;
bool fade;
bool autoActivate;
};
ID_INLINE bool rvVehicleSound::IsPlaying ( void ) const {
idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
if( emitter ) {
return ( emitter->CurrentlyPlaying ( ) );
}
return( false );
}
ID_INLINE void rvVehicleSound::SetAutoActivate ( bool activate ){
autoActivate = activate;
}
//----------------------------------------------------------------
// Hoverpad
//----------------------------------------------------------------
class rvVehicleHoverpad : public rvVehiclePart {
public:
CLASS_PROTOTYPE( rvVehicleHoverpad );
rvVehicleHoverpad ( void );
~rvVehicleHoverpad ( void );
void Spawn ( void );
void Save ( idSaveGame* saveFile ) const;
void Restore ( idRestoreGame* saveFile );
virtual void RunPrePhysics ( void );
virtual void RunPhysics ( void );
virtual void Activate ( bool active );
protected:
void UpdateDustEffect ( const idVec3& origin, const idMat3& axis, float attenuation, const rvDeclMatType* mtype );
float height;
float dampen;
bool atRest;
idClipModel* clipModel;
idInterpolate<float> currentForce;
float force;
const idDeclTable* forceTable;
float forceRandom;
float fadeTime;
idVec3 velocity;
float thrustForward;
float thrustLeft;
float maxRestAngle;
int soundPart;
int forceUpTime;
int forceDownTime;
// Dust effects
rvClientEntityPtr<rvClientEffect> effectDust;
const rvDeclMatType* effectDustMaterialType;
};
//----------------------------------------------------------------
// Thruster
//----------------------------------------------------------------
class rvVehicleThruster : public rvVehiclePart {
public:
CLASS_PROTOTYPE( rvVehicleThruster );
rvVehicleThruster ( void );
~rvVehicleThruster ( void );
void Spawn ( void );
void Save ( idSaveGame* saveFile ) const;
void Restore ( idRestoreGame* saveFile );
virtual void RunPhysics ( void );
protected:
enum EThrusterKey
{
KEY_FORWARD,
KEY_RIGHT,
KEY_UP
};
float force;
int forceAxis;
EThrusterKey key;
};
//----------------------------------------------------------------
// Light
//----------------------------------------------------------------
class rvVehicleLight : public rvVehiclePart {
public:
CLASS_PROTOTYPE( rvVehicleLight );
rvVehicleLight ( void );
~rvVehicleLight ( void );
void Spawn ( void );
void Save ( idSaveGame* saveFile ) const;
void Restore ( idRestoreGame* saveFile );
virtual void RunPostPhysics ( void );
virtual void Activate ( bool active );
virtual void Impulse ( int impulse );
protected:
void TurnOff ( void );
void TurnOn ( void );
void UpdateLightDef ( void );
renderLight_t renderLight;
int lightHandle;
bool lightOn;
idStr soundOn;
idStr soundOff;
};
//----------------------------------------------------------------
// Weapon
//----------------------------------------------------------------
class rvVehicleWeapon : public rvVehiclePart {
public:
CLASS_PROTOTYPE( rvVehicleWeapon );
rvVehicleWeapon ( void );
~rvVehicleWeapon ( void );
void Spawn ( void );
void Save ( idSaveGame* saveFile ) const;
void Restore ( idRestoreGame* saveFile );
virtual void RunPostPhysics ( void );
virtual void Activate ( bool activate );
int GetCurrentAmmo ( void ) const;
float GetCurrentCharge ( void ) const;
void UpdateCursorGUI ( idUserInterface* gui ) const;
bool Fire ();
int GetZoomFov ( void ) const;
idUserInterface * GetZoomGui ( void ) const;
float GetZoomTime ( void ) const;
bool CanZoom ( void ) const;
void StopTargetEffect ( void );
protected:
#ifdef _XENON
idActor* bestEnemy;
void AutoAim( idPlayer* player, const idVec3& origin, idVec3& dir );
#endif
void LaunchHitScan ( const idVec3& origin, const idVec3& dir, const idVec3& jointOrigin );
void LaunchProjectile ( const idVec3& origin, const idVec3& dir, const idVec3& pushVelocity );
void LaunchProjectiles ();
void UpdateLock ( void );
void GetLockInfo ( const idVec3& eyeOrigin, const idMat3& eyeAxis );
void EjectBrass ( void );
void MuzzleFlashLight ( const idVec3& origin, const idMat3& axis );
void WeaponFeedback ( const idDict* dict );
int nextFireTime;
int fireDelay;
int count;
const idDict* projectileDef;
const idDict* hitScanDef;
float spread;
bool launchFromJoint;
bool lockScanning;
int lastLockTime;
float lockRange;
idEntityPtr<idEntity> targetEnt;
jointHandle_t targetJoint;
idVec3 targetPos;
rvClientEntityPtr<rvClientEffect> targetEffect;
idList<jointHandle_t> joints;
int jointIndex;
idVec3 force;
int ammoPerCharge;
int chargeTime;
int currentAmmo;
idInterpolate<float> currentCharge;
renderLight_t muzzleFlash;
int muzzleFlashHandle;
int muzzleFlashEnd;
int muzzleFlashTime;
idVec3 muzzleFlashOffset;
int animNum;
int animChannel;
const idSoundShader* shaderFire;
const idSoundShader* shaderReload;
const idDict* brassDict;
jointHandle_t brassEjectJoint;
idVec3 brassEjectOffset;
int brassEjectNext;
int brassEjectDelay;
int zoomFov;
idUserInterface * zoomGui;
float zoomTime;
};
ID_INLINE int rvVehicleWeapon::GetCurrentAmmo ( void ) const { return currentAmmo; }
ID_INLINE float rvVehicleWeapon::GetCurrentCharge ( void ) const { return currentCharge.IsDone(gameLocal.time) ? 1.0f : currentCharge.GetCurrentValue(gameLocal.time); }
ID_INLINE int rvVehicleWeapon::GetZoomFov ( void ) const { return zoomFov; }
ID_INLINE idUserInterface* rvVehicleWeapon::GetZoomGui ( void ) const { return zoomGui; }
ID_INLINE float rvVehicleWeapon::GetZoomTime ( void ) const { return zoomTime; }
ID_INLINE bool rvVehicleWeapon::CanZoom ( void ) const { return zoomFov != -1; }
//----------------------------------------------------------------
// Turret
//----------------------------------------------------------------
class rvVehicleTurret : public rvVehiclePart {
public:
CLASS_PROTOTYPE( rvVehicleTurret );
rvVehicleTurret ( void );
void Spawn ( void );
void Save ( idSaveGame* saveFile ) const;
void Restore ( idRestoreGame* saveFile );
virtual void RunPrePhysics ( void );
virtual void RunPostPhysics ( void );
virtual void Activate ( bool active );
protected:
idBounds angles;
int axisMap[3];
float invert[3];
idAngles currentAngles;
int moveTime;
float turnRate;
int soundPart;
bool parentStuck;
};
//----------------------------------------------------------------
// Animated Vehicle Part
//----------------------------------------------------------------
class rvVehicleUserAnimated : public rvVehiclePart {
public:
CLASS_PROTOTYPE( rvVehicleUserAnimated );
rvVehicleUserAnimated ( void );
void Spawn ( void );
void Save ( idSaveGame* saveFile ) const;
void Restore ( idRestoreGame* saveFile );
virtual void RunPrePhysics ( void );
void Event_PostSpawn ( void );
protected:
typedef struct rvUserAnimatedAnim_s {
int index;
float frame;
short length;
short channel;
float rate;
bool loop;
} rvUserAnimatedAnim_t;
enum { VUAA_Forward, VUAA_Strafe, VUAA_Crouch, VUAA_Attack, VUAA_Count };
enum { VUAF_Forward, VUAF_Strafe, VUAF_Crouch, VUAF_Attack, VUAF_Count };
rvUserAnimatedAnim_t anims[ VUAA_Count ];
rvScriptFuncUtility funcs[ VUAF_Count ];
void InitAnim( const char * action, rvUserAnimatedAnim_t & anim );
void InitFunc( const char * action, rvScriptFuncUtility & func );
void SetFrame( const rvUserAnimatedAnim_t & anim );
void LateralMove( signed char input, int anim, int func );
};
typedef idList<rvVehiclePart*> rvVehiclePartList_t;
#endif // __GAME_VEHICLEPARTS_H__
+847
View File
@@ -0,0 +1,847 @@
//----------------------------------------------------------------
// VehicleController.cpp
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "Vehicle.h"
/*
================
rvVehiclePosition::rvVehiclePosition
================
*/
rvVehiclePosition::rvVehiclePosition ( void ) {
memset ( &mInputCmd, 0, sizeof(mInputCmd) );
mInputAngles.Zero ( );
memset ( &fl, 0, sizeof(fl) );
mCurrentWeapon = -1;
mSoundPart = -1;
mDriver = NULL;
mParent = NULL;
mEyeOrigin.Zero();
mEyeAxis.Identity();
mEyeOffset.Zero();
mEyeJoint = INVALID_JOINT;
mDriverOffset.Zero ( );
mDriverJoint = INVALID_JOINT;
}
/*
================
rvVehiclePosition::~rvVehiclePosition
================
*/
rvVehiclePosition::~rvVehiclePosition ( void ) {
mParts.DeleteContents ( true );
mWeapons.DeleteContents ( true );
}
void InitIntArray( const idVec3& vec, int array[] ) {
int ix;
for( ix = 0; ix < vec.GetDimension(); ++ix ) {
array[ix] = (int)vec[ix];
}
}
/*
================
rvVehiclePosition::Init
================
*/
void rvVehiclePosition::Init ( rvVehicle* parent, const idDict& args ) {
idVec3 garbage;
mParent = parent;
mEyeJoint = mParent->GetAnimator()->GetJointHandle ( args.GetString ( "eyeJoint" ) );
// abahr & twhitaker: removed this due to other changes.
//if( !mParent->GetAnimator()->GetJointTransform(mEyeJoint, gameLocal.GetTime(), garbage, mEyeJointTransform) ) {
mEyeJointTransform.Identity();
//}
//mEyeJointTransform.TransposeSelf();
mEyeOffset = args.GetVector ( "eyeOffset", "0 0 0" );
mDeltaEyeAxisScale = args.GetAngles( "deltaEyeAxisScale", "1 1 0" );
mDeltaEyeAxisScale.Clamp( ang_zero, idAngles(1.0f, 1.0f, 1.0f) );
InitIntArray( args.GetVector("eyeJointAxisMap", "0 1 2"), mEyeJointAxisMap );
InitIntArray( args.GetVector("eyeJointDirMap", "1 1 1"), mEyeJointDirMap );
mAxisOffset = args.GetAngles( "angles_offset" ).ToMat3();
mDriverJoint = mParent->GetAnimator()->GetJointHandle ( args.GetString ( "driverJoint" ) );
// abahr & twhitaker: removed this due to other changes.
//if( !mParent->GetAnimator()->GetJointTransform(mDriverJoint, gameLocal.GetTime(), garbage, mDriverJointTransform) ) {
mDriverJointTransform.Identity();
//}
//mDriverJointTransform.TransposeSelf( );
mDriverOffset = args.GetVector ( "driverOffset", "0 0 0" );
mDeltaDriverAxisScale = args.GetAngles( "deltaDriverAxisScale", "1 1 0" );
mDeltaDriverAxisScale.Clamp( ang_zero, idAngles(1.0f, 1.0f, 1.0f) );
InitIntArray( args.GetVector("driverJointAxisMap", "0 1 2"), mDriverJointAxisMap );
InitIntArray( args.GetVector("driverJointDirMap", "1 1 1"), mDriverJointDirMap );
mExitPosOffset = args.GetVector( "exitPosOffset" );
mExitAxisOffset = args.GetAngles( "exitAxisOffset" ).ToMat3();
mDriverAnim = args.GetString ( "driverAnim", "driver" );
fl.driverVisible = args.GetBool ( "driverVisible", "0" );
fl.engine = args.GetBool ( "engine", "0" );
fl.depthHack = args.GetBool ( "depthHack", "1" );
fl.bindDriver = args.GetBool ( "bindDriver", "1" );
args.GetString ( "internalSurface", "", mInternalSurface );
SetParts ( args );
mSoundMaxSpeed = args.GetFloat ( "maxsoundspeed", "0" );
// Looping sound when occupied?
// jmarshall - vehicle sound loops cause a crash, disabling for the time being.
//if ( *args.GetString ( "snd_loop", "" ) ) {
// mSoundPart = AddPart ( rvVehicleSound::GetClassType(), args );
// static_cast<rvVehicleSound*>(mParts[mSoundPart])->SetAutoActivate ( false );
//}
// jmarshall end
SelectWeapon ( 0 );
UpdateInternalView ( true );
}
/*
================
rvVehiclePosition::SetParts
================
*/
void rvVehiclePosition::SetParts ( const idDict& args ) {
const idKeyValue* kv;
// Spawn all parts
kv = args.MatchPrefix( "def_part", NULL );
while ( kv ) {
const idDict* dict;
idTypeInfo* typeInfo;
// Skip empty strings
if ( !kv->GetValue().Length() ) {
kv = args.MatchPrefix( "def_part", kv );
continue;
}
// Get the dictionary for the part
dict = gameLocal.FindEntityDefDict ( kv->GetValue() );
if ( !dict ) {
gameLocal.Error ( "Invalid vehicle part definition '%'", kv->GetValue().c_str() );
}
// Determine the part type
typeInfo = idClass::GetClass ( dict->GetString ( "spawnclass" ) );
if ( !typeInfo || !typeInfo->IsType ( rvVehiclePart::GetClassType() ) ) {
gameLocal.Error ( "Class '%s' is not a vehicle part", dict->GetString ( "spawnclass" ) );
}
// Add the new part
AddPart ( *typeInfo, *dict );
kv = args.MatchPrefix( "def_part", kv );
}
}
/*
================
rvVehiclePosition::AddPart
================
*/
int rvVehiclePosition::AddPart ( const idTypeInfo &classdef, const idDict& args ) {
rvVehiclePart* part;
int soundChannel;
// Get a sound channel
soundChannel = SND_CHANNEL_CUSTOM;
soundChannel += mParts.Num();
// Allocate the new part
part = static_cast<rvVehiclePart*>(classdef.CreateInstance ( ));
part->Init ( this, args, (s_channelType)soundChannel );
part->CallSpawn ( );
// Weapons go into their own list since only one can be active
// and any given point in time.
if ( part->IsType ( rvVehicleWeapon::GetClassType() ) ) {
return mWeapons.Append ( part );
}
return mParts.Append ( part );
}
/*
================
rvVehiclePosition::SetDriver
================
*/
bool rvVehiclePosition::SetDriver ( idActor* driver ) {
if ( mDriver == driver ) {
return false;
}
fl.inputValid = false;
if ( driver ) {
mDriver = driver;
// Keep the driver visible if the position is exposed
if ( fl.driverVisible ) {
mDriver->Show ( );
} else {
mDriver->Hide ( );
// Dont let the player take damage when inside the if not visible
mDriver->fl.takedamage = false;
}
if ( mSoundPart != -1 ) {
static_cast<rvVehicleSound*>(mParts[mSoundPart])->Play ( );
}
// Bind the driver to a joint or to the vehicles origin?
if( fl.bindDriver ) {
if ( INVALID_JOINT != mDriverJoint ) {
mDriver->GetPhysics()->SetAxis ( mParent->GetAxis( ) );// Not sure if this is needed
mDriver->BindToJoint ( mParent, mDriverJoint, true );
mDriver->GetPhysics()->SetOrigin ( vec3_origin );
} else {
mDriver->Bind ( mParent, true );
mDriver->GetPhysics()->SetOrigin( mDriverOffset );
}
} else {// If not bound put the vehicle first in the active list
mParent->activeNode.Remove();
mParent->activeNode.AddToFront( gameLocal.activeEntities );
}
// Play a certain animation on the driver
if ( mDriverAnim.Length() ) {
mDriver->GetAnimator()->CycleAnim( ANIMCHANNEL_ALL, mDriver->GetAnimator()->GetAnim( mDriverAnim ), gameLocal.time, 0 );
}
} else {
if ( !fl.driverVisible ) {
mDriver->Show ( );
// Take damage again
mDriver->fl.takedamage = true;
}
// Driver is no longer bound to the vehicle
mDriver->Unbind();
mDriver = driver;
if ( mSoundPart != -1 ) {
static_cast<rvVehicleSound*>(mParts[mSoundPart])->Stop ( );
}
// Clear out the input commands so the guns dont keep firing and what not when
// the player gets out
memset ( &mInputCmd, 0, sizeof(mInputCmd) );
mInputAngles.Zero ( );
}
return true;
}
/*
================
rvVehiclePosition::GetAxis
================
*/
idMat3 rvVehiclePosition::GetAxis() const {
return mAxisOffset * GetParent()->GetPhysics()->GetAxis();
}
/*
================
rvVehiclePosition::GetOrigin
================
*/
idVec3 rvVehiclePosition::GetOrigin( const idVec3& offset ) const {
return GetParent()->GetPhysics()->GetOrigin() + (mDriverOffset + offset) * GetAxis();
}
/*
================
rvVehiclePosition::ActivateParts
================
*/
void rvVehiclePosition::ActivateParts ( bool active ) {
int i;
// Activate or deactive the parts based on whether there is a driver
for ( i = mParts.Num() - 1; i >= 0; i -- ) {
mParts[i]->Activate ( active );
}
for ( i = mWeapons.Num() - 1; i >= 0; i -- ) {
mWeapons[i]->Activate ( active );
}
}
/*
================
rvVehiclePosition::EjectDriver
================
*/
bool rvVehiclePosition::EjectDriver ( bool force ) {
if ( !IsOccupied ( ) ) {
return false;
}
// Physically eject the actor from the position
if ( !force && mParent->IsLocked ( ) ) {
mParent->IssueLockedWarning ( );
return false;
}
// Remove the driver and if successful disable all parts for
// this position
if ( SetDriver ( NULL ) ) {
ActivateParts ( false );
return true;
}
return false;
}
/*
================
rvVehiclePosition::SetInput
================
*/
void rvVehiclePosition::SetInput ( const usercmd_t& cmd, const idAngles& newAngles ) {
if ( gameDebug.IsHudActive ( DBGHUD_VEHICLE ) ) {
if ( mDriver == gameLocal.GetLocalPlayer ( ) ) {
gameDebug.SetFocusEntity ( mParent );
}
}
if ( fl.inputValid || !mDriver ) {
mOldInputCmd = mInputCmd;
mOldInputAngles = mInputAngles;
} else {
mOldInputCmd = cmd;
mInputCmd = cmd;
mInputAngles = newAngles;
// We have valid input now and there is a driver so activate all of the parts
if ( !fl.inputValid && mDriver ) {
ActivateParts ( true );
}
}
fl.inputValid = true;
mInputCmd = cmd;
mInputAngles = newAngles;
}
/*
================
rvVehiclePosition::GetInput
================
*/
void rvVehiclePosition::GetInput( usercmd_t& cmd, idAngles& newAngles ) const {
cmd = mInputCmd;
newAngles = mInputAngles;
}
/*
================
rvVehiclePosition::UpdateHUD
================
*/
void rvVehiclePosition::UpdateHUD ( idUserInterface* gui ) {
// HACK: twhitaker: this is ugly but since the GEV and the Walker now have a unified HUD, it is a necessary evil
int guiWeaponID;
if ( !stricmp( mParent->spawnArgs.GetString( "classname" ), "vehicle_walker" ) ) {
guiWeaponID = mCurrentWeapon + 2;
} else {
guiWeaponID = mCurrentWeapon;
}
gui->SetStateInt ( "vehicle_weapon", guiWeaponID );
// HACK: twhitaker end
gui->SetStateInt ( "vehicle_weaponcount", mWeapons.Num() );
if ( mCurrentWeapon >= 0 && mCurrentWeapon < mWeapons.Num() ) {
rvVehicleWeapon* weapon;
weapon = static_cast<rvVehicleWeapon*>(mWeapons[mCurrentWeapon]);
gui->SetStateFloat ( "vehicle_weaponcharge", weapon->GetCurrentCharge() );
gui->SetStateInt ( "vehicle_weaponammo", weapon->GetCurrentAmmo() );
}
// Calculate the rotation of the view in relation to the vehicle itself
gui->SetStateFloat ( "vehicle_rotate", -idMath::AngleDelta ( mEyeAxis.ToAngles()[YAW], mParent->GetAxis ( ).ToAngles()[YAW] ) );
if( GetParent() ) {
GetParent()->UpdateHUD( GetDriver(), gui );
}
}
/*
================
rvVehiclePosition::UpdateCursorGUI
================
*/
void rvVehiclePosition::UpdateCursorGUI ( idUserInterface* gui ) {
if ( mCurrentWeapon < 0 || mCurrentWeapon >= mWeapons.Num() ) {
return;
}
rvVehicleWeapon* weapon;
weapon = static_cast<rvVehicleWeapon*>(mWeapons[mCurrentWeapon]);
assert ( weapon );
weapon->UpdateCursorGUI ( gui );
}
/*
================
rvVehiclePosition::UpdateInternalView
================
*/
void rvVehiclePosition::UpdateInternalView ( bool force ) {
bool internal = false;
// If the local player is driving and not in third person then use internal
internal = ( mDriver == gameLocal.GetLocalPlayer() && !pm_thirdPerson.GetInteger() );
// force the update?
if ( !force && internal == fl.internalView ) {
return;
}
fl.internalView = internal;
if ( fl.depthHack ) {
mParent->GetRenderEntity()->weaponDepthHackInViewID = (IsOccupied() && fl.internalView) ? GetDriver()->entityNumber + 1 : 0;
}
// Show and hide the internal surface
if ( mInternalSurface.Length() ) {
mParent->ProcessEvent ( fl.internalView ? &EV_ShowSurface : &EV_HideSurface, mInternalSurface.c_str() );
}
}
/*
================
rvVehiclePosition::RunPrePhysics
================
*/
void rvVehiclePosition::RunPrePhysics ( void ) {
int i;
UpdateInternalView ( );
if ( mParent->IsStalled() ) {
if ( !fl.stalled ) {
// we just stalled
fl.stalled = true;
ActivateParts( false );
}
return;
} else if ( IsOccupied() && !mParent->IsStalled() && fl.stalled ) {
// we just restarted
fl.stalled = false;
ActivateParts( true );
}
// Give the parts a chance to set up for physics
for ( i = mParts.Num() - 1; i >= 0; i -- ) {
assert ( mParts[i] );
mParts[i]->RunPrePhysics ( );
}
if ( mCurrentWeapon >= 0 ) {
mWeapons[mCurrentWeapon]->RunPrePhysics ( );
}
// Run physics for each part
for ( i = mParts.Num() - 1; i >= 0; i -- ) {
assert ( mParts[i] );
mParts[i]->RunPhysics ( );
}
// Attenuate the attached sound if speed based
if ( mSoundPart != -1 && mSoundMaxSpeed > 0.0f ) {
float f;
float speed;
idVec3 vel;
// Only interested in forward or backward velocity
vel = mParent->GetPhysics()->GetLinearVelocity ( ) * mParent->GetPhysics()->GetAxis ( );
speed = idMath::ClampFloat ( 0.0f, mSoundMaxSpeed, vel.Normalize ( ) );
f = speed / mSoundMaxSpeed;
static_cast<rvVehicleSound*>(mParts[mSoundPart])->Attenuate ( f, f );
}
if ( mCurrentWeapon >= 0 ) {
mWeapons[mCurrentWeapon]->RunPhysics ( );
}
}
/*
================
rvVehiclePosition::RunPostPhysics
================
*/
void rvVehiclePosition::RunPostPhysics ( void ) {
int i;
for ( i = 0; i < mParts.Num(); i ++ ) {
assert ( mParts[i] );
mParts[i]->RunPostPhysics ( );
}
if ( mCurrentWeapon >= 0 ) {
mWeapons[mCurrentWeapon]->RunPostPhysics ( );
}
if ( !IsOccupied ( ) ) {
return;
}
if ( fl.inputValid ) {
if ( mInputCmd.upmove > 0 && !mParent->IsLocked() ) {
// inform the driver that its time to get out of the vehicle.
if( !mDriver->EventIsPosted(&AI_ExitVehicle) ) {
mDriver->PostEventMS( &AI_ExitVehicle, 250, false );// To remove jump when exiting
}
// If the position isnt occupied anymore then the vehicle exit was successful and there
// is nothing else to do
if ( !IsOccupied ( ) ) {
return;
}
} else if ( (mInputCmd.flags & UCF_IMPULSE_SEQUENCE) != (mOldInputFlags & UCF_IMPULSE_SEQUENCE) ) {
int i;
if ( mInputCmd.impulse >= IMPULSE_0 && mInputCmd.impulse <= IMPULSE_12 ) {
SelectWeapon( mInputCmd.impulse - IMPULSE_0 );
}
if ( mWeapons.Num () ) {
switch ( mInputCmd.impulse ) {
case IMPULSE_14:
SelectWeapon ( (mCurrentWeapon + mWeapons.Num() + 1) % mWeapons.Num() );
break;
case IMPULSE_15:
SelectWeapon ( (mCurrentWeapon + mWeapons.Num() - 1) % mWeapons.Num() );
break;
}
}
for( i = 0; i < mParts.Num(); i++ ) {
mParts[ i ]->Impulse ( mInputCmd.impulse );
}
mOldInputFlags = mInputCmd.flags;
}
}
// Update the eye origin and axis
GetEyePosition( mEyeOrigin, mEyeAxis );
if ( g_debugVehicle.GetInteger() == 2 ) {
gameRenderWorld->DebugArrow( colorMagenta, mEyeOrigin, mEyeOrigin + mEyeAxis[0] * 30.0f, 3 );
}
}
/*
================
rvVehiclePosition::GetEyePosition
================
*/
void rvVehiclePosition::GetEyePosition( idVec3& origin, idMat3& axis ) const {
GetPosition( mEyeJoint, mEyeOffset, mEyeJointTransform, mDeltaEyeAxisScale, mEyeJointAxisMap, mEyeJointDirMap, origin, axis );
axis *= GetParent()->GetAxis();
}
/*
================
rvVehiclePosition::GetDriverPosition
================
*/
void rvVehiclePosition::GetDriverPosition( idVec3& origin, idMat3& axis ) const {
if( fl.bindDriver ) {
GetPosition( mDriverJoint, mDriverOffset, mDriverJointTransform, mDeltaDriverAxisScale, mDriverJointAxisMap, mDriverJointDirMap, origin, axis );
} else {
origin = GetDriver()->GetPhysics()->GetOrigin();
axis = GetDriver()->viewAxis;
}
}
/*
================
rvVehiclePosition::GetPosition
================
*/
void rvVehiclePosition::GetPosition( const jointHandle_t jointHandle, const idVec3& offset, const idMat3& jointTransform, const idAngles& scale, const int axisMap[], const int dirMap[], idVec3& origin, idMat3& axis ) const {
if( GetParent()->GetAnimator()->GetJointTransform(jointHandle, gameLocal.GetTime(), origin, axis) ) {
axis *= jointTransform;
idAngles ang( axis.ToAngles().Remap(axisMap, dirMap).Scale(scale) );
axis = ang.Normalize360().ToMat3() * mAxisOffset;
origin = GetParent()->GetOrigin() + (origin + offset * axis) * GetParent()->GetAxis();
} else {
origin = GetOrigin( mEyeOffset );
axis = GetAxis();
}
}
/*
================
rvVehiclePosition::FireWeapon
================
*/
void rvVehiclePosition::FireWeapon( void ) {
if ( mCurrentWeapon >= 0 ) {
static_cast<rvVehicleWeapon*>( mWeapons[mCurrentWeapon] )->Fire();
}
}
/*
================
rvVehiclePosition::SelectWeapon
================
*/
void rvVehiclePosition::SelectWeapon ( int weapon ) {
if ( weapon < 0 || weapon >= mWeapons.Num ( ) ) {
return;
}
// mekberg: clear effect
if ( mCurrentWeapon != -1 ) {
static_cast<rvVehicleWeapon*> ( mWeapons[ mCurrentWeapon ] )->StopTargetEffect( );
}
mCurrentWeapon = weapon;
}
/*
================
rvVehiclePosition::WriteToSnapshot
================
*/
void rvVehiclePosition::WriteToSnapshot ( idBitMsgDelta &msg ) const {
msg.WriteBits ( mCurrentWeapon, 3 );
}
/*
================
rvVehiclePosition::ReadFromSnapshot
================
*/
void rvVehiclePosition::ReadFromSnapshot ( const idBitMsgDelta &msg ) {
mCurrentWeapon = msg.ReadBits ( 3 );
}
/*
================
rvVehiclePosition::Save
================
*/
void rvVehiclePosition::Save ( idSaveGame* savefile ) const {
int i;
savefile->WriteUsercmd( mInputCmd );
savefile->WriteAngles ( mInputAngles );
savefile->WriteUsercmd ( mOldInputCmd );
savefile->WriteAngles ( mOldInputAngles );
savefile->WriteInt ( mOldInputFlags );
savefile->WriteInt ( mCurrentWeapon );
mDriver.Save ( savefile );
mParent.Save ( savefile );
savefile->WriteInt ( mParts.Num ( ) );
for ( i = 0; i < mParts.Num(); i ++ ) {
savefile->WriteString ( mParts[i]->GetClassname() );
savefile->WriteStaticObject ( *mParts[i] );
}
savefile->WriteInt ( mWeapons.Num ( ) );
for ( i = 0; i < mWeapons.Num(); i ++ ) {
savefile->WriteString ( mWeapons[i]->GetClassname() );
savefile->WriteStaticObject ( *mWeapons[i] );
}
savefile->WriteVec3 ( mEyeOrigin );
savefile->WriteMat3 ( mEyeAxis );
savefile->WriteJoint ( mEyeJoint );
savefile->WriteVec3 ( mEyeOffset );
savefile->WriteMat3( mEyeJointTransform );
savefile->WriteAngles( mDeltaEyeAxisScale );
savefile->Write ( mEyeJointAxisMap, sizeof mEyeJointAxisMap );
savefile->Write ( mEyeJointDirMap, sizeof mEyeJointDirMap );
savefile->WriteMat3 ( mAxisOffset );
savefile->WriteJoint ( mDriverJoint );
savefile->WriteVec3 ( mDriverOffset );
savefile->WriteMat3 ( mDriverJointTransform );
savefile->WriteAngles( mDeltaDriverAxisScale );
savefile->Write ( mDriverJointAxisMap, sizeof mDriverJointAxisMap );
savefile->Write ( mDriverJointDirMap, sizeof mDriverJointDirMap );
savefile->WriteVec3 ( mExitPosOffset );
savefile->WriteMat3 ( mExitAxisOffset );
savefile->WriteString ( mDriverAnim );
savefile->WriteString ( mInternalSurface );
savefile->Write ( &fl, sizeof ( fl ) );
savefile->WriteInt ( mSoundPart );
savefile->WriteFloat ( mSoundMaxSpeed );
}
/*
================
rvVehiclePosition::Restore
================
*/
void rvVehiclePosition::Restore ( idRestoreGame* savefile ) {
int i;
int num;
savefile->ReadUsercmd( mInputCmd );
savefile->ReadAngles ( mInputAngles );
savefile->ReadUsercmd ( mOldInputCmd );
savefile->ReadAngles ( mOldInputAngles );
savefile->ReadInt ( mOldInputFlags );
savefile->ReadInt ( mCurrentWeapon );
mDriver.Restore ( savefile );
mParent.Restore ( savefile );
savefile->ReadInt ( num );
mParts.Clear ( );
mParts.SetNum ( num );
for ( i = 0; i < num; i ++ ) {
idStr spawnclass;
rvVehiclePart* part;
idTypeInfo* typeInfo;
savefile->ReadString ( spawnclass );
// Determine the part type
typeInfo = idClass::GetClass ( spawnclass );
if ( !typeInfo || !typeInfo->IsType ( rvVehiclePart::GetClassType() ) )
{
gameLocal.Error ( "Class '%s' is not a vehicle part", spawnclass.c_str() );
}
part = static_cast<rvVehiclePart*>(typeInfo->CreateInstance ( ));
savefile->ReadStaticObject ( *part );
mParts[i] = part;
}
savefile->ReadInt ( num );
mWeapons.Clear ( );
mWeapons.SetNum ( num );
for ( i = 0; i < num; i ++ ) {
idStr spawnclass;
rvVehiclePart* part;
idTypeInfo* typeInfo;
savefile->ReadString ( spawnclass );
// Determine the part type
typeInfo = idClass::GetClass ( spawnclass );
if ( !typeInfo || !typeInfo->IsType ( rvVehiclePart::GetClassType() ) )
{
gameLocal.Error ( "Class '%s' is not a vehicle part", spawnclass.c_str() );
}
part = static_cast<rvVehiclePart*>(typeInfo->CreateInstance ( ));
savefile->ReadStaticObject ( *part );
mWeapons[i] = part;
}
savefile->ReadVec3 ( mEyeOrigin );
savefile->ReadMat3 ( mEyeAxis );
savefile->ReadJoint ( mEyeJoint );
savefile->ReadVec3 ( mEyeOffset );
savefile->ReadMat3 ( mEyeJointTransform );
savefile->ReadAngles( mDeltaEyeAxisScale );
savefile->Read( mEyeJointAxisMap, sizeof mEyeJointAxisMap );
savefile->Read( mEyeJointDirMap, sizeof mEyeJointDirMap );
savefile->ReadMat3 ( mAxisOffset );
savefile->ReadJoint ( mDriverJoint );
savefile->ReadVec3 ( mDriverOffset );
savefile->ReadMat3 ( mDriverJointTransform );
savefile->ReadAngles( mDeltaDriverAxisScale );
savefile->Read( mDriverJointAxisMap, sizeof mDriverJointAxisMap );
savefile->Read( mDriverJointDirMap, sizeof mDriverJointDirMap );
savefile->ReadVec3 ( mExitPosOffset );
savefile->ReadMat3 ( mExitAxisOffset );
savefile->ReadString ( mDriverAnim );
savefile->ReadString ( mInternalSurface );
savefile->Read ( &fl, sizeof(fl) );
savefile->ReadInt ( mSoundPart );
savefile->ReadFloat ( mSoundMaxSpeed );
}
+163
View File
@@ -0,0 +1,163 @@
//----------------------------------------------------------------
// Vehicle.cpp
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "VehicleRigid.h"
CLASS_DECLARATION( rvVehicle, rvVehicleRigid )
END_CLASS
rvVehicleRigid::rvVehicleRigid ( void ) {
}
rvVehicleRigid::~rvVehicleRigid ( void ) {
SetPhysics( NULL );
}
/*
================
rvVehicleRigid::Spawn
================
*/
void rvVehicleRigid::Spawn( void ) {
physicsObj.SetSelf( this );
SetClipModel ( );
physicsObj.SetOrigin( GetPhysics()->GetOrigin ( ) );
physicsObj.SetAxis ( GetPhysics()->GetAxis ( ) );
physicsObj.SetContents( CONTENTS_BODY );
physicsObj.SetClipMask( MASK_PLAYERSOLID|CONTENTS_VEHICLECLIP );
physicsObj.SetFriction ( spawnArgs.GetFloat ( "friction_linear", "1" ), spawnArgs.GetFloat ( "friction_angular", "1" ), spawnArgs.GetFloat ( "friction_contact", "1" ) );
physicsObj.SetBouncyness ( spawnArgs.GetFloat ( "bouncyness", "0.6" ) );
physicsObj.SetGravity( gameLocal.GetGravity() );
SetPhysics( &physicsObj );
animator.CycleAnim ( ANIMCHANNEL_ALL, animator.GetAnim( spawnArgs.GetString( "anim", "idle" ) ), gameLocal.time, 0 );
BecomeActive( TH_THINK );
}
/*
================
rvVehicleRigid::SetClipModel
================
*/
void rvVehicleRigid::SetClipModel ( void ) {
idStr clipModelName;
idTraceModel trm;
float mass;
// rebuild clipmodel
spawnArgs.GetString( "clipmodel", "", clipModelName );
// load the trace model
if ( clipModelName.Length() ) {
if ( !collisionModelManager->TrmFromModel( gameLocal.GetMapName(), clipModelName, trm ) ) {
gameLocal.Error( "rvVehicleRigid '%s': cannot load collision model %s", name.c_str(), clipModelName.c_str() );
return;
}
physicsObj.SetClipModel( new idClipModel( trm ), spawnArgs.GetFloat ( "density", "1" ) );
} else {
physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), spawnArgs.GetFloat ( "density", "1" ) );
}
if ( spawnArgs.GetFloat ( "mass", "0", mass ) && mass > 0 ) {
physicsObj.SetMass ( mass );
}
}
/*
================
rvVehicleRigid::RunPrePhysics
================
*/
void rvVehicleRigid::RunPrePhysics ( void ) {
storedVelocity = physicsObj.GetLinearVelocity();
}
/*
================
rvVehicleRigid::RunPostPhysics
================
*/
void rvVehicleRigid::RunPostPhysics ( void ) {
if ( autoCorrectionBegin + 1250 > static_cast<unsigned>( gameLocal.time )) {
autoCorrectionBegin = 0;
float lengthSq = physicsObj.GetLinearVelocity().LengthSqr();
if ( !autoCorrectionBegin && ( ( storedVelocity * 0.4f ).LengthSqr() >= lengthSq ) || ( lengthSq < 0.01f ) ) {
autoCorrectionBegin = gameLocal.time;
}
}
if ( g_debugVehicle.GetInteger() == 10 ) {
gameLocal.Printf( "Speed: %f\n", physicsObj.GetLinearVelocity().Length() );
}
}
/*
================
rvVehicleRigid::WriteToSnapshot
================
*/
void rvVehicleRigid::WriteToSnapshot( idBitMsgDelta &msg ) const {
rvVehicle::WriteToSnapshot( msg );
physicsObj.WriteToSnapshot( msg );
}
/*
================
rvVehicleRigid::ReadFromSnapshot
================
*/
void rvVehicleRigid::ReadFromSnapshot( const idBitMsgDelta &msg ) {
rvVehicle::ReadFromSnapshot( msg );
physicsObj.ReadFromSnapshot( msg );
}
/*
================
rvVehicleRigid::Save
================
*/
void rvVehicleRigid::Save ( idSaveGame *savefile ) const {
savefile->WriteVec3 ( storedVelocity ); // cnicholson: Added unsaved var
savefile->WriteStaticObject ( physicsObj );
}
/*
================
rvVehicleRigid::Restore
================
*/
void rvVehicleRigid::Restore ( idRestoreGame *savefile ) {
savefile->ReadVec3 ( storedVelocity ); // cnicholson: Added unrestored var
physicsObj.SetSelf( this );
SetClipModel ( );
savefile->ReadStaticObject ( physicsObj );
RestorePhysics( &physicsObj );
}
/*
=====================
rvVehicleRigid::SkipImpulse
=====================
*/
bool rvVehicleRigid::SkipImpulse( idEntity* ent, int id ) {
return false;
}
+45
View File
@@ -0,0 +1,45 @@
//----------------------------------------------------------------
// VehicleRigid.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#ifndef __GAME_VEHICLERIGID_H__
#define __GAME_VEHICLERIGID_H__
#ifndef __GAME_VEHICLE_H__
#include "Vehicle.h"
#endif
class rvVehicleRigid : public rvVehicle
{
public:
CLASS_PROTOTYPE( rvVehicleRigid );
rvVehicleRigid ( void );
~rvVehicleRigid ( void );
void Spawn ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
void WriteToSnapshot ( idBitMsgDelta &msg ) const;
void ReadFromSnapshot ( const idBitMsgDelta &msg );
bool SkipImpulse ( idEntity* ent, int id );
protected:
void SetClipModel ( void );
// twhitaker:
virtual void RunPrePhysics ( void );
virtual void RunPostPhysics ( void );
idVec3 storedVelocity;
// end twhitaker:
idPhysics_RigidBody physicsObj; // physics object
};
#endif // __GAME_VEHICLERIGID_H__
+123
View File
@@ -0,0 +1,123 @@
//----------------------------------------------------------------
// VehicleSplineCoupling.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "VehicleSpline.h"
CLASS_DECLARATION( rvVehicle, rvVehicleSpline )
EVENT( EV_PostSpawn, rvVehicleSpline::Event_PostSpawn )
EVENT( EV_SetSpline, rvVehicleSpline::Event_SetSpline )
EVENT( EV_DoneMoving, rvVehicleSpline::Event_DoneMoving )
END_CLASS
rvVehicleSpline::rvVehicleSpline ( void ) {
}
rvVehicleSpline::~rvVehicleSpline ( void ) {
SetPhysics( NULL );
}
void rvVehicleSpline::Spawn ( void ) {
physicsObj.SetSelf( this );
physicsObj.SetClipModel( new idClipModel(GetPhysics()->GetClipModel()), 1.0f );
physicsObj.SetContents( CONTENTS_SOLID );
physicsObj.SetClipMask( 0 );
physicsObj.SetLinearVelocity( GetPhysics()->GetLinearVelocity() );
physicsObj.SetLinearAcceleration( spawnArgs.GetFloat( "accel", "200" ) );
physicsObj.SetLinearDeceleration( spawnArgs.GetFloat( "decel", "200" ) );
viewAxis = idAngles( 0, spawnArgs.GetFloat( "angle" ) , 0 ).ToMat3();
physicsObj.SetAxis( GetPhysics()->GetAxis() * viewAxis );
physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
SetPhysics( &physicsObj );
BecomeActive( TH_THINK );
accelWithStrafe = Sign( spawnArgs.GetFloat("accel_strafe") );
idealSpeed = spawnArgs.GetFloat( "speed", "200" );
PostEventMS( &EV_PostSpawn, 0 );
}
/*
================
rvVehicleSpline::Save
================
*/
void rvVehicleSpline::Save ( idSaveGame *savefile ) const {
savefile->WriteStaticObject( physicsObj );
savefile->WriteMat3( angleOffset );
savefile->WriteFloat( idealSpeed );
savefile->WriteFloat( accelWithStrafe );
}
/*
================
rvVehicleSpline::Restore
================
*/
void rvVehicleSpline::Restore ( idRestoreGame *savefile ) {
physicsObj.SetSelf( this );
physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
savefile->ReadStaticObject ( physicsObj );
RestorePhysics ( &physicsObj );
physicsObj.EnableClip();
savefile->ReadMat3( angleOffset );
savefile->ReadFloat( idealSpeed );
savefile->ReadFloat( accelWithStrafe );
}
void rvVehicleSpline::Think( void ) {
float moveAmount = 0.0f;
if ( positions[0].IsOccupied ( ) && !IsFrozen () && IsMovementEnabled ( ) ) {
if ( accelWithStrafe != 0.0f ) {
moveAmount = positions[0].mInputCmd.rightmove * accelWithStrafe;
} else {
moveAmount = positions[0].mInputCmd.forwardmove;
}
moveAmount = Sign( moveAmount );
}
physicsObj.SetSpeed( idealSpeed * moveAmount );
rvVehicle::Think( );
}
void rvVehicleSpline::Event_PostSpawn( void ) {
idStr splinePath;
if ( spawnArgs.GetString( "spline_path", "", splinePath ) ) {
Event_SetSpline( gameLocal.FindEntity( splinePath.c_str() ) );
} else {
gameLocal.Warning( "\"spline_path\" key not found on %s (rvVehicleSpline)", this->GetName() );
}
}
void rvVehicleSpline::Event_SetSpline ( idEntity * spline ) {
if ( spline && spline->IsType( idSplinePath::GetClassType() ) ) {
physicsObj.SetSplineEntity( static_cast< idSplinePath * >( spline ) );
//HACK: force an intitial physics update so that the object orients itself with the spline
//TEMP: this should be fixed after the build on friday (Jan 28, 2005)
physicsObj.SetSpeed( 0.1f );
RunPhysics();
//END HACK
}
}
void rvVehicleSpline::Event_DoneMoving() {
idThread::ReturnInt( true );
}
+34
View File
@@ -0,0 +1,34 @@
//----------------------------------------------------------------
// VehicleSpline.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#ifndef __GAME_VEHICLESPLINECOUPLING_H__
#define __GAME_VEHICLESPLINECOUPLING_H__
class rvVehicleSpline : public rvVehicle {
public:
CLASS_PROTOTYPE( rvVehicleSpline );
rvVehicleSpline ( void );
~rvVehicleSpline ( void );
void Spawn ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
void Think ( void );
void Event_PostSpawn ( void );
void Event_SetSpline ( idEntity * spline );
void Event_DoneMoving ( void );
protected:
rvPhysics_Spline physicsObj;
idMat3 angleOffset;
float idealSpeed;
float accelWithStrafe;
};
#endif // __GAME_VEHICLESPLINECOUPLING_H__
+118
View File
@@ -0,0 +1,118 @@
//----------------------------------------------------------------
// VehicleStatic.cpp
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "VehicleStatic.h"
CLASS_DECLARATION( rvVehicle, rvVehicleStatic )
EVENT( AI_ScriptedAnim, rvVehicleStatic::Event_ScriptedAnim )
EVENT( AI_ScriptedDone, rvVehicleStatic::Event_ScriptedDone )
EVENT( AI_ScriptedStop, rvVehicleStatic::Event_ScriptedStop )
END_CLASS
rvVehicleStatic::rvVehicleStatic ( void ) {
}
rvVehicleStatic::~rvVehicleStatic ( void ) {
}
/*
================
rvVehicleStatic::Spawn
================
*/
void rvVehicleStatic::Spawn( void ) {
BecomeActive( TH_THINK );
}
/*
================
rvVehicleStatic::AddDriver
================
*/
int rvVehicleStatic::AddDriver ( int position, idActor* driver ) {
int pos = rvVehicle::AddDriver( position, driver );
if( pos < 0 ) {
return pos;
}
if( GetHud() ) {
GetHud()->HandleNamedEvent( "hideGunInfo" );
}
return pos;
}
/*
================
rvVehicleStatic::RemoveDriver
================
*/
bool rvVehicleStatic::RemoveDriver ( int position, bool force ) {
bool result = rvVehicle::RemoveDriver( position, force );
if( !result ) {
return result;
}
if( GetHud() ) {
GetHud()->HandleNamedEvent( "showGunInfo" );
}
return result;
}
/*
================
rvVehicleStatic::UpdateHUD
================
*/
void rvVehicleStatic::UpdateHUD( idActor* driver, idUserInterface* gui ) {
if( driver && driver->IsType( idPlayer::GetClassType() ) ) {
static_cast<idPlayer*>(driver)->UpdateHudStats( gui );
}
}
/*
================
rvVehicleStatic::Event_ScriptedAnim
================
*/
void rvVehicleStatic::Event_ScriptedAnim( const char* animname, int blendFrames, bool loop, bool endWithIdle ) {
vfl.endWithIdle = endWithIdle;
if ( loop ) {
PlayCycle ( ANIMCHANNEL_TORSO, animname, blendFrames );
} else {
PlayAnim ( ANIMCHANNEL_TORSO, animname, blendFrames );
}
vfl.scripted = true;
}
/*
================
rvVehicleStatic::Event_ScriptedDone
================
*/
void rvVehicleStatic::Event_ScriptedDone( void ) {
idThread::ReturnInt( !vfl.scripted );
}
/*
================
rvVehicleStatic::Event_ScriptedStop
================
*/
void rvVehicleStatic::Event_ScriptedStop( void ) {
vfl.scripted = false;
if ( vfl.endWithIdle ) {
PlayCycle( ANIMCHANNEL_TORSO, spawnArgs.GetString( "idle" ), 2 );
}
}
+35
View File
@@ -0,0 +1,35 @@
//----------------------------------------------------------------
// VehicleStatic.h
//
// Copyright 2002-2004 Raven Software
//----------------------------------------------------------------
#ifndef __GAME_VEHICLESTATIC_H__
#define __GAME_VEHICLESTATIC_H__
#ifndef __GAME_VEHICLE_H__
#include "Vehicle.h"
#endif
class rvVehicleStatic : public rvVehicle
{
public:
CLASS_PROTOTYPE( rvVehicleStatic );
rvVehicleStatic ( void );
~rvVehicleStatic ( void );
void Spawn ( void );
virtual int AddDriver ( int position, idActor* driver );
virtual bool RemoveDriver ( int position, bool force = false );
virtual void UpdateHUD ( idActor* driver, idUserInterface* gui );
void Event_ScriptedAnim ( const char* animname, int blendFrames, bool loop, bool endWithIdle );
void Event_ScriptedDone ( void );
void Event_ScriptedStop ( void );
};
#endif // __GAME_VEHICLESTATIC_H__
+177
View File
@@ -0,0 +1,177 @@
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "VehicleStatic.h"
class rvVehicleDropPod : public rvVehicleStatic {
public:
CLASS_PROTOTYPE( rvVehicleDropPod );
rvVehicleDropPod ( void );
void Spawn ( void );
virtual bool GetPhysicsToVisualTransform ( idVec3 &origin, idMat3 &axis );
private:
stateResult_t State_Idle ( const stateParms_t& parms );
stateResult_t State_IdleThink ( const stateParms_t& parms );
stateResult_t State_IdleOffline ( const stateParms_t& parms );
stateResult_t State_ScriptedAnim ( const stateParms_t& parms );
void Event_ScriptedAnim ( const char* animname, int blendFrames, bool loop, bool endWithIdle );
void Event_ScriptedDone ( void );
void Event_ScriptedStop ( void );
CLASS_STATES_PROTOTYPE ( rvVehicleDropPod );
};
CLASS_DECLARATION( rvVehicleStatic, rvVehicleDropPod )
EVENT( AI_ScriptedAnim, rvVehicleDropPod::Event_ScriptedAnim )
EVENT( AI_ScriptedDone, rvVehicleDropPod::Event_ScriptedDone )
EVENT( AI_ScriptedStop, rvVehicleDropPod::Event_ScriptedStop )
END_CLASS
/*
================
rvVehicleDropPod::rvVehicleDropPod
================
*/
rvVehicleDropPod::rvVehicleDropPod ( void ) {
}
/*
================
rvVehicleDropPod::Spawn
================
*/
void rvVehicleDropPod::Spawn ( void ) {
SetAnimState ( ANIMCHANNEL_LEGS, "State_IdleOffline", 0 );
}
/*
===============================================================================
States
===============================================================================
*/
CLASS_STATES_DECLARATION ( rvVehicleDropPod )
STATE ( "State_Idle", rvVehicleDropPod::State_Idle )
STATE ( "State_IdleThink", rvVehicleDropPod::State_IdleThink )
STATE ( "State_IdleOffline", rvVehicleDropPod::State_IdleOffline )
STATE ( "State_ScriptedAnim", rvVehicleDropPod::State_ScriptedAnim )
END_CLASS_STATES
/*
================
rvVehicleDropPod::State_IdleOffline
================
*/
stateResult_t rvVehicleDropPod::State_IdleOffline ( const stateParms_t& parms ) {
vfl.frozen = true;
PlayCycle ( ANIMCHANNEL_LEGS, "idle", parms.blendFrames );
PostAnimState ( ANIMCHANNEL_LEGS, "Wait_Driver", 0 );
PostAnimState ( ANIMCHANNEL_LEGS, "State_Idle", 0 );
return SRESULT_DONE;
}
/*
================
rvVehicleDropPod::State_Idle
================
*/
stateResult_t rvVehicleDropPod::State_Idle ( const stateParms_t& parms ) {
if ( SRESULT_WAIT != State_IdleThink ( parms ) ) {
return SRESULT_DONE;
}
return SRESULT_DONE;
}
/*
================
rvVehicleDropPod::State_IdleThink
================
*/
stateResult_t rvVehicleDropPod::State_IdleThink ( const stateParms_t& parms ) {
if ( !vfl.driver ) {
PostAnimState ( ANIMCHANNEL_LEGS, "State_IdleOffline", parms.blendFrames );
return SRESULT_DONE;
}
return SRESULT_WAIT;
}
/*
================
rvVehicleDropPod::State_ScriptedAnim
================
*/
stateResult_t rvVehicleDropPod::State_ScriptedAnim ( const stateParms_t& parms ) {
if ( !AnimDone ( ANIMCHANNEL_LEGS, parms.blendFrames ) ) {
return SRESULT_WAIT;
}
Event_ScriptedStop();
return SRESULT_DONE;
}
/*
================
rvVehicleDropPod::Event_ScriptedAnim
================
*/
void rvVehicleDropPod::Event_ScriptedAnim( const char* animname, int blendFrames, bool loop, bool endWithIdle ) {
vfl.endWithIdle = endWithIdle;
if ( loop ) {
PlayCycle ( ANIMCHANNEL_LEGS, animname, blendFrames );
} else {
PlayAnim ( ANIMCHANNEL_LEGS, animname, blendFrames );
}
SetAnimState ( ANIMCHANNEL_LEGS, "State_ScriptedAnim", blendFrames );
vfl.scripted = true;
}
/*
================
rvVehicleDropPod::Event_ScriptedDone
================
*/
void rvVehicleDropPod::Event_ScriptedDone( void ) {
idThread::ReturnInt( !vfl.scripted );
}
/*
================
rvVehicleDropPod::Event_ScriptedStop
================
*/
void rvVehicleDropPod::Event_ScriptedStop( void ) {
vfl.scripted = false;
if ( vfl.endWithIdle ) {
SetAnimState ( ANIMCHANNEL_LEGS, "State_Idle", 1 );
}
}
/*
================
rvVehicleDropPod::GetPhysicsToVisualTransform
================
*/
bool rvVehicleDropPod::GetPhysicsToVisualTransform ( idVec3 &origin, idMat3 &axis ) {
// if ( GetBindMaster() ) {
// axis = viewAxis;
// origin.Zero();
// return true;
// }
return false;
}
+593
View File
@@ -0,0 +1,593 @@
#include "precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "VehicleAnimated.h"
class rvVehicleWalker : public rvVehicleAnimated {
public:
CLASS_PROTOTYPE( rvVehicleWalker );
rvVehicleWalker ( void );
void Think ( void );
void Spawn ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
virtual void UpdateState ( void );
virtual void SetInput ( int position, const usercmd_t& cmd, const idAngles& newAngles );
const char* stopAnimName;
virtual bool FindClearExitPoint ( int pos, idVec3& origin, idMat3& axis ) const;
private:
void HandleStrafing ( void );
stateResult_t Frame_ForwardRight ( int );
stateResult_t Frame_ForwardLeft ( int );
stateResult_t Frame_BackwardRight ( int );
stateResult_t Frame_BackwardLeft ( int );
stateResult_t State_Wait_OnlineAnim ( const stateParms_t& parms );
stateResult_t State_Idle ( const stateParms_t& parms );
stateResult_t State_IdleThink ( const stateParms_t& parms );
stateResult_t State_IdleOffline ( const stateParms_t& parms );
stateResult_t State_Offline ( const stateParms_t& parms );
stateResult_t State_Online ( const stateParms_t& parms );
stateResult_t State_ForwardStart ( const stateParms_t& parms );
stateResult_t State_Forward ( const stateParms_t& parms );
stateResult_t State_BackwardStart ( const stateParms_t& parms );
stateResult_t State_Backward ( const stateParms_t& parms );
stateResult_t State_Stop ( const stateParms_t& parms );
stateResult_t State_Turn ( const stateParms_t& parms );
stateResult_t State_TurnThink ( const stateParms_t& parms );
stateResult_t State_ScriptedAnim ( const stateParms_t& parms );
void Event_ScriptedAnim ( const char* animname, int blendFrames, bool loop, bool endWithIdle );
void Event_ScriptedDone ( void );
void Event_ScriptedStop ( void );
CLASS_STATES_PROTOTYPE ( rvVehicleWalker );
};
CLASS_DECLARATION( rvVehicleAnimated, rvVehicleWalker )
EVENT( AI_ScriptedAnim, rvVehicleWalker::Event_ScriptedAnim )
EVENT( AI_ScriptedDone, rvVehicleWalker::Event_ScriptedDone )
EVENT( AI_ScriptedStop, rvVehicleWalker::Event_ScriptedStop )
END_CLASS
/*
================
rvVehicleWalker::rvVehicleWalker
================
*/
rvVehicleWalker::rvVehicleWalker ( void ) {
stopAnimName = "";
}
/*
================
rvVehicleWalker::Think
================
*/
void rvVehicleWalker::Think ( void ) {
rvVehicleAnimated::Think();
if ( !HasDrivers() || IsStalled() ) {
return;
}
idVec3 delta;
animator.GetDelta( gameLocal.time - gameLocal.GetMSec(), gameLocal.time, delta );
if ( delta.LengthSqr() > 0.1f ) {
gameLocal.RadiusDamage( GetOrigin(), this, this, this, this, spawnArgs.GetString( "def_stompDamage", "damage_Smallexplosion" ) );
}
}
/*
================
rvVehicleWalker::Spawn
================
*/
void rvVehicleWalker::Spawn ( void ) {
SetAnimState ( ANIMCHANNEL_LEGS, "State_IdleOffline", 0 );
}
/*
================
rvVehicleWalker::Save
================
*/
void rvVehicleWalker::Save ( idSaveGame *savefile ) const {
savefile->WriteString( stopAnimName );
}
/*
================
rvVehicleWalker::Restore
================
*/
void rvVehicleWalker::Restore ( idRestoreGame *savefile ) {
//twhitaker: I just happened to see this, while going through this code which I originally wrote (at 3am or so).
//TODO: fix this. Make stopAnimName an idStr?
idStr str;
savefile->ReadString( str );
stopAnimName = str;
}
/*
================
rvVehicleWalker::UpdateState
================
*/
void rvVehicleWalker::UpdateState ( void ) {
rvVehiclePosition& pos = positions[0];
usercmd_t& cmd = pos.mInputCmd;
vfl.driver = pos.IsOccupied();
vfl.forward = (vfl.driver && cmd.forwardmove > 0);
vfl.backward = (vfl.driver && cmd.forwardmove < 0);
vfl.right = (vfl.driver && cmd.rightmove < 0);
vfl.left = (vfl.driver && cmd.rightmove > 0);
vfl.strafe = (vfl.driver && cmd.buttons & BUTTON_STRAFE );
if ( g_vehicleMode.GetInteger() != 0 ) {
vfl.strafe = !vfl.strafe;
}
}
/*
================
rvVehicleWalker::SetInput
================
*/
void rvVehicleWalker::SetInput ( int position, const usercmd_t& cmd, const idAngles& newAngles ) {
usercmd_t* pcmd = const_cast<usercmd_t*>( &cmd );
pcmd->rightmove *= -1;
GetPosition(position)->SetInput ( cmd, newAngles );
}
/*
================
rvVehicleWalker::HandleStrafing
================
*/
void rvVehicleWalker::HandleStrafing ( void ) {
if ( vfl.right ) {
additionalDelta -= spawnArgs.GetVector( "strafe_delta", "0 0 1.2" );
}
if ( vfl.left ) {
additionalDelta += spawnArgs.GetVector( "strafe_delta", "0 0 1.2" );
}
}
// mekberg: overloaded this because physics bounds code is significantly different
/*
=====================
rvVehicleWalker::FindClearExitPoint
=====================
*/
// FIXME: this whole function could be cleaned up
bool rvVehicleWalker::FindClearExitPoint( int pos, idVec3& origin, idMat3& axis ) const {
trace_t trace;
const rvVehiclePosition* position = GetPosition( pos );
idActor* driver = position->GetDriver();
idVec3 end;
idVec3 traceOffsetPoints[4];
const float error = 1.1f;
origin.Zero();
axis.Identity();
idMat3 driverAxis = driver->viewAxis;
idVec3 driverOrigin = driver->GetPhysics()->GetOrigin();
idMat3 vehicleAxis = position->GetEyeAxis();
idVec3 vehicleOrigin = GetPhysics()->GetOrigin();
idBounds driverBounds( driver->GetPhysics()->GetBounds() );
idBounds vehicleBounds( GetPhysics()->GetBounds() );
idBounds driverAbsBounds;
idBounds vehicleAbsBounds;
vehicleAbsBounds.FromTransformedBounds( vehicleBounds, vehicleOrigin, GetPhysics()->GetAxis() );
if( position->fl.driverVisible ) {
// May want to do this even if the driver isn't visible
if( position->mExitPosOffset.LengthSqr() > VECTOR_EPSILON ) {
axis = GetPhysics()->GetAxis() * position->mExitAxisOffset;
origin = vehicleOrigin + position->mExitPosOffset * axis;
} else {
origin = driverOrigin;
axis = (driver->IsBoundTo(this)) ? vehicleAxis : driverAxis;
}
return true;
}
// Build list
// FIXME: try and find a cleaner way to do this
traceOffsetPoints[ 0 ] = vehicleBounds.FindVectorToEdge( vehicleAxis[ 1 ] ) - driverBounds.FindVectorToEdge( -vehicleAxis[ 1 ] );
traceOffsetPoints[ 1 ] = vehicleBounds.FindVectorToEdge( -vehicleAxis[ 1 ] ) - driverBounds.FindVectorToEdge( vehicleAxis[ 1 ] );
traceOffsetPoints[ 2 ] = vehicleBounds.FindVectorToEdge( vehicleAxis[ 0 ] ) - driverBounds.FindVectorToEdge( -vehicleAxis[ 0 ] );
traceOffsetPoints[ 3 ] = vehicleBounds.FindVectorToEdge( -vehicleAxis[ 0 ] ) - driverBounds.FindVectorToEdge( vehicleAxis[ 0 ] );
for( int ix = 0; ix < 4; ++ix ) {
//Try all four sides and on top if need be
end = vehicleOrigin + traceOffsetPoints[ ix ] * error;
// RAVEN BEGIN
// ddynerman: multiple clip worlds
gameLocal.Translation( this, trace, vehicleOrigin, end, driver->GetPhysics()->GetClipModel(), driverAxis, driver->GetPhysics()->GetClipMask(), this, driver );
// RAVEN END
driverAbsBounds.FromTransformedBounds( driverBounds, trace.endpos, driverAxis );
if( trace.fraction > 0.0f && !driverAbsBounds.IntersectsBounds(vehicleAbsBounds) ) {
origin = trace.endpos;
axis = vehicleAxis;
return true;
}
}
return false;
}
/*
===============================================================================
States
===============================================================================
*/
CLASS_STATES_DECLARATION ( rvVehicleWalker )
STATE ( "ForwardLeft", rvVehicleWalker::Frame_ForwardLeft )
STATE ( "ForwardRight", rvVehicleWalker::Frame_ForwardRight )
STATE ( "BackwardLeft", rvVehicleWalker::Frame_BackwardLeft )
STATE ( "BackwardRight", rvVehicleWalker::Frame_BackwardRight )
STATE ( "Wait_OnlineAnim", rvVehicleWalker::State_Wait_OnlineAnim )
STATE ( "State_Idle", rvVehicleWalker::State_Idle )
STATE ( "State_IdleThink", rvVehicleWalker::State_IdleThink )
STATE ( "State_IdleOffline", rvVehicleWalker::State_IdleOffline )
STATE ( "State_Offline", rvVehicleWalker::State_Offline )
STATE ( "State_Online", rvVehicleWalker::State_Online )
STATE ( "State_ForwardStart", rvVehicleWalker::State_ForwardStart )
STATE ( "State_Forward", rvVehicleWalker::State_Forward )
STATE ( "State_BackwardStart", rvVehicleWalker::State_BackwardStart )
STATE ( "State_Backward", rvVehicleWalker::State_Backward )
STATE ( "State_Stop", rvVehicleWalker::State_Stop )
STATE ( "State_Turn", rvVehicleWalker::State_Turn )
STATE ( "State_TurnThink", rvVehicleWalker::State_TurnThink )
STATE ( "State_ScriptedAnim", rvVehicleWalker::State_ScriptedAnim )
END_CLASS_STATES
/*
================
rvVehicleWalker::State_IdleOffline
================
*/
stateResult_t rvVehicleWalker::State_IdleOffline ( const stateParms_t& parms ) {
vfl.frozen = true;
PlayCycle ( ANIMCHANNEL_LEGS, "idle_offline", parms.blendFrames );
PostAnimState ( ANIMCHANNEL_LEGS, "Wait_Driver", 2 );
PostAnimState ( ANIMCHANNEL_LEGS, "State_Online", 2 );
return SRESULT_DONE;
}
/*
================
rvVehicleWalker::State_Online
================
*/
stateResult_t rvVehicleWalker::State_Online ( const stateParms_t& parms ) {
vfl.frozen = false;
PlayAnim ( ANIMCHANNEL_LEGS, "start", parms.blendFrames );
PostAnimState ( ANIMCHANNEL_LEGS, "Wait_OnlineAnim", 4 );
PostAnimState ( ANIMCHANNEL_LEGS, "State_Idle", 4 );
return SRESULT_DONE;
}
/*
================
rvVehicleWalker::State_Offline
================
*/
stateResult_t rvVehicleWalker::State_Offline ( const stateParms_t& parms ) {
PlayAnim ( ANIMCHANNEL_LEGS, "stop", parms.blendFrames );
PostAnimState ( ANIMCHANNEL_LEGS, "Wait_TorsoAnim", 4 );
PostAnimState ( ANIMCHANNEL_LEGS, "State_IdleOffline", 4 );
return SRESULT_DONE;
}
/*
================
rvVehicleWalker::State_Idle
================
*/
stateResult_t rvVehicleWalker::State_Idle ( const stateParms_t& parms ) {
if ( SRESULT_WAIT != State_IdleThink ( parms ) ) {
return SRESULT_DONE;
}
PlayCycle( ANIMCHANNEL_LEGS, "idle", parms.blendFrames );
PostAnimState ( ANIMCHANNEL_LEGS, "State_IdleThink", 2 );
return SRESULT_DONE;
}
/*
================
rvVehicleWalker::State_Idle
================
*/
stateResult_t rvVehicleWalker::State_IdleThink ( const stateParms_t& parms ) {
if ( !vfl.driver || vfl.stalled ) {
PostAnimState ( ANIMCHANNEL_LEGS, "State_Offline", parms.blendFrames );
return SRESULT_DONE;
}
if ( IsMovementEnabled ( ) ) {
if ( vfl.forward ) {
PostAnimState ( ANIMCHANNEL_LEGS, "State_ForwardStart", 2 );
return SRESULT_DONE;
}
if ( vfl.backward ) {
PostAnimState ( ANIMCHANNEL_LEGS, "State_BackwardStart", 2 );
return SRESULT_DONE;
}
if ( vfl.right || vfl.left ) {
PostAnimState ( ANIMCHANNEL_LEGS, "State_Turn", 2 );
return SRESULT_DONE;
}
}
return SRESULT_WAIT;
}
/*
================
rvVehicleWalker::State_ForwardStart
================
*/
stateResult_t rvVehicleWalker::State_ForwardStart ( const stateParms_t& parms ) {
PlayAnim ( ANIMCHANNEL_LEGS, "forward_start", 2 );
PostAnimState ( ANIMCHANNEL_LEGS, "Wait_TorsoAnim", 2 );
PostAnimState ( ANIMCHANNEL_LEGS, "State_Forward", 2 );
return SRESULT_DONE;
}
stateResult_t rvVehicleWalker::State_Forward ( const stateParms_t& parms ) {
// If not moving anymore by the time we get here just play the stop anim
if ( !vfl.forward ) {
stopAnimName = "forward_stop_leftmid";
SetAnimState ( ANIMCHANNEL_LEGS, "State_Stop", 4 );
return SRESULT_DONE;
}
if ( !parms.stage ) {
PlayCycle( ANIMCHANNEL_LEGS, "forward", 2 );
return SRESULT_STAGE(parms.stage + 1);
}
if ( AnimDone( ANIMCHANNEL_LEGS, 2 ) ) {
return SRESULT_DONE;
}
HandleStrafing();
return SRESULT_WAIT;
}
/*
================
rvVehicleWalker::State_BackwardStart
================
*/
stateResult_t rvVehicleWalker::State_BackwardStart ( const stateParms_t& parms ) {
PlayAnim ( ANIMCHANNEL_LEGS, "backward_start", parms.blendFrames );
PostAnimState ( ANIMCHANNEL_LEGS, "Wait_TorsoAnim", 2 );
PostAnimState ( ANIMCHANNEL_LEGS, "State_Backward", 2 );
return SRESULT_DONE;
}
stateResult_t rvVehicleWalker::State_Backward ( const stateParms_t& parms ) {
// If not moving anymore by the time we get here just play the stop anim
if ( !vfl.backward ) {
stopAnimName = "backward_stop_leftmid";
SetAnimState ( ANIMCHANNEL_LEGS, "State_Stop", 2 );
return SRESULT_DONE;
}
if ( !parms.stage ) {
PlayCycle( ANIMCHANNEL_LEGS, "backward", 2 );
return SRESULT_STAGE(parms.stage + 1);
}
if ( AnimDone( ANIMCHANNEL_LEGS, 2 ) ) {
return SRESULT_DONE;
}
HandleStrafing();
return SRESULT_WAIT;
}
/*
================
rvVehicleWalker::State_Stop
================
*/
stateResult_t rvVehicleWalker::State_Stop ( const stateParms_t& parms ) {
PlayAnim ( ANIMCHANNEL_LEGS, stopAnimName, parms.blendFrames );
PostAnimState ( ANIMCHANNEL_LEGS, "Wait_TorsoAnim", 2 );
PostAnimState ( ANIMCHANNEL_LEGS, "State_Idle", 2 );
return SRESULT_DONE;
}
/*
================
rvVehicleWalker::State_Turn
================
*/
stateResult_t rvVehicleWalker::State_Turn ( const stateParms_t& parms ) {
if ( vfl.left ) {
PlayAnim ( ANIMCHANNEL_LEGS, "turn_left", parms.blendFrames );
} else if ( vfl.right ) {
PlayAnim ( ANIMCHANNEL_LEGS, "turn_right", parms.blendFrames );
} else {
PostAnimState ( ANIMCHANNEL_LEGS, "State_Idle", parms.blendFrames );
return SRESULT_DONE;
}
PostAnimState ( ANIMCHANNEL_LEGS, "State_TurnThink", 16 );
return SRESULT_DONE;
}
/*
================
rvVehicleWalker::State_TurnThink
================
*/
stateResult_t rvVehicleWalker::State_TurnThink ( const stateParms_t& parms ) {
// If moving again bail on the turn, reguardless of whether its in mid animation
if ( vfl.forward || vfl.backward ) {
PostAnimState ( ANIMCHANNEL_LEGS, "State_Idle", parms.blendFrames );
return SRESULT_DONE;
}
// If the animation is done then repeat
if ( AnimDone ( ANIMCHANNEL_LEGS, 8 ) ){
PostAnimState ( ANIMCHANNEL_LEGS, "State_Turn", 8 );
return SRESULT_DONE;
}
HandleStrafing();
return SRESULT_WAIT;
}
/*
================
rvVehicleWalker::Frame_ForwardLeft
================
*/
stateResult_t rvVehicleWalker::Frame_ForwardLeft ( int ) {
if ( !vfl.forward ) {
stopAnimName = "forward_stop_left";
SetAnimState ( ANIMCHANNEL_LEGS, "State_Stop", 2 );
}
return SRESULT_OK;
}
/*
================
rvVehicleWalker::Frame_ForwardRight
================
*/
stateResult_t rvVehicleWalker::Frame_ForwardRight ( int ) {
if ( !vfl.forward ) {
stopAnimName = "forward_stop_right";
SetAnimState ( ANIMCHANNEL_LEGS, "State_Stop", 2 );
}
return SRESULT_OK;
}
/*
================
rvVehicleWalker::Frame_BackwardLeft
================
*/
stateResult_t rvVehicleWalker::Frame_BackwardLeft ( int ) {
if ( !vfl.backward ) {
stopAnimName = "backward_stop_left";
SetAnimState ( ANIMCHANNEL_LEGS, "State_Stop", 2 );
}
return SRESULT_OK;
}
/*
================
rvVehicleWalker::Frame_BackwardRight
================
*/
stateResult_t rvVehicleWalker::Frame_BackwardRight ( int ) {
if ( !vfl.backward ) {
stopAnimName = "backward_stop_right";
SetAnimState ( ANIMCHANNEL_LEGS, "State_Stop", 2 );
}
return SRESULT_OK;
}
/*
================
rvVehicleWalker::State_Wait_OnlineAnim
================
*/
stateResult_t rvVehicleWalker::State_Wait_OnlineAnim ( const stateParms_t& parms ) {
if ( !AnimDone ( ANIMCHANNEL_LEGS, parms.blendFrames ) && vfl.driver ) {
return SRESULT_WAIT;
}
return SRESULT_DONE;
}
/*
================
rvVehicleWalker::State_ScriptedAnim
================
*/
stateResult_t rvVehicleWalker::State_ScriptedAnim ( const stateParms_t& parms ) {
if ( !AnimDone ( ANIMCHANNEL_LEGS, parms.blendFrames ) ) {
return SRESULT_WAIT;
}
Event_ScriptedStop();
return SRESULT_DONE;
}
/*
================
rvVehicleWalker::Event_ScriptedAnim
================
*/
void rvVehicleWalker::Event_ScriptedAnim( const char* animname, int blendFrames, bool loop, bool endWithIdle ) {
vfl.endWithIdle = endWithIdle;
if ( loop ) {
PlayCycle ( ANIMCHANNEL_LEGS, animname, blendFrames );
} else {
PlayAnim ( ANIMCHANNEL_LEGS, animname, blendFrames );
}
SetAnimState ( ANIMCHANNEL_LEGS, "State_ScriptedAnim", blendFrames );
vfl.scripted = true;
}
/*
================
rvVehicleWalker::Event_ScriptedDone
================
*/
void rvVehicleWalker::Event_ScriptedDone( void ) {
idThread::ReturnInt( !vfl.scripted );
}
/*
================
rvVehicleWalker::Event_ScriptedStop
================
*/
void rvVehicleWalker::Event_ScriptedStop( void ) {
vfl.scripted = false;
if ( vfl.endWithIdle ) {
SetAnimState ( ANIMCHANNEL_LEGS, "State_Idle", 2 );
}
}