1102 lines
34 KiB
C++
1102 lines
34 KiB
C++
//=============================================================================
|
|
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
|
|
//
|
|
// File:
|
|
//
|
|
// Description: Implementation of class Avatar
|
|
//
|
|
// History: 4/3/2002 + Created -- TBJ
|
|
//
|
|
//=============================================================================
|
|
|
|
//========================================
|
|
// System Includes
|
|
//========================================
|
|
// Foundation Tech
|
|
#include <raddebug.hpp>
|
|
|
|
//========================================
|
|
// Project Includes
|
|
//========================================
|
|
#include <worldsim/avatar.h>
|
|
#include <worldsim/character/character.h>
|
|
#include <worldsim/character/charactertarget.h>
|
|
#include <worldsim/character/charactermanager.h>
|
|
#include <worldsim/character/charactermappable.h>
|
|
#include <worldsim/character/charactercontroller.h>
|
|
#include <worldsim/vehiclecentral.h>
|
|
#include <worldsim/redbrick/geometryvehicle.h>
|
|
#include <worldsim/redbrick/vehicle.h>
|
|
#include <worldsim/redbrick/vehiclecontroller/vehiclecontroller.h>
|
|
#include <worldsim/redbrick/vehiclecontroller/humanvehiclecontroller.h>
|
|
#include <worldsim/redbrick/vehiclecontroller/vehiclemappable.h>
|
|
#include <input/inputmanager.h>
|
|
|
|
#include <ai/vehicle/vehicleai.h>
|
|
|
|
#include <roads/geometry.h>
|
|
#include <roads/road.h>
|
|
|
|
#include <camera/supercammanager.h>
|
|
#include <camera/supercamcentral.h>
|
|
|
|
#include <roads/intersection.h>
|
|
#include <presentation/gui/ingame/guimanageringame.h>
|
|
#include <presentation/gui/ingame/guiscreenhud.h>
|
|
#include <memory/srrmemory.h>
|
|
#include <mission/gameplaymanager.h>
|
|
|
|
#include <gameflow/gameflow.h>
|
|
#include <supersprint/supersprintmanager.h>
|
|
#include <worldsim/traffic/trafficmanager.h>
|
|
//******************************************************************************
|
|
//
|
|
// Global Data, Local Data, Local Classes
|
|
//
|
|
//******************************************************************************
|
|
|
|
//
|
|
// If true, display avatar coordinates on screen
|
|
//
|
|
bool Avatar::s_displayCoordinates = false;
|
|
|
|
struct AvatarInputManager
|
|
{
|
|
AvatarInputManager( void )
|
|
:
|
|
mVehicleMappableHandle( -1 ),
|
|
#ifdef RAD_PS2
|
|
mVehicleMappableHandleWheel0( -1 ),
|
|
mVehicleMappableHandleWheel1( -1 ),
|
|
#endif
|
|
mCharacterMappableHandle( -1 )
|
|
{
|
|
HeapMgr()->PushHeap (GMA_LEVEL_OTHER);
|
|
|
|
mpVehicleMappable = new VehicleMappable;
|
|
mpVehicleMappable->AddRef();
|
|
|
|
#ifdef RAD_PS2
|
|
mpVehicleMappableUSB0 = new VehicleMappable;
|
|
mpVehicleMappableUSB0->AddRef();
|
|
|
|
mpVehicleMappableUSB1 = new VehicleMappable;
|
|
mpVehicleMappableUSB1->AddRef();
|
|
#endif
|
|
|
|
mpHumanVehicleController = new HumanVehicleController;
|
|
mpHumanVehicleController->AddRef();
|
|
|
|
mpInCarCharacterMappable = new InCarCharacterMappable;
|
|
mpInCarCharacterMappable->AddRef();
|
|
|
|
mpBipedCharacterMappable = new BipedCharacterMappable;
|
|
mpBipedCharacterMappable->AddRef();
|
|
|
|
mpCameraRelativeCharacterController = new CameraRelativeCharacterController;
|
|
mpCameraRelativeCharacterController->AddRef();
|
|
|
|
HeapMgr()->PopHeap (GMA_LEVEL_OTHER);
|
|
}
|
|
~AvatarInputManager( void )
|
|
{
|
|
mpVehicleMappable->ReleaseController();
|
|
mpVehicleMappable->Release();
|
|
|
|
#ifdef RAD_PS2
|
|
mpVehicleMappableUSB0->Release();
|
|
mpVehicleMappableUSB1->Release();
|
|
#endif
|
|
|
|
mpHumanVehicleController->ReleaseVehicleMappable();
|
|
mpHumanVehicleController->Release();
|
|
|
|
mpInCarCharacterMappable->SetCharacterController( NULL );
|
|
mpInCarCharacterMappable->Release();
|
|
|
|
mpBipedCharacterMappable->SetCharacterController( NULL );
|
|
mpBipedCharacterMappable->Release();
|
|
|
|
mpCameraRelativeCharacterController->SetCamera (0);
|
|
mpCameraRelativeCharacterController->Release();
|
|
|
|
int x =5;
|
|
}
|
|
VehicleMappable* mpVehicleMappable;
|
|
VehicleMappable* mpVehicleMappableUSB0;
|
|
VehicleMappable* mpVehicleMappableUSB1;
|
|
HumanVehicleController* mpHumanVehicleController;
|
|
InCarCharacterMappable* mpInCarCharacterMappable;
|
|
BipedCharacterMappable* mpBipedCharacterMappable;
|
|
CameraRelativeCharacterController* mpCameraRelativeCharacterController;
|
|
int mVehicleMappableHandle;
|
|
int mVehicleMappableHandleWheel0;
|
|
int mVehicleMappableHandleWheel1;
|
|
int mCharacterMappableHandle;
|
|
};
|
|
|
|
|
|
void UnRegisterMappableHandle( int controllerId, int& handle )
|
|
{
|
|
if ( handle > -1 )
|
|
{
|
|
// Detach the mappable.
|
|
//
|
|
InputManager::GetInstance( )->UnregisterMappable( controllerId, handle );
|
|
handle = -1;
|
|
}
|
|
}
|
|
//******************************************************************************
|
|
//
|
|
// Public Member Functions
|
|
//
|
|
//******************************************************************************
|
|
|
|
//==============================================================================
|
|
// Avatar::Avatar
|
|
//==============================================================================
|
|
// Description: Constructor.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: N/A.
|
|
//
|
|
//==============================================================================
|
|
Avatar::Avatar()
|
|
:
|
|
mHasBeenUpdatedThisFrame( false ),
|
|
mLastRoadSegment( NULL ),
|
|
mLastRoadSegmentT( 0.0f ),
|
|
mLastRoadT( 0.0f ),
|
|
mControllerId( INVALID_CONTROLLER ),
|
|
mPlayerId( 0 ),
|
|
mpCharacter( 0 ),
|
|
mpVehicle( 0 ),
|
|
mpAvatarInputManager( 0 )
|
|
{
|
|
mLastPathElement.elem = NULL;
|
|
|
|
mpAvatarInputManager = new AvatarInputManager;
|
|
|
|
GetCheatInputSystem()->RegisterCallback( this );
|
|
|
|
//
|
|
// Just in case the cheat is set before object creation
|
|
//
|
|
if( GetCheatInputSystem()->IsCheatEnabled( CHEAT_ID_SHOW_AVATAR_POSITION ) )
|
|
{
|
|
s_displayCoordinates = true;
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// Avatar::~Avatar
|
|
//==============================================================================
|
|
// Description: Destructor.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: N/A.
|
|
//
|
|
//==============================================================================
|
|
Avatar::~Avatar()
|
|
{
|
|
Destroy( );
|
|
|
|
if ( mpAvatarInputManager )
|
|
{
|
|
delete mpAvatarInputManager;
|
|
mpAvatarInputManager = 0;
|
|
}
|
|
|
|
GetCheatInputSystem()->UnregisterCallback( this );
|
|
}
|
|
|
|
void Avatar::Destroy( void )
|
|
{
|
|
|
|
if ( mpCharacter )
|
|
{
|
|
mpCharacter->SetController( NULL );
|
|
mpCharacter->Release( );
|
|
mpCharacter = 0;
|
|
}
|
|
if ( mpVehicle )
|
|
{
|
|
mpVehicle->Release( );
|
|
mpVehicle = 0;
|
|
}
|
|
UnRegisterMappableHandle( mControllerId, mpAvatarInputManager->mCharacterMappableHandle );
|
|
UnRegisterMappableHandle( mControllerId, mpAvatarInputManager->mVehicleMappableHandle );
|
|
#ifdef RAD_PS2
|
|
if ( mpAvatarInputManager->mVehicleMappableHandleWheel0 != -1 )
|
|
{
|
|
UnRegisterMappableHandle( Input::USB0, mpAvatarInputManager->mVehicleMappableHandleWheel0 );
|
|
}
|
|
|
|
if ( mpAvatarInputManager->mVehicleMappableHandleWheel1 != -1 )
|
|
{
|
|
UnRegisterMappableHandle( Input::USB1, mpAvatarInputManager->mVehicleMappableHandleWheel1 );
|
|
}
|
|
#endif
|
|
mControllerId = INVALID_CONTROLLER;
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::GetControllerId
|
|
==============================================================================
|
|
Description: Comment
|
|
|
|
Parameters: ( void )
|
|
|
|
Return: int
|
|
|
|
=============================================================================
|
|
*/
|
|
int Avatar::GetControllerId( void ) const
|
|
{
|
|
return mControllerId;
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::SetControllerId
|
|
==============================================================================
|
|
Description: Comment
|
|
|
|
Parameters: ( int id )
|
|
|
|
Return: void
|
|
|
|
=============================================================================
|
|
*/
|
|
void Avatar::SetControllerId( int id )
|
|
{
|
|
mControllerId = id;
|
|
}
|
|
/*
|
|
==============================================================================
|
|
Avatar::GetCharacter
|
|
==============================================================================
|
|
Description: Comment
|
|
|
|
Parameters: ( void )
|
|
|
|
Return: const
|
|
|
|
=============================================================================
|
|
*/
|
|
Character* Avatar::GetCharacter( void ) const
|
|
{
|
|
return mpCharacter;
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::SetCharacter
|
|
==============================================================================
|
|
Description: Comment
|
|
|
|
Parameters: ( Character* pCharacter )
|
|
|
|
Return: void
|
|
|
|
=============================================================================
|
|
*/
|
|
void Avatar::SetCharacter( Character* pCharacter )
|
|
{
|
|
tRefCounted::Assign( mpCharacter, pCharacter );
|
|
if( mpCharacter )
|
|
{
|
|
tColour shadowColour = ::GetGameplayManager()->GetControllerColour( mControllerId );
|
|
mpCharacter->SetShadowColour( shadowColour );
|
|
}
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::GetVehicle
|
|
==============================================================================
|
|
Description: Comment
|
|
|
|
Parameters: ( void )
|
|
|
|
Return: const
|
|
|
|
=============================================================================
|
|
*/
|
|
Vehicle* Avatar::GetVehicle( void ) const
|
|
{
|
|
return mpVehicle;
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::SetVehicle
|
|
==============================================================================
|
|
Description: Comment
|
|
|
|
Parameters: ( Vehicle* pVehicle )
|
|
|
|
Return: void
|
|
|
|
=============================================================================
|
|
*/
|
|
void Avatar::SetVehicle( Vehicle* pVehicle )
|
|
{
|
|
tRefCounted::Assign( mpVehicle, pVehicle );
|
|
|
|
if( pVehicle )
|
|
{
|
|
int playerID = 0; // normal game defaults player to zero
|
|
if( GetGameFlow()->GetCurrentContext() == CONTEXT_LOADING_SUPERSPRINT )
|
|
{
|
|
playerID = SuperSprintManager::GetInstance()->GetOnlyHumanPlayerID();
|
|
if( this->mPlayerId != playerID )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// can be -1 if in supersprint and more than 1 human is participating...
|
|
if( playerID == -1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SuperCam* sc = GetSuperCamManager()->GetSCC( 0 )->GetActiveSuperCam();
|
|
if ( sc && sc->GetType() == SuperCam::BUMPER_CAM )
|
|
{
|
|
//Only stop rendering for bumpercams.
|
|
pVehicle->DrawVehicle( false );
|
|
}
|
|
else
|
|
{
|
|
pVehicle->DrawVehicle( true );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::GetIntoVehicle
|
|
==============================================================================
|
|
Description: Pseudo code.
|
|
|
|
1. Get a "human" vehicle controller.
|
|
2. Init HumanVehicleController with mControllerId.
|
|
3. Register with ControllerSystem.
|
|
4. Get pointer to Vehicle via VehicleManager using vehicleId.
|
|
5. Set Avatar member data mpVehicle to Vehicle pointer from 4.
|
|
6. Set Controller for Vehicle.
|
|
|
|
|
|
Parameters: ( Vehicle* pVehicle)
|
|
|
|
Return: void
|
|
|
|
=============================================================================
|
|
*/
|
|
void Avatar::SetInCarController( void )
|
|
{
|
|
rAssert( mpVehicle );
|
|
mpVehicle->mGeometryVehicle->FadeRoof( true );
|
|
mpVehicle->mGeometryVehicle->EnableLights( true );
|
|
mpVehicle->SetUserDrivingCar( true );
|
|
mpVehicle->SetDisableGasAndBrake(false);
|
|
|
|
// in case we just got into a traffi car, make sure brake lights are off
|
|
mpVehicle->mGeometryVehicle->HideBrakeLights();
|
|
mpVehicle->mBrakeLightsOn = false;
|
|
mpVehicle->mGeometryVehicle->HideReverseLights();
|
|
mpVehicle->mReverseLightsOn = false;
|
|
|
|
int vehicleId = GetVehicleCentral( )->GetVehicleId( mpVehicle );
|
|
// Detach the vehicle controller.
|
|
//
|
|
UnRegisterMappableHandle( mControllerId, mpAvatarInputManager->mVehicleMappableHandle );
|
|
|
|
|
|
HumanVehicleController* pVehicleController = mpAvatarInputManager->mpHumanVehicleController;
|
|
|
|
VehicleMappable* pVehicleMappable = mpAvatarInputManager->mpVehicleMappable;
|
|
pVehicleController->Create( mpVehicle, pVehicleMappable, mControllerId );
|
|
pVehicleMappable->SetController( pVehicleController );
|
|
|
|
mpAvatarInputManager->mVehicleMappableHandle = InputManager::GetInstance( )->RegisterMappable( mControllerId, pVehicleMappable );
|
|
|
|
bool wheelAttached = false;
|
|
#ifdef RAD_PS2
|
|
if ( GetGameplayManager()->GetGameType() != GameplayManager::GT_SUPERSPRINT )
|
|
{
|
|
if ( mControllerId == Input::USB0 ||
|
|
( mControllerId != Input::USB0 &&
|
|
mControllerId != Input::USB1 &&
|
|
GetInputManager()->IsControllerInPort( Input::USB0 )
|
|
)
|
|
)
|
|
{
|
|
mpAvatarInputManager->mVehicleMappableHandleWheel0 = InputManager::GetInstance( )->RegisterMappable( Input::USB0, mpAvatarInputManager->mpVehicleMappableUSB0 );
|
|
pVehicleController->SetWheel( mpAvatarInputManager->mpVehicleMappableUSB0, 0 );
|
|
mpAvatarInputManager->mpVehicleMappableUSB0->SetController( pVehicleController );
|
|
GetInputManager()->SetRumbleForDevice( Input::USB0, GetInputManager()->IsRumbleEnabled() );
|
|
wheelAttached = true;
|
|
}
|
|
else if ( mControllerId == Input::USB1 ||
|
|
( mControllerId != Input::USB0 &&
|
|
mControllerId != Input::USB1 &&
|
|
GetInputManager()->IsControllerInPort( Input::USB1 )
|
|
)
|
|
)
|
|
{
|
|
mpAvatarInputManager->mVehicleMappableHandleWheel1 = InputManager::GetInstance( )->RegisterMappable( Input::USB1, mpAvatarInputManager->mpVehicleMappableUSB1 );
|
|
pVehicleController->SetWheel( mpAvatarInputManager->mpVehicleMappableUSB1, 1 );
|
|
mpAvatarInputManager->mpVehicleMappableUSB1->SetController( pVehicleController );
|
|
GetInputManager()->SetRumbleForDevice( Input::USB1, GetInputManager()->IsRumbleEnabled() );
|
|
wheelAttached = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if ( !wheelAttached )
|
|
{
|
|
GetInputManager()->SetRumbleForDevice( mControllerId, GetInputManager()->IsRumbleEnabled() );
|
|
}
|
|
|
|
if ( !GetGameplayManager()->mIsDemo )
|
|
{
|
|
GetVehicleCentral( )->SetVehicleController( vehicleId, pVehicleController );
|
|
}
|
|
|
|
// First things, detach the in car character controller.
|
|
//
|
|
UnRegisterMappableHandle( mControllerId, mpAvatarInputManager->mCharacterMappableHandle );
|
|
|
|
CharacterMappable* pCharacterMappable = mpAvatarInputManager->mpInCarCharacterMappable;
|
|
CameraRelativeCharacterController* pCharacterController = mpAvatarInputManager->mpCameraRelativeCharacterController;
|
|
pCharacterController->Create( mpCharacter, pCharacterMappable );
|
|
|
|
mpAvatarInputManager->mCharacterMappableHandle = InputManager::GetInstance()->RegisterMappable( mControllerId, pCharacterMappable );
|
|
mpCharacter->SetController( pCharacterController );
|
|
|
|
// new:
|
|
// for changing the physics/collision representation if applicabble
|
|
mpVehicle->SetInCarSimState();
|
|
|
|
mpVehicle->BeefUpHitPointsOnTrafficCarsWhenUserDriving();
|
|
|
|
|
|
}
|
|
|
|
void Avatar::SetCameraTargetToVehicle( bool cut )
|
|
{
|
|
// Set the camera target.
|
|
//
|
|
GetSuperCamManager()->GetSCC( mPlayerId )->SetTarget( mpVehicle );
|
|
|
|
// Select the follow cam.
|
|
//
|
|
GetSuperCamManager()->GetSCC( mPlayerId )->SelectSuperCam( SuperCam::FOLLOW_CAM, cut ? (SuperCamCentral::CUT|SuperCamCentral::FORCE ) : 0, cut ? 0 : 7000 );
|
|
}
|
|
|
|
void Avatar::GetIntoVehicleStart( Vehicle* pVehicle)
|
|
{
|
|
SetVehicle( pVehicle );
|
|
|
|
// check to see if the target vehicle is currently controlled by traffic
|
|
// if it is, we need to work a little harder to carjack it :-)
|
|
if(pVehicle->GetLocomotionType() == VL_TRAFFIC)
|
|
{
|
|
pVehicle->SetLocomotion(VL_PHYSICS);
|
|
pVehicle->mHijackedByUser = true;
|
|
}
|
|
|
|
if(GetSuperCamManager()->GetSCC( mPlayerId )->GetPreferredFollowCam() != SuperCam::BUMPER_CAM)
|
|
{
|
|
SetCameraTargetToVehicle( );
|
|
}
|
|
|
|
CGuiScreenMultiHud* currentHUD = GetCurrentHud();
|
|
if( currentHUD != NULL )
|
|
{
|
|
currentHUD->GetHudMap( mPlayerId )->UnregisterIcon( 0 );
|
|
currentHUD->GetHudMap( mPlayerId )->RegisterIcon( HudMapIcon::ICON_PLAYER,
|
|
rmt::Vector( 0, 0, 0 ),
|
|
pVehicle );
|
|
}
|
|
|
|
UnRegisterMappableHandle( mControllerId, mpAvatarInputManager->mCharacterMappableHandle );
|
|
|
|
|
|
}
|
|
|
|
void Avatar::GetIntoVehicleEnd( Vehicle* pVehicle)
|
|
{
|
|
SetCameraTargetToVehicle( );
|
|
|
|
SetInCarController( );
|
|
// this call is to record the rest seating positions of the driver and passenger
|
|
pVehicle->RecordRestSeatingPositionsOnEntry();
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::GetOutOfVehicle
|
|
==============================================================================
|
|
Description: Pseudo code
|
|
2. Set Controller for Vehicle to NULL ( or AI controller )
|
|
3. Set Vehicle member data to NULL.
|
|
4. Unregister controller with controller system.
|
|
|
|
Parameters: ( Vehicle* pVehicle)
|
|
|
|
Return: void
|
|
|
|
=============================================================================
|
|
*/
|
|
void Avatar::GetOutOfVehicleStart( Vehicle* pVehicle)
|
|
{
|
|
// First things, detach the in car character controller.
|
|
//
|
|
UnRegisterMappableHandle( mControllerId, mpAvatarInputManager->mCharacterMappableHandle );
|
|
|
|
// Detach the vehicle controller.
|
|
UnRegisterMappableHandle( mControllerId, mpAvatarInputManager->mVehicleMappableHandle );
|
|
#ifdef RAD_PS2
|
|
if ( mpAvatarInputManager->mVehicleMappableHandleWheel0 != -1 )
|
|
{
|
|
UnRegisterMappableHandle( Input::USB0, mpAvatarInputManager->mVehicleMappableHandleWheel0 );
|
|
GetInputManager()->SetRumbleForDevice( Input::USB0, false );
|
|
}
|
|
|
|
if ( mpAvatarInputManager->mVehicleMappableHandleWheel1 != -1 )
|
|
{
|
|
UnRegisterMappableHandle( Input::USB1, mpAvatarInputManager->mVehicleMappableHandleWheel1 );
|
|
GetInputManager()->SetRumbleForDevice( Input::USB1, false );
|
|
}
|
|
#endif
|
|
|
|
// attach the on-foot controller
|
|
// we do this early (don't wait for end of get out of car) so that we can abort \
|
|
// the door close if there is movement)
|
|
SetOutOfCarController();
|
|
|
|
int vehicleId = GetVehicleCentral()->GetVehicleId( pVehicle, false );
|
|
|
|
if ( !GetGameplayManager()->mIsDemo && (vehicleId != -1))
|
|
{
|
|
GetVehicleCentral( )->SetVehicleController( vehicleId, 0 );
|
|
}
|
|
|
|
if(GetSuperCamManager()->GetSCC( mPlayerId )->GetPreferredFollowCam() == SuperCam::BUMPER_CAM)
|
|
{
|
|
SetCameraTargetToCharacter();
|
|
}
|
|
}
|
|
|
|
void Avatar::SetOutOfCarController( void )
|
|
{
|
|
if( GetVehicle() )
|
|
{
|
|
GetVehicle()->mGeometryVehicle->FadeRoof( false );
|
|
|
|
if( !TrafficManager::GetInstance()->IsVehicleTrafficVehicle( GetVehicle() ) )
|
|
{
|
|
GetVehicle()->mGeometryVehicle->EnableLights( false );
|
|
}
|
|
|
|
GetVehicle()->SetOutOfCarSimState();
|
|
|
|
GetVehicle()->SetUserDrivingCar( false );
|
|
}
|
|
|
|
// Then, make a new character controller.
|
|
//
|
|
CharacterMappable* pCharacterMappable = mpAvatarInputManager->mpBipedCharacterMappable;
|
|
CameraRelativeCharacterController* pCharacterController = mpAvatarInputManager->mpCameraRelativeCharacterController;
|
|
pCharacterController->Create( mpCharacter, pCharacterMappable );
|
|
|
|
// Register the new character controller.
|
|
//
|
|
mpAvatarInputManager->mCharacterMappableHandle = InputManager::GetInstance()->RegisterMappable( mControllerId, pCharacterMappable );
|
|
mpCharacter->SetController( pCharacterController );
|
|
|
|
pCharacterController->SetCamera( GetSuperCamManager()->GetSCC( mPlayerId )->GetCamera() );
|
|
|
|
GetInputManager()->SetRumbleForDevice( mControllerId, false );
|
|
}
|
|
|
|
void Avatar::SetCameraTargetToCharacter( bool cut )
|
|
{
|
|
// Set the camera target.
|
|
//
|
|
GetSuperCamManager()->GetSCC( mPlayerId )->SetTarget( mpCharacter->GetTarget( ) );
|
|
// Select the follow cam.
|
|
//
|
|
#ifdef RAD_WIN32
|
|
GetSuperCamManager()->GetSCC( mPlayerId )->SelectSuperCam( SuperCam::ON_FOOT_CAM, cut ? SuperCamCentral::CUT : 0 );
|
|
#else
|
|
GetSuperCamManager()->GetSCC( mPlayerId )->SelectSuperCam( SuperCam::WALKER_CAM, cut ? SuperCamCentral::CUT : 0 );
|
|
#endif
|
|
}
|
|
|
|
void Avatar::GetOutOfVehicleEnd( Vehicle* pVehicle)
|
|
{
|
|
pVehicle->DrawVehicle(true); // just in case it was in bumper cam
|
|
|
|
SetCameraTargetToCharacter();
|
|
|
|
SetVehicle( 0 );
|
|
|
|
CGuiScreenMultiHud* currentHUD = GetCurrentHud();
|
|
if( currentHUD != NULL )
|
|
{
|
|
currentHUD->GetHudMap( mPlayerId )->UnregisterIcon( 0 );
|
|
currentHUD->GetHudMap( mPlayerId )->RegisterIcon( HudMapIcon::ICON_PLAYER,
|
|
rmt::Vector( 0, 0, 0 ),
|
|
mpCharacter->GetTarget() );
|
|
}
|
|
}
|
|
/*
|
|
==============================================================================
|
|
Avatar::IsInCar
|
|
==============================================================================
|
|
Description: Comment
|
|
|
|
Parameters: ( void )
|
|
|
|
Return: bool
|
|
|
|
=============================================================================
|
|
*/
|
|
bool Avatar::IsInCar( void ) const
|
|
{
|
|
rAssert( mpCharacter );
|
|
return mpCharacter->IsInCar( ) && (mpVehicle != NULL);
|
|
}
|
|
|
|
|
|
const void Avatar::GetPosition( rmt::Vector& pos ) const
|
|
{
|
|
if( this->IsInCar() )
|
|
{
|
|
mpVehicle->GetPosition( &pos );
|
|
}
|
|
else
|
|
{
|
|
mpCharacter->GetPosition( pos );
|
|
}
|
|
}
|
|
|
|
const void Avatar::GetHeading( rmt::Vector& irHeading ) const
|
|
{
|
|
if( this->IsInCar() )
|
|
{
|
|
mpVehicle->GetHeading( &irHeading );
|
|
}
|
|
else
|
|
{
|
|
mpCharacter->GetFacing( irHeading );
|
|
}
|
|
}
|
|
|
|
const void Avatar::GetNormalizedHeadingSafe( rmt::Vector& heading ) const
|
|
{
|
|
if( this->IsInCar() )
|
|
{
|
|
assert( mpVehicle != NULL );
|
|
mpVehicle->GetVelocity( &heading );
|
|
float speedMps = mpVehicle->GetSpeedKmh() * KPH_2_MPS;
|
|
if( rmt::Fabs(speedMps) < 0.00001f )
|
|
{
|
|
heading.Set( 0.0f, 0.0f, 0.0f );
|
|
}
|
|
else
|
|
{
|
|
heading.Scale( 1.0f/speedMps );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// for characters, facing is same as heading (no skidding/sliding)
|
|
// I hope...
|
|
assert( mpCharacter != NULL );
|
|
mpCharacter->GetFacing( heading );
|
|
}
|
|
assert( rmt::Epsilon( heading.MagnitudeSqr(), 1.0f, 0.00001f ) ||
|
|
rmt::Epsilon( heading.MagnitudeSqr(), 0.0f, 0.00001f ) );
|
|
}
|
|
|
|
const void Avatar::GetVelocity( rmt::Vector& vel ) const
|
|
{
|
|
if( this->IsInCar() )
|
|
{
|
|
assert( mpVehicle != NULL );
|
|
mpVehicle->GetVelocity( &vel );
|
|
}
|
|
else
|
|
{
|
|
// Not sure here if the Choreo puppet's velocity value
|
|
// (which is what Character::GetVelocity() retrieves)
|
|
// is a good one. So we just track our own.
|
|
assert( mpCharacter != NULL );
|
|
mpCharacter->GetVelocity( vel );
|
|
}
|
|
}
|
|
|
|
const float Avatar::GetSpeedMps() const
|
|
{
|
|
if( this->IsInCar() )
|
|
{
|
|
assert( mpVehicle != NULL );
|
|
return mpVehicle->GetSpeedKmh() * KPH_2_MPS;
|
|
}
|
|
else
|
|
{
|
|
assert( mpCharacter != NULL );
|
|
return mpCharacter->GetSpeed();
|
|
}
|
|
|
|
}
|
|
|
|
void Avatar::OnCheatEntered( eCheatID cheatID, bool isEnabled )
|
|
{
|
|
if( cheatID == CHEAT_ID_SHOW_AVATAR_POSITION )
|
|
{
|
|
s_displayCoordinates = isEnabled;
|
|
}
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::Update
|
|
==============================================================================
|
|
Description: Comment
|
|
|
|
Parameters: (float dt)
|
|
|
|
Return: void
|
|
|
|
=============================================================================
|
|
*/
|
|
void Avatar::Update(float dt)
|
|
{
|
|
mHasBeenUpdatedThisFrame = false;
|
|
#ifndef FINAL
|
|
char buffy[256];
|
|
rmt::Vector posn;
|
|
const pddiColour YELLOW(255,255,0);
|
|
|
|
//
|
|
// Coordinate display cheat
|
|
//
|
|
if( s_displayCoordinates )
|
|
{
|
|
if( mpCharacter != NULL )
|
|
{
|
|
GetPosition( posn );
|
|
}
|
|
else
|
|
{
|
|
posn.Set( 0.0f, 0.0f, 0.0f );
|
|
}
|
|
sprintf( buffy, "Avatar %d position: %f %f %f", mPlayerId, posn.x, posn.y, posn.z );
|
|
p3d::pddi->DrawString( buffy, 40, 40 + ( mPlayerId * 20), YELLOW );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void Avatar::GetLastPathInfo(
|
|
RoadManager::PathElement& oElem,
|
|
RoadSegment*& oSeg,
|
|
float& oSegT,
|
|
float& oRoadT )
|
|
{
|
|
oElem.elem = NULL;
|
|
oSeg = NULL;
|
|
oSegT = 0.0f;
|
|
oRoadT = 0.0f;
|
|
|
|
// don't do it again if already done
|
|
if( !mHasBeenUpdatedThisFrame )
|
|
{
|
|
mHasBeenUpdatedThisFrame = true;
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Update the Avatar's closest path entities in the world.
|
|
|
|
rmt::Vector myPos;
|
|
GetPosition( myPos );
|
|
|
|
|
|
RoadSegment* seg = NULL;
|
|
float segT = 0.0f;
|
|
float roadT = 0.0f;
|
|
RoadManager::PathElement elem;
|
|
elem.elem = NULL;
|
|
|
|
/*
|
|
RoadManager::PathfindingOptions options = RoadManager::PO_SEARCH_SHORTCUTS;
|
|
RoadManager::GetInstance()->FindClosestPathElement(
|
|
pos, 100.0f, options, tmpPathElem, tmpSeg, tmpSegT, tmpRoadT );
|
|
*/
|
|
|
|
// Special initial case:
|
|
// If my last path info is completely unset (started off the road)
|
|
// then we fetch the closest path element using Devin's thing
|
|
if( mLastPathElement.elem == NULL && mLastRoadSegment == NULL )
|
|
{
|
|
RoadSegment* closestSeg = NULL;
|
|
float dummy;
|
|
GetIntersectManager()->FindClosestAnyRoad( myPos, 100.0f, closestSeg, dummy );
|
|
|
|
seg = (RoadSegment*) closestSeg;
|
|
segT = RoadManager::DetermineSegmentT( myPos, seg );
|
|
roadT = RoadManager::DetermineRoadT( seg, segT );
|
|
elem.elem = seg->GetRoad();
|
|
elem.type = RoadManager::ET_NORMALROAD;
|
|
}
|
|
else
|
|
{
|
|
VehicleAI::FindClosestPathElement( myPos, elem, seg, segT, roadT, true );
|
|
}
|
|
|
|
if( elem.elem == NULL )
|
|
{
|
|
GetEventManager()->TriggerEvent( EVENT_AVATAR_OFF_ROAD );
|
|
|
|
oElem = mLastPathElement;
|
|
oSeg = mLastRoadSegment;
|
|
oSegT = mLastRoadSegmentT;
|
|
oRoadT = mLastRoadT;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
GetEventManager()->TriggerEvent( EVENT_AVATAR_ON_ROAD );
|
|
}
|
|
|
|
rAssert( elem.elem != NULL );
|
|
|
|
mLastPathElement = elem;
|
|
if( seg )
|
|
{
|
|
mLastRoadSegment = seg;
|
|
mLastRoadSegmentT = segT;
|
|
mLastRoadT = roadT;
|
|
}
|
|
|
|
/*
|
|
//
|
|
// true means not to ignore the path element we just found
|
|
// default is true because we could have lastpathelement == elem
|
|
// but we could be on different segments...
|
|
//
|
|
bool OK = true;
|
|
|
|
if( mLastPathElement != elem )
|
|
{
|
|
if( mLastPathElement.elem == NULL )
|
|
{
|
|
OK = true;
|
|
}
|
|
else
|
|
{
|
|
Road* lastRoad = NULL;
|
|
Intersection* lastInt = NULL;
|
|
Road* currRoad = NULL;
|
|
Intersection* currInt = NULL;
|
|
|
|
// temporary type: 0 = intersection, 1 = road, 2 = shortcut
|
|
|
|
// Figure out what type is LAST
|
|
int lastElemType = 0;
|
|
if( mLastPathElement.type == RoadManager::ET_NORMALROAD )
|
|
{
|
|
lastRoad = (Road*) mLastPathElement.elem;
|
|
lastElemType++;
|
|
|
|
if( lastRoad->GetShortCut() )
|
|
{
|
|
lastElemType++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lastInt = (Intersection*) mLastPathElement.elem;
|
|
}
|
|
|
|
// Figure out what type is CURR
|
|
int currElemType = 0;
|
|
if( elem.type == RoadManager::ET_NORMALROAD )
|
|
{
|
|
currRoad = (Road*) elem.elem;
|
|
currElemType++;
|
|
|
|
if( currRoad->GetShortCut() )
|
|
{
|
|
currElemType++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
currInt = (Intersection*) elem.elem;
|
|
}
|
|
|
|
//
|
|
// Start resolving ...
|
|
///////////////
|
|
// LAST: Intersection
|
|
if( lastElemType == 0 )
|
|
{
|
|
rAssert( lastInt );
|
|
if( currElemType == 2 )// CURR: shortcut
|
|
{
|
|
rAssert( currRoad );
|
|
if( lastInt == (Intersection*) currRoad->GetSourceIntersection() ||
|
|
lastInt == (Intersection*) currRoad->GetDestinationIntersection() )
|
|
{
|
|
OK = true;
|
|
}
|
|
else
|
|
{
|
|
OK = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OK = true;
|
|
}
|
|
}
|
|
/////////////////
|
|
// LAST: Normal road
|
|
else if( lastElemType == 1 )
|
|
{
|
|
rAssert( lastRoad );
|
|
|
|
if( currElemType == 0 ) // CURR: intersection
|
|
{
|
|
rAssert( currInt );
|
|
if( currInt == (Intersection*)lastRoad->GetSourceIntersection() ||
|
|
currInt == (Intersection*)lastRoad->GetDestinationIntersection() )
|
|
{
|
|
OK = true;
|
|
}
|
|
else
|
|
{
|
|
OK = false;
|
|
}
|
|
}
|
|
else if( currElemType == 1 ) // CURR: normal road
|
|
{
|
|
rAssert( currRoad );
|
|
OK = true;
|
|
}
|
|
else // CURR: shortcut
|
|
{
|
|
rAssert( currRoad );
|
|
OK = false;
|
|
}
|
|
}
|
|
////////////////
|
|
// LAST: Shortcut
|
|
else
|
|
{
|
|
rAssert( lastRoad );
|
|
|
|
if( currElemType == 0 ) // CURR: intersection
|
|
{
|
|
rAssert( currInt );
|
|
|
|
// NOTE:
|
|
// This is the fix to Level 3 Mission 7 where the limo drives over the where the shortcuts
|
|
// and normal road segments merge near the squidport.... This was where its last good element
|
|
// was found... It then transitted onto the intersection, but rejected it because back then
|
|
// we only tested for the destination intersection... So it was stuck there for a long time
|
|
// but didn't realize it until it hit the next waypoint (wayy... over by the dam) and decided
|
|
// it needed to turn back.
|
|
if( currInt == (Intersection*)lastRoad->GetDestinationIntersection() ||
|
|
currInt == (Intersection*)lastRoad->GetSourceIntersection() )
|
|
{
|
|
OK = true;
|
|
}
|
|
else
|
|
{
|
|
OK = false;
|
|
}
|
|
}
|
|
else if( currElemType == 1 ) // CURR: normal road
|
|
{
|
|
rAssert( currRoad );
|
|
OK = false;
|
|
}
|
|
else // CURR: shortcut
|
|
{
|
|
rAssert( currRoad );
|
|
OK = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( OK )
|
|
{
|
|
mLastPathElement = elem;
|
|
if( seg )
|
|
{
|
|
if( mLastRoadSegment != seg )
|
|
{
|
|
mLastRoadSegment = seg;
|
|
}
|
|
mLastRoadSegmentT = segT;
|
|
mLastRoadT = roadT;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
oElem = mLastPathElement;
|
|
oSeg = (RoadSegment*) mLastRoadSegment;
|
|
oSegT = mLastRoadSegmentT;
|
|
oRoadT = mLastRoadT;
|
|
}
|
|
|
|
void Avatar::GetRaceInfo( float& distToCurrCollectible, int& currCollectible, int& numLapsCompleted )
|
|
{
|
|
distToCurrCollectible = mDistToCurrentCollectible;
|
|
currCollectible = mCurrentCollectible;
|
|
numLapsCompleted = mNumLapsCompleted;
|
|
}
|
|
|
|
void Avatar::SetRaceInfo( float distToCurrCollectible, int currCollectible, int numLapsCompleted )
|
|
{
|
|
mDistToCurrentCollectible = distToCurrCollectible;
|
|
mCurrentCollectible = currCollectible;
|
|
mNumLapsCompleted = numLapsCompleted;
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
Avatar::SetCamera
|
|
==============================================================================
|
|
Description: Controller needs to be aware of camera changes so that
|
|
direction can be normalized.
|
|
|
|
Parameters: ( tCamera* pCamera )
|
|
|
|
Return: void
|
|
|
|
=============================================================================
|
|
*/
|
|
void Avatar::SetCamera( tCamera* pCamera )
|
|
{
|
|
rAssert( pCamera != 0 );
|
|
mpAvatarInputManager->mpCameraRelativeCharacterController->SetCamera( pCamera );
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Private Member Functions
|
|
//
|
|
//******************************************************************************
|