The-Simpsons-Hit-and-Run/game/code/supersprint/supersprintmanager.cpp

2669 lines
87 KiB
C++

//=============================================================================
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
//
// File: supersprintmanager.cpp
//
// Description: Implement SuperSprintManager
//
// History: 2/3/2003 + Created -- Cary Brisebois
//
//=============================================================================
//========================================
// System Includes
//========================================
// Foundation Tech
#include <raddebug.hpp>
#include <radtime.hpp>
#include <p3d/utility.hpp>
#include <p3d/anim/multicontroller.hpp>
#include <string.h>
//========================================
// Project Includes
//========================================
#include <memory/srrmemory.h>
#include <loading/loadingmanager.h>
#include <gameflow/gameflow.h>
#include <camera/supercammanager.h>
#include <camera/supercamcentral.h>
#include <camera/animatedcam.h>
#include <mission/missionscriptloader.h>
#include <render/loaders/billboardwrappedloader.h>
#include <render/dsg/animcollisionentitydsg.h>
#include <worldsim/vehiclecentral.h>
#include <worldsim/avatarmanager.h>
#include <worldsim/character/character.h>
#include <worldsim/character/charactermanager.h>
#include <meta/carstartlocator.h>
#include <render/rendermanager/rendermanager.h>
#include <render/rendermanager/renderlayer.h>
#include <input/inputmanager.h>
#include <events/eventmanager.h>
#include <meta/eventlocator.h>
#include <contexts/supersprint/supersprintcontext.h>
#include <gameflow/gameflow.h>
#include <presentation/gui/guisystem.h>
#include <presentation/gui/guimanager.h>
#include <sound/soundmanager.h>
#include <roads/roadmanager.h>
#include <roads/roadsegment.h>
#include <worldsim/avatarmanager.h>
#include <worldsim/avatar.h>
#include <render/intersectmanager/intersectmanager.h>
#include <supersprint/supersprintmanager.h>
#include <mission/gameplaymanager.h>
//*****************************************************************************
//
// Global Data, Local Data, Local Classes
//
//*****************************************************************************
const float MIN_SCALE = 0.01f;
const float MAX_SCALE = 1.0f;
const float MIN_DIST = 10.0f;
const float MAX_DIST = 80.0f;
SuperSprintManager* SuperSprintManager::spInstance = NULL;
const int DNF_TIMEOUT_TIME = 10000;
#define GET_TIME ::radTimeGetMicroseconds()
static char CHEKPOINT_LIST_B01 [] =
{
2, 3, 4, 5, 6, 7, 8, 1
};
static char CHEKPOINT_LIST_B01_R [] =
{
8, 7, 6, 5, 4, 3, 2, 1
};
static char CHECKPOINT_LIST_B02 [] =
{
2, 3, 4, 5, 6, 3, 8, 9, 1
};
static char CHECKPOINT_LIST_B02_R [] =
{
9, 8, 3, 6, 5, 4, 3, 2, 1
};
static char CHECKPOINT_LIST_B03 [] =
{
2, 3, 4, 5, 6, 7, 1
};
static char CHECKPOINT_LIST_B03_R [] =
{
7, 6, 5, 4, 3, 2, 1
};
static char CHECKPOINT_LIST_B05 [] =
{
2, 3, 4, 5, 6, 7, 8, 9, 10, 7, 3, 11, 1
};
static char CHECKPOINT_LIST_B05_R [] =
{
11, 3, 7, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
};
static char CHECKPOINT_LIST [] =
{
2, 3, 1
};
static char CHECKPOINT_LIST_R [] =
{
3, 2, 1
};
//*****************************************************************************
//
// Public Member Functions
//
//*****************************************************************************
//From EventListener
//=============================================================================
// SuperSprintManager::HandleEvent
//=============================================================================
// Description: Comment
//
// Parameters: ( EventEnum id, void* pEventData )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::HandleEvent( EventEnum id, void* pEventData )
{
#if defined( RAD_DEBUG ) || defined( RAD_TUNE )
char errMsg[128];
#endif
if ( id == EVENT_LOCATOR + LocatorEvent::CHECK_POINT )
{
EventLocator* loc = static_cast<EventLocator*>(pEventData);
char checkNum = static_cast<char>( loc->GetData() );
if ( loc->GetPlayerEntered() && checkNum != 0 ) //Ignore the 0 ones.
{
//The idea here is to detect if the player is attempting to do the
//checkpoints out of order. If the checkpoint passed is not the one we want
//we test to see if the player has already hit a bad one and if not we decrement
//where they are going (send them back) and mark them as cheaters.
//Then, only when they pass the one they're supposed to do they get unmarked
//as cheaters and get to move on to the next check point. The first checkpoint is a
//bit tricky as the players start inside the last checkpoint and would thus be
//considered cheaters. We can ignore cheaters cheating on checkpoint 2.
//Indexes start at 1
int playerID = loc->GetPlayerID();
#if defined( RAD_DEBUG ) || defined( RAD_TUNE )
sprintf( errMsg, "Something wrong with player %d", playerID+1 );
rTuneAssertMsg( 0 <= playerID && playerID < 4, errMsg );
rTuneAssertMsg( 0 <= mPlayers[ playerID ].mNextCheckPoint &&
mPlayers[ playerID ].mNextCheckPoint < GetNumCheckpoints(), errMsg );
#endif
// find the one we're supposed to be at
const char nextCheck = mCheckPoints[ mPlayers[ playerID ].mNextCheckPoint ];
// find the one we were just at
char lastCheckIdx = mPlayers[ playerID ].mNextCheckPoint;
if ( lastCheckIdx == 0 )
{
lastCheckIdx = GetNumCheckpoints() - 1;
}
else
{
lastCheckIdx--;
}
rTuneAssert( 0 <= lastCheckIdx && lastCheckIdx < GetNumCheckpoints() );
const char prevCheck = mCheckPoints[ lastCheckIdx ];
if ( checkNum != nextCheck )
{
//This guy is possibly cheating
if ( !mPlayers[ playerID ].mCheated &&
checkNum != prevCheck )
{
//CHEATER!
// we want to knock him back to aim for the previous check
mPlayers[ playerID ].mNextCheckPoint = lastCheckIdx;
/*
if ( nextCheck == 1 )
{
mPlayers[ playerID ].mNextCheckPoint = GetNumCheckpoints() - 1;
}
else
{
mPlayers[ playerID ].mNextCheckPoint = nextCheck - 1;
}
*/
#if defined( RAD_DEBUG ) || defined( RAD_TUNE )
rTuneAssertMsg( 0 <= mPlayers[ playerID ].mNextCheckPoint &&
mPlayers[ playerID ].mNextCheckPoint < GetNumCheckpoints(), errMsg );
#endif
mPlayers[ playerID ].mCheated = true;
}
}
else
{
//Unmark the cheater
bool previouslyCheated = mPlayers[ playerID ].mCheated;
mPlayers[ playerID ].mCheated = false;
if( nextCheck == 1 && !previouslyCheated ) //This is the finish line.
{
//This guy has completed a lap
mPlayers[ playerID ].mNumLaps++;
//Figure out his lap time.
unsigned int endTime = GET_TIME;
unsigned int time = endTime - mStartTime;
unsigned int lapTime = time - mPlayers[ playerID ].mRaceTime;
//Possibly set the best lap time
if ( lapTime < mPlayers[ playerID ].mBestLap )
{
mPlayers[ playerID ].mBestLap = lapTime;
}
//Set the lapTime
mPlayers[ playerID ].mLapTime = lapTime;
//Set the raceTime
mPlayers[ playerID ].mRaceTime += lapTime;
if ( static_cast<int>( mPlayers[ playerID ].mNumLaps ) == mNumLaps - 1 )
{
//Show the white flag for a few seconds.
mWFlag->ShouldRender( true );
mWFlagTimeout = SuperSprintData::FLAG_TIMEOUT;
}
else if ( static_cast<int>( mPlayers[ playerID ].mNumLaps ) == mNumLaps )
{
//Show the finished flag for a few seconds.
mFFlag->ShouldRender( true );
mFFlagTimeout = SuperSprintData::FLAG_TIMEOUT;
//This guy is finished.
if( !mVehicleSlots[ playerID ].mIsHuman )
{
mVehicleSlots[ playerID ].mVehicleAI->SetActive( false );
}
else
{
//Disable his controller
mNumHumansFinished++;
int controllerID = GetInputManager()->GetControllerIDforPlayer( playerID );
if( controllerID != -1 )
{
GetInputManager()->GetController( controllerID )->SetGameState( Input::ACTIVE_SS_GAME );
}
}
mPlayers[ playerID ].mPosition = mCurrentPosition;
//Only one guy left, or all humans done, go to DNF
if ( mCurrentState != DNF_TIMEOUT &&
( mCurrentPosition == mNumActivePlayers - 1 ||
mNumHumansFinished == mNumHumanPlayers ) )
{
mCountDownTime = DNF_TIMEOUT_TIME;
mDrawable->SetRenderState( SuperSprintDrawable::COUNT_DOWN );
mDrawable->SetTextScale( 2.0f );
sprintf( mTime, "%d", mCountDownTime / 1000 );
mDrawable->SetCountDownMSG( mTime );
SetState( DNF_TIMEOUT );
}
else if ( mCurrentPosition == mNumActivePlayers )
{
//We're done!
mCountDownTime = 0;
}
mCurrentPosition++;
}
}
mPlayers[ playerID ].mNextCheckPoint++;
if ( mPlayers[ playerID ].mNextCheckPoint == GetNumCheckpoints() )
{
mPlayers[ playerID ].mNextCheckPoint = 0; //Reset
}
#if defined( RAD_DEBUG ) || defined( RAD_TUNE )
rTuneAssertMsg( 0 <= mPlayers[ playerID ].mNextCheckPoint &&
mPlayers[ playerID ].mNextCheckPoint < GetNumCheckpoints(), errMsg );
#endif
}
}
}
else if ( id == EVENT_LOCATOR + LocatorEvent::TRAP )
{
EventLocator* loc = static_cast<EventLocator*>(pEventData);
if ( loc->GetPlayerEntered() )
{
unsigned int locID = loc->GetData();
if ( !mTrapTriggered &&
mPositions[ loc->GetPlayerID() ] == 1 &&
((!mGoLeft && locID == 0) || (mGoLeft && locID == 1)) )
{
//This toggles on
mTrapController->SetAnimationDirection( 1.0f );
mTrapTriggered = true;
}
else if ( mTrapTriggered &&
mPositions[ loc->GetPlayerID() ] == 1 &&
((!mGoLeft && locID == 1) || (mGoLeft && locID == 0)) )
{
//This toggles off
mTrapController->SetAnimationDirection( -1.0f );
mTrapTriggered = false;
}
}
}
else if ( id == EVENT_ANIMATED_CAM_SHUTDOWN )
{
DisableAllControllers();
}
GameplayManager::HandleEvent( id, pEventData );
}
//From LoadingManager::ProcessRequestsCallback
//=============================================================================
// SuperSprintManager::OnProcessRequestsComplete
//=============================================================================
// Description: Comment
//
// Parameters: ( void* pUserData )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::OnProcessRequestsComplete( void* pUserData )
{
PositionCharacters();
SetupIcons();
GetGameFlow()->SetContext( CONTEXT_SUPERSPRINT );
}
//Local
//=============================================================================
// SuperSprintManager::GetInstance
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: SuperSprintManager
//
//=============================================================================
SuperSprintManager* SuperSprintManager::GetInstance()
{
if ( spInstance == NULL )
{
HeapMgr()->PushHeap( GMA_LEVEL_OTHER );
spInstance = new SuperSprintManager();
spInstance->AddRef();
HeapMgr()->PopHeap( GMA_LEVEL_OTHER );
}
return spInstance;
}
//=============================================================================
// SuperSprintManager::DestroyInstance
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::DestroyInstance()
{
if ( spInstance )
{
spInstance->Release();
}
spInstance = NULL;
}
//=============================================================================
// SuperSprintManager::Initialize
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::Initialize()
{
GameplayManager::Initialize();
HeapMgr()->PushHeap( GMA_LEVEL_OTHER );
//Add the drawable to the views
mDrawable = new SuperSprintDrawable();
rAssert( mDrawable );
mDrawable->AddRef();
RenderManager* rm = GetRenderManager();
RenderLayer* rloutside = rm->mpLayer( RenderEnums::LevelSlot );
rAssert( rloutside );
rloutside->AddGuts( mDrawable );
mDrawable->SetCarData( mVehicleSlots );
mDrawable->SetPlayerData( mPlayers );
int i;
for( i = 0; i < SuperSprintData::NUM_PLAYERS; i++ )
{
int controllerID = GetInputManager()->GetControllerIDforPlayer( i );
mVehicleSlots[ i ].mState = (controllerID != -1) ?
SuperSprintData::CarData::SELECTED :
SuperSprintData::CarData::WAITING;
mVehicleSlots[ i ].mIsHuman = (controllerID != -1);
mPlayers[ i ].mRacing = (controllerID != -1);
}
EnumerateControllers();
mNumCheckPoints = 0;
GetEventManager()->AddListener( this, (EventEnum)(EVENT_LOCATOR + LocatorEvent::CHECK_POINT) );
GetEventManager()->AddListener( this, (EventEnum)(EVENT_LOCATOR + LocatorEvent::TRAP) );
GetEventManager()->AddListener( this, EVENT_ANIMATED_CAM_SHUTDOWN );
mFFlag = new AnimatedIcon();
mWFlag = new AnimatedIcon();
int j;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
for ( j = 0; j < SuperSprintData::NUM_PLAYERS; ++j )
{
mPositionIcon[ i ][ j ] = new AnimatedIcon();
}
mPlayerID[ i ] = new AnimatedIcon();
mNitroEffect[ i ] = new AnimatedIcon();
}
for ( i = 0; i < MAX_AI_WAYPOINTS; ++i )
{
mPathData[ i ].closestElem.elem = NULL;
mPathData[ i ].roadT = 0.0f;
mPathData[ i ].seg = NULL;
mPathData[ i ].segT = 0.0f;
mPathData[ i ].loc = NULL;
}
HeapMgr()->PopHeap( GMA_LEVEL_OTHER );
}
//=============================================================================
// SuperSprintManager::Finalize
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::Finalize()
{
//Remove the drawable from the views
RenderManager* rm = GetRenderManager();
RenderLayer* rloutside = rm->mpLayer( RenderEnums::LevelSlot );
rAssert( rloutside );
rloutside->RemoveGuts( mDrawable );
//Shut down the controllers.
InputManager* im = GetInputManager();
unsigned int i;
for ( i = 0; i < Input::MaxControllers; ++i )
{
im->UnregisterMappable( i, this );
}
GetEventManager()->RemoveAll( this );
mDrawable->Release();
mDrawable = NULL;
CleanUpCars();
delete mFFlag;
mFFlag = NULL;
delete mWFlag;
mWFlag = NULL;
int j;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
for ( j = 0; j < SuperSprintData::NUM_PLAYERS; ++j )
{
delete mPositionIcon[ i ][ j ];
mPositionIcon[ i ][ j ] = NULL;
}
delete mPlayerID[ i ];
delete mNitroEffect[ i ];
}
if ( mTrapController )
{
mTrapController->Release();
mTrapController = NULL;
}
for ( i = 0; i < mNumCheckPointLocators; ++i )
{
//mCheckPointLocators[ i ]->Release();
mCheckPointLocators[ i ] = NULL;
}
mNumCheckPointLocators = 0;
GameplayManager::Finalize();
}
//=============================================================================
// SuperSprintManager::Update
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int milliseconds )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::Update( unsigned int milliseconds )
{
int oldTimeSecs;
int newTimeSecs;
//Test the flags
if ( mFFlagTimeout > 0 )
{
if ( mFFlagTimeout <= milliseconds )
{
mFFlag->ShouldRender( false );
mFFlagTimeout = 0;
}
else
{
mFFlagTimeout -= milliseconds;
mFFlag->Update( milliseconds );
}
}
if ( mWFlagTimeout > 0 )
{
if ( mWFlagTimeout <= milliseconds )
{
mWFlag->ShouldRender( false );
mWFlagTimeout = 0;
}
else
{
mWFlagTimeout -= milliseconds;
mWFlag->Update( milliseconds );
}
}
UpdatePositionIcons( milliseconds );
switch ( mCurrentState )
{
case COUNT_DOWN:
{
// 3 - 2 - 1 - GO!
oldTimeSecs = mCountDownTime / 1000;
if ( mCountDownTime - static_cast<int>(milliseconds) <= 0 )
{
mCountDownTime = 0;
}
else
{
mCountDownTime -= milliseconds;
}
if ( mCountDownTime > 2000 )
{
mDrawable->SetCountDownMSG( "3" );
}
else if ( mCountDownTime > 1000 )
{
mDrawable->SetCountDownMSG( "2" );
mDrawable->SetTextScale( 1.5f );
}
else if ( mCountDownTime > 0 )
{
mDrawable->SetCountDownMSG( "1" );
mDrawable->SetTextScale( 2.0f );
}
else
{
mDrawable->SetCountDownMSG( "GO!" );
mDrawable->SetTextScale( 2.5f );
//Leave the go up for a little while.
mCountDownTime = 500;
mCurrentPosition = 1;
mNumHumansFinished = 0;
// Temp structures for turbo-on-start hack
int aiIndices[ 3 ];
int numAIs = 0;
int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
int controllerID = GetInputManager()->GetControllerIDforPlayer( i );
if( controllerID != -1 )
{
GetInputManager()->GetController( controllerID )->SetGameState( Input::ACTIVE_ALL );
GetInputManager()->GetController( controllerID )->SetRumble( GetInputManager()->IsRumbleEnabled() );
}
else
{
if( mVehicleSlots[ i ].mVehicleAI != NULL )
{
mVehicleSlots[ i ].mVehicleAI->SetActive( true );
// Remember this AI index for turbo-on-start hack just below..
aiIndices[ numAIs ] = i;
numAIs++;
}
}
}
/////////////////////////
// HACK:
// For each AI, it has a "m-in-n" chance to turbo at the start.
// This helps to avoid cluttering at the start, as well as adds
// life to the game.
//
const int MAX_AIS_DOING_TURBO = numAIs - 1;
int numAIsDoingTurbo = 0;
for( int j=0; j<numAIs; j++ )
{
if( numAIsDoingTurbo < MAX_AIS_DOING_TURBO )
{
int coinflip = rand() % 7;
if( coinflip == 0 || coinflip == 1 || coinflip == 2 )
{
rAssert( 0 <= aiIndices[j] && aiIndices[j] < SuperSprintData::NUM_PLAYERS );
mVehicleSlots[ aiIndices[j] ].mVehicleAI->UseTurbo();
numAIsDoingTurbo++;
}
}
else
{
break;
}
}
// If more than one AI, at least ONE AI will need to do turbo
// so there's no cluttering near the start...
if( numAIs > 1 && numAIsDoingTurbo == 0 )
{
int randAI = rand() % numAIs;
rAssert( 0 <= aiIndices[randAI] && aiIndices[randAI] < SuperSprintData::NUM_PLAYERS );
mVehicleSlots[ aiIndices[randAI] ].mVehicleAI->UseTurbo();
}
//////////////////////////////
GetEventManager()->TriggerEvent( EVENT_FE_MENU_SELECT );
//record the starting time
mStartTime = GET_TIME;
SetState( RACING );
}
//
// Reuse the menu select sound for a countdown sound
//
newTimeSecs = mCountDownTime / 1000;
if( oldTimeSecs != newTimeSecs )
{
GetEventManager()->TriggerEvent( EVENT_FE_MENU_SELECT );
}
break;
}
case RACING:
{
//Watch to see who crosses the finish line first!
if ( mCountDownTime - static_cast<int>(milliseconds) <= 0 )
{
mDrawable->SetRenderState( SuperSprintDrawable::NONE );
mDrawable->SetTextScale( 1.0f );
mCountDownTime = 0;
}
else
{
mCountDownTime -= milliseconds;
}
break;
}
case DNF_TIMEOUT:
{
oldTimeSecs = mCountDownTime / 1000;
if ( mCountDownTime - static_cast<int>(milliseconds) <= 0 )
{
//mDrawable->SetRenderState( SuperSprintDrawable::PLAYER_DATA );
//mDrawable->SetTextScale( 1.0f );
GetEventManager()->TriggerEvent( EVENT_FE_MENU_SELECT );
SetState( WINNER_CIRCLE );
mCountDownTime = 0;
mDrawable->SetRenderState( SuperSprintDrawable::NONE );
DisableAllAI();
DisableAllControllers();
}
else
{
mCountDownTime -= milliseconds;
}
sprintf( mTime, "%d", mCountDownTime / 1000 );
//
// Reuse the menu select sound for a countdown sound
//
newTimeSecs = mCountDownTime / 1000;
if( oldTimeSecs != newTimeSecs )
{
GetEventManager()->TriggerEvent( EVENT_FE_MENU_SELECT );
}
break;
}
case WINNER_CIRCLE:
{
//Display the winner!
GetInputManager()->SetGameState( Input::ACTIVE_SS_GAME );
// go to Race Summary screen
//
GetGameFlow()->GetContext( CONTEXT_SUPERSPRINT )->Suspend();
GetGuiSystem()->GotoScreen( CGuiWindow::GUI_SCREEN_ID_MINI_SUMMARY,
0, 0, CLEAR_WINDOW_HISTORY );
//Calculate your score
int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( mPositions[ i ] == 1 )
{
mPlayers[ i ].mWins++;
//
// We've found a winner. Send the win/lose sound events
//
if( mVehicleSlots[i].mIsHuman )
{
GetEventManager()->TriggerEvent( EVENT_SUPERSPRINT_WIN );
}
else
{
GetEventManager()->TriggerEvent( EVENT_SUPERSPRINT_LOSE );
}
}
if ( mPlayers[ i ].mPosition == 0 )
{
mPlayers[ i ].mPoints += 0; //Joel made me set it to 0
}
else
{
mPlayers[ i ].mPoints += 5 - mPositions[ i ];
}
}
SetState( IDLE );
break;
}
default:
{
break;
}
}
}
//=============================================================================
// SuperSprintManager::LoadScriptData
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::LoadScriptData()
{
HeapMgr()->PushHeap( GMA_LEVEL_OTHER ); // I choose other because this stuff will exist longer than a single mission
char name[64];
sprintf( name, "scripts\\ssi.mfk" );
GetMissionScriptLoader()->SetFileHander( FILEHANDLER_LEVEL );
GetMissionScriptLoader()->LoadScriptAsync( name );
//Also load the carstarts and stuff.
sprintf( name, "art\\B0%ddata.p3d", GetCurrentLevelIndex() ); //Hackish
GetLoadingManager()->AddRequest( FILEHANDLER_LEVEL, name, GMA_LEVEL_OTHER );
HeapMgr()->PopHeap( GMA_LEVEL_OTHER );
//MOve this here so the car con files get loaded in time.
SetUpCars();
GetLoadingManager()->AddCallback( this );
}
//=============================================================================
// SuperSprintManager::StartRace
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::StartRace()
{
PositionCars();
PositionAI();
InitRaceData();
PlaceCharactersInCars(); //TODO: texas scramble
mCountDownTime = 5000;
mDrawable->SetRenderState( SuperSprintDrawable::COUNT_DOWN );
mDrawable->SetTextScale( 1.0f );
InitCamera();
SetupTraps(); //Only do this once.
PlayIntroCam();
SetState( COUNT_DOWN );
}
//=============================================================================
// SuperSprintManager::SetCharacter
//=============================================================================
// Description: Comment
//
// Parameters: ( int playerID, const char* name )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::SetCharacter( int playerID, int index )
{
mPlayers[ playerID ].mCharacterIndex = index;
}
//=============================================================================
// SuperSprintManager::SetVehicle
//=============================================================================
// Description: Comment
//
// Parameters: ( int playerID, const char* name )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::SetVehicle( int playerID, const char* name )
{
rAssert( playerID >= 0 && playerID < SuperSprintData::NUM_PLAYERS );
strncpy( mVehicleSlots[ playerID ].mCarName, name, sizeof( mVehicleSlots[ playerID ].mCarName ) );
}
//=============================================================================
// SuperSprintManager::FindLeader
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: char
//
//=============================================================================
char SuperSprintManager::FindLeader()
{
char leader = -1;
unsigned char numLaps = 0;
char nextCheckpoint = -1;
//For now just figure out who's in the lead.
char i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( mPlayers[ i ].mNumLaps > numLaps )
{
//This guy is in the lead.
leader = i;
numLaps = mPlayers[ i ].mNumLaps;
nextCheckpoint = mPlayers[ i ].mNextCheckPoint;
}
else if ( mPlayers[ i ].mNumLaps == numLaps )
{
if ( mPlayers[ i ].mNextCheckPoint > nextCheckpoint )
{
//This guys is in the lead.
leader = i;
numLaps = mPlayers[ i ].mNumLaps;
nextCheckpoint = mPlayers[ i ].mNextCheckPoint;
}
}
}
return leader;
}
//=============================================================================
// SuperSprintManager::CalculatePositions
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::CalculatePositions()
{
#if defined( RAD_DEBUG ) || defined( RAD_TUNE )
char errMsg[128];
#endif
int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; i++ )
{
if ( mPlayers[ i ].mNumLaps == mNumLaps )
{
//No more updates for this guy.
continue;
}
if ( !mVehicleSlots[ i ].mIsHuman )
{
WaypointAI* ai = mVehicleSlots[ i ].mVehicleAI;
rmt::Vector aiPos;
ai->GetPosition( &aiPos );
/*
// reset as necessary.
rmt::Sphere aiSphere;
ai->GetVehicle()->GetBoundingSphere( &aiSphere );
SuperCam* superCam = GetSuperCamManager()->GetSCC(0)->GetActiveSuperCam();
rAssert( superCam );
if( superCam->GetType() == SuperCam::SUPER_SPRINT_CAM &&
!superCam->GetCamera()->SphereVisible( aiPos, aiSphere.radius ) )
{
ai->GetVehicle()->ResetOnSpot( false );
}
*/
//////////////////////////////////////////////////////
// Query the road manager to get the distance
RoadManager::PathElement aiElem;
aiElem.elem = NULL;
RoadSegment* aiSeg = NULL;
float aiSegT = 0.0f;
float aiRoadT = 0.0f;
ai->GetRacePathInfo( aiElem, aiSeg, aiSegT, aiRoadT );
// make sure the AI is on a path element
#if defined( RAD_DEBUG ) || defined( RAD_TUNE )
sprintf( errMsg, "Something wrong with player %d!\n", i+1 );
rTuneAssertMsg( aiElem.elem != NULL, errMsg );
rTuneAssertMsg( 0 <= mPlayers[ i ].mNextCheckPoint &&
mPlayers[ i ].mNextCheckPoint < GetNumCheckpoints(), errMsg );
#endif
char nextCheckpoint = mCheckPoints[ mPlayers[ i ].mNextCheckPoint ];
int path = GetPathDataWith( GetCheckpointWith( nextCheckpoint ) );
rAssert( path != -1 );
RoadManager::PathElement collectibleElem = mPathData[ path ].closestElem;
float collectibleRoadT = mPathData[ path ].roadT;
rmt::Vector collectiblePos;
mPathData[ path ].loc->GetLocation( &collectiblePos );
// make sure the collectible is on a path element
rAssert( collectibleElem.elem != NULL );
float aiDistToColl = NEAR_INFINITY;
if( aiElem.elem != NULL && collectibleElem.elem != NULL )
{
SwapArray<RoadManager::PathElement> dummy;
HeapMgr()->PushHeap(GMA_TEMP);
dummy.Allocate( RoadManager::GetInstance()->GetMaxPathElements() );
HeapMgr()->PopHeap(GMA_TEMP);
aiDistToColl = RoadManager::GetInstance()->FindPathElementsBetween(
false,
aiElem, aiRoadT, aiPos,
collectibleElem, collectibleRoadT, collectiblePos,
dummy );
}
ai->SetDistToCurrentCollectible( aiDistToColl );
mPlayers[ i ].mDistToCheckpoint = aiDistToColl;
}
else
{
////////////////////////////////////////////////////////
// Find out player's dist to mNextCollectible
//
Avatar* player = GetAvatarManager()->GetAvatarForPlayer( i );
rAssert( player );
rmt::Vector playerPos;
player->GetPosition( playerPos );
/*
// if player has gone out of bounds, reset to nearest segment
rmt::Sphere playerSphere;
player->GetVehicle()->GetBoundingSphere( &playerSphere );
SuperCam* superCam = GetSuperCamManager()->GetSCC(0)->GetActiveSuperCam();
rAssert( superCam );
if( superCam->GetType() == SuperCam::SUPER_SPRINT_CAM &&
!superCam->GetCamera()->SphereVisible( playerPos, playerSphere.radius ) )
{
player->GetVehicle()->ResetOnSpot( false );
player->mHasBeenUpdatedThisFrame = false;
}
*/
RoadManager::PathElement playerElem;
playerElem.elem = NULL;
RoadSegment* playerSeg = NULL;
float playerSegT = 0.0f;
float playerRoadT = 0.0f;
player->GetLastPathInfo( playerElem, playerSeg, playerSegT, playerRoadT );
#if defined( RAD_DEBUG ) || defined( RAD_TUNE )
rTuneAssertMsg( playerElem.elem != NULL, errMsg );
rTuneAssertMsg( 0 <= mPlayers[ i ].mNextCheckPoint &&
mPlayers[ i ].mNextCheckPoint < GetNumCheckpoints(), errMsg );
#endif
char nextCheckpoint = mCheckPoints[ mPlayers[ i ].mNextCheckPoint ];
int path = GetPathDataWith( GetCheckpointWith( nextCheckpoint ) );
rAssert( path != -1 );
RoadManager::PathElement collectibleElem = mPathData[ path ].closestElem;
float collectibleRoadT = mPathData[ path ].roadT;
rmt::Vector collectiblePos;
mPathData[ path ].loc->GetLocation( &collectiblePos );
// make sure the collectible is on a path element
rAssert( collectibleElem.elem != NULL );
float playerDistToCurrCollectible = NEAR_INFINITY;
if( playerElem.elem != NULL && collectibleElem.elem != NULL )
{
SwapArray<RoadManager::PathElement> dummy;
HeapMgr()->PushHeap(GMA_TEMP);
dummy.Allocate( RoadManager::GetInstance()->GetMaxPathElements() );
HeapMgr()->PopHeap(GMA_TEMP);
playerDistToCurrCollectible = RoadManager::GetInstance()->FindPathElementsBetween(
false,
playerElem, playerRoadT, playerPos,
collectibleElem, collectibleRoadT, collectiblePos,
dummy );
}
mPlayers[ i ].mDistToCheckpoint = playerDistToCurrCollectible;
}
}
////////////////////////////////////////////////////////////////////
// Update my position
//
unsigned int j;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( mPlayers[ i ].mNumLaps == mNumLaps )
{
//No more updates for this guy.
continue;
}
unsigned int numInFront = 0;
unsigned int vehiclesWithMe[ SuperSprintData::NUM_PLAYERS ];
unsigned int numWithMe = 0;
unsigned int numFinished = 0;
int whichOtherPlayer = (i + 1) % SuperSprintData::NUM_PLAYERS;
for( j = 0; j < SuperSprintData::NUM_PLAYERS - 1; ++j )
{
int numLapsCompleted = mPlayers[ whichOtherPlayer ].mNumLaps;
if ( numLapsCompleted == mNumLaps )
{
//They're finshed racing
numFinished++;
}
else if ( numLapsCompleted > mPlayers[ i ].mNumLaps )
{
//This guys finished more laps than I.
numInFront++;
}
else if ( numLapsCompleted == mPlayers[ i ].mNumLaps )
{
//We're racing the same lap number.
char currCollectible = mPlayers[ whichOtherPlayer ].mNextCheckPoint;
char playerCollectible = mPlayers[ i ].mNextCheckPoint;
if( currCollectible > playerCollectible )
{
numInFront++;
}
else if( currCollectible == playerCollectible )
{
vehiclesWithMe[ numWithMe ] = whichOtherPlayer;
numWithMe++;
}
}
whichOtherPlayer = ( whichOtherPlayer + 1 ) % SuperSprintData::NUM_PLAYERS;
}
mPositions[ i ] = 1 + numInFront + numFinished;
//Now, who is actually in front of me going to the same waypoint?
const Locator* waypointLoc = GetCheckpointWith( mCheckPoints[ mPlayers[ i ].mNextCheckPoint ] );
if ( !waypointLoc )
{
rAssert( false ); //Why? Because we've not started to race yet.
return;
}
////////////////////////////////////////////////////////////
// The last set of vehicles to consider are the ones that
// are headed to the same collectible (race checkpoint) and
// are in the same lap as we are...
//
for( j = 0; j < numWithMe; ++j )
{
int index = vehiclesWithMe[ j ];
//This guy and I are racing for the same collectible
//Test the dist to the collectible.
float aiDistToCurrCollectible = mPlayers[ index ].mDistToCheckpoint;
float playerDistToCurrCollectible = mPlayers[ i ].mDistToCheckpoint;
if( aiDistToCurrCollectible < playerDistToCurrCollectible )
{
// blast! he's ahead of me... my pos is thus bumped even lower...
mPositions[ i ] = mPositions[ i ] + 1;
}
}
}
}
//=============================================================================
// SuperSprintManager::LoadLevelData
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::LoadLevelData()
{
char name[64];
sprintf( name, "scripts\\ss.mfk" );
BillboardWrappedLoader::OverrideLoader( true );
HeapMgr()->PushHeap( GMA_LEVEL_OTHER ); // I choose other because this stuff will exist longer than a single mission
GetMissionScriptLoader()->SetFileHander( FILEHANDLER_LEVEL );
GetMissionScriptLoader()->LoadScriptAsync( name );
HeapMgr()->PopHeap( GMA_LEVEL_OTHER );
BillboardWrappedLoader::OverrideLoader( false );
}
//=============================================================================
// SuperSprintManager::Reset
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::Reset()
{
//Reset the same race with all the existing cars and stuff.
PositionCars();
PositionAI();
ResetRaceData();
mCountDownTime = 5000;
mDrawable->SetRenderState( SuperSprintDrawable::COUNT_DOWN );
mDrawable->SetTextScale( 1.0f );
InitCamera();
PlayIntroCam();
SetState( COUNT_DOWN );
}
//=============================================================================
// SuperSprintManager::OnButton
//=============================================================================
// Description: Comment
//
// Parameters: ( int controllerId, int id, const Button* pButton )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::OnButton( int controllerId, int id, const Button* pButton )
{
}
//=============================================================================
// SuperSprintManager::OnButtonUp
//=============================================================================
// Description: Comment
//
// Parameters: ( int controllerId, int buttonId, const Button* pButton )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::OnButtonUp( int controllerId, int buttonId, const Button* pButton )
{
if ( buttonId == ShowPositions )
{
int playerID = GetInputManager()->GetControllerPlayerIDforController( controllerId );
if ( playerID >= 0 && playerID < SuperSprintData::NUM_PLAYERS )
{
mTogglePosition[ playerID ] = false;
}
}
}
//=============================================================================
// SuperSprintManager::OnButtonDown
//=============================================================================
// Description: Comment
//
// Parameters: ( int controllerId, int buttonId, const Button* pButton )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::OnButtonDown( int controllerId, int buttonId, const Button* pButton )
{
switch ( mCurrentState )
{
case RACING:
{
int playerID = GetInputManager()->GetControllerPlayerIDforController( controllerId );
if ( playerID == -1 )
{
playerID = controllerId;
rAssert( playerID < SuperSprintData::NUM_PLAYERS );
if( playerID >= SuperSprintData::NUM_PLAYERS )
{
return;
}
}
int controllerIDPlayer = GetInputManager()->GetControllerIDforPlayer( playerID );
if ( buttonId == CamSelect && mVehicleSlots[ playerID ].mIsHuman && !GetGameFlow()->GetContext( CONTEXT_SUPERSPRINT )->IsSuspended())
{
unsigned int playerCount = 0;
int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( mVehicleSlots[ i ].mIsHuman )
{
++playerCount;
}
}
if ( playerCount == 1 )
{
GetSuperCamManager()->GetSCC( 0 )->SetTarget( mVehicleSlots[ playerID ].mVehicle );
if ( GetSuperCamManager()->GetSCC( 0 )->GetActiveSuperCam()->GetType() == SuperCam::WRECKLESS_CAM )
{
//Skip the animated cams.
GetSuperCamManager()->GetSCC( 0 )->SelectSuperCam( (unsigned int)0 );
}
else
{
GetSuperCamManager()->GetSCC( 0 )->ToggleSuperCam( true );
}
}
}
break;
}
default:
{
break;
}
}
if ( buttonId == ShowPositions )
{
int playerID = GetInputManager()->GetControllerPlayerIDforController( controllerId );
if ( playerID >= 0 && playerID < SuperSprintData::NUM_PLAYERS )
{
mTogglePosition[ playerID ] = true;
}
}
}
//=============================================================================
// SuperSprintManager::LoadControllerMappings
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int controllerId )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::LoadControllerMappings( unsigned int controllerId )
{
if ( GetInputManager()->GetController( controllerId )->IsConnected() )
{
#ifdef RAD_XBOX
ClearMap(0);
Map( "Start", Start, 0, controllerId );
Map( "A", Select, 0, controllerId );
Map( "B", Back, 0, controllerId );
Map( "DPadRight", Right, 0, controllerId );
Map( "DPadLeft", Left, 0, controllerId );
Map( "LeftStickX", StickX, 0, controllerId );
Map( "LeftTrigger", L1, 0, controllerId );
Map( "Black", CamSelect, 0, controllerId );
Map( "Y", ShowPositions, 0, controllerId );
#endif
#ifdef RAD_PS2
ClearMap(0);
Map( "Start", Start, 0, controllerId );
Map( "X", Select, 0, controllerId );
Map( "Triangle", Back, 0, controllerId );
Map( "DPadRight", Right, 0, controllerId );
Map( "DPadLeft", Left, 0, controllerId );
Map( "LeftStickX", StickX, 0, controllerId );
Map( "L1", L1, 0, controllerId );
Map( "Select", CamSelect, 0, controllerId );
Map( "Triangle", ShowPositions, 0, controllerId );
#endif
#ifdef RAD_GAMECUBE
ClearMap(0);
Map( "Menu", Start, 0, controllerId );
Map( "A", Select, 0, controllerId );
Map( "B", Back, 0, controllerId );
Map( "DPadRight", Right, 0, controllerId );
Map( "DPadLeft", Left, 0, controllerId );
Map( "LeftStickX", StickX, 0, controllerId );
Map( "AnalogTriggerL", L1, 0, controllerId );
Map( "DPadDown", CamSelect, 0, controllerId );
Map( "Y", ShowPositions, 0, controllerId );
#endif
#ifdef RAD_WIN32
ClearMap(0);
Map( "Pause", Start, 0, controllerId );
Map( "Attack", Select, 0, controllerId );
Map( "Jump", Back, 0, controllerId );
Map( "MoveRight", Right, 0, controllerId );
Map( "MoveLeft", Left, 0, controllerId );
Map( "MoveX", StickX, 0, controllerId );
//Map( "LeftTrigger", L1, 0, controllerId );
Map( "CameraToggle", CamSelect, 0, controllerId );
#endif
}
}
//=============================================================================
// SuperSprintManager::OnControllerConnect
//=============================================================================
// Description: Comment
//
// Parameters: ( int id )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::OnControllerConnect( int id )
{
int playerID = GetInputManager()->GetControllerPlayerIDforController( id );
if ( playerID != -1 && mVehicleSlots[ playerID ].mState == SuperSprintData::CarData::SELECTED &&
static_cast<int>( mPlayers[ playerID ].mNumLaps ) < mNumLaps &&
mVehicleSlots[ playerID ].mIsHuman &&
(mCurrentState == RACING || mCurrentState == DNF_TIMEOUT) )
{
GetInputManager()->GetController( id )->SetGameState( Input::ACTIVE_ALL );
GetInputManager()->GetController( id )->SetRumble( GetInputManager()->IsRumbleEnabled() );
}
else
{
GetInputManager()->GetController( id )->SetGameState( Input::ACTIVE_SS_GAME );
}
}
//=============================================================================
// SuperSprintManager::OnControllerDisconnect
//=============================================================================
// Description: Comment
//
// Parameters: ( int id )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::OnControllerDisconnect( int id )
{
}
//=============================================================================
// SuperSprintManager::GetNumCheckpoints
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: char
//
//=============================================================================
char SuperSprintManager::GetNumCheckpoints()
{
if ( mNumCheckPoints == 0 )
{
if ( (RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B02 ||
(RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B07 )
{
if ( mGoLeft )
{
mCheckPoints = CHECKPOINT_LIST_B02_R;
}
else
{
mCheckPoints = CHECKPOINT_LIST_B02;
}
mNumCheckPoints = sizeof( CHECKPOINT_LIST_B02 ) / sizeof( char );
}
else if ( (RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B05 )
{
if ( mGoLeft )
{
mCheckPoints = CHECKPOINT_LIST_B05_R;
}
else
{
mCheckPoints = CHECKPOINT_LIST_B05;
}
mNumCheckPoints = sizeof( CHECKPOINT_LIST_B05 ) / sizeof( char );
}
else if ( (RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B01 )
{
if ( mGoLeft )
{
mCheckPoints = CHEKPOINT_LIST_B01_R;
}
else
{
mCheckPoints = CHEKPOINT_LIST_B01;
}
mNumCheckPoints = sizeof( CHEKPOINT_LIST_B01 ) / sizeof( char );
}
else if ( ((RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B03 ) ||
((RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B04 )||
((RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B06 ) )
{
if ( mGoLeft )
{
mCheckPoints = CHECKPOINT_LIST_B03_R;
}
else
{
mCheckPoints = CHECKPOINT_LIST_B03;
}
mNumCheckPoints = sizeof( CHECKPOINT_LIST_B03 ) / sizeof( char );
}
else
{
if ( mGoLeft )
{
mCheckPoints = CHECKPOINT_LIST_R;
}
else
{
mCheckPoints = CHECKPOINT_LIST;
}
mNumCheckPoints = sizeof( CHECKPOINT_LIST ) / sizeof( char );
}
}
return mNumCheckPoints;
}
//*****************************************************************************
//
// Protected Member Functions
//
//*****************************************************************************
//*****************************************************************************
//
// Private Member Functions
//
//*****************************************************************************
//=============================================================================
// SuperSprintManager::SetUpCars
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::SetUpCars()
{
unsigned int conFileIndex = 1;
for( int i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( mVehicleSlots[ i ].mState == SuperSprintData::CarData::SELECTED )
{
mNumActivePlayers++;
char* carName = mVehicleSlots[i].mCarName; //Why does this have to be non-const?
if( mVehicleSlots[ i ].mIsHuman )
{
mNumHumanPlayers++;
mVehicleSlots[ i ].mVehicle = GetVehicleCentral()->InitVehicle( carName, true, NULL, VT_USER,
VehicleCentral::FORCE_NO_DRIVER,
false, // playercar - I think this is chucks thing for the character sheet
false); // one of the few rare cases where we start in the car
}
else
{
char scriptName[64];
sprintf( scriptName, "bonus/bg%d_%d.con", GetCurrentLevelIndex(), conFileIndex );
mVehicleSlots[ i ].mVehicle = GetVehicleCentral()->InitVehicle( carName, true, scriptName, VT_AI, VehicleCentral::FORCE_NO_DRIVER, false, false ); // see comments above
++conFileIndex;
}
rAssert( mVehicleSlots[ i ].mVehicle );
mVehicleSlots[ i ].mVehicle->AddRef();
int added = GetVehicleCentral()->AddVehicleToActiveList( mVehicleSlots[ i ].mVehicle );
rAssert( added != -1 );
mVehicleSlots[ i ].mActiveListIndex = added;
}
if( mVehicleSlots[ i ].mVehicle != NULL )
{
GetSuperCamManager()->GetSCC( i )->SetTarget( mVehicleSlots[ i ].mVehicle );
GetSoundManager()->LoadCarSound( mVehicleSlots[ i ].mVehicle, false );
}
}
}
//=============================================================================
// SuperSprintManager::CleanUpCars
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::CleanUpCars()
{
int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( mVehicleSlots[ i ].mVehicle != NULL )
{
// drop character out of the car...
Character* playerCharacter = GetAvatarManager()->GetAvatarForPlayer( i )->GetCharacter();
//PlaceCharacterAtLocator( playerCharacter, this->m );
GetAvatarManager()->PutCharacterOnGround( playerCharacter, mVehicleSlots[ i ].mVehicle );
GetVehicleCentral()->RemoveVehicleFromActiveList( mVehicleSlots[ i ].mVehicle );
mVehicleSlots[ i ].mVehicle->Release();
mVehicleSlots[ i ].mVehicle = NULL;
}
if( mVehicleSlots[ i ].mVehicleAI != NULL )
{
rAssert( mVehicleSlots[ i ].mActiveListIndex != -1 );
GetVehicleCentral()->SetVehicleController( mVehicleSlots[ i ].mActiveListIndex, NULL );
mVehicleSlots[ i ].mVehicleAI->SetActive( false );
mVehicleSlots[ i ].mVehicleAI->Finalize();
mVehicleSlots[ i ].mVehicleAI->Release();
mVehicleSlots[ i ].mVehicleAI = NULL;
}
mVehicleSlots[ i ].mActiveListIndex = -1;
}
//Dump the car geo.
p3d::pddi->DrawSync();
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
p3d::inventory->RemoveSectionElements( mVehicleSlots[ i ].mCarName );
p3d::inventory->DeleteSection( mVehicleSlots[ i ].mCarName );
}
mNumActivePlayers = 0;
mNumHumanPlayers = 0;
mNumHumansFinished = 0;
}
//=============================================================================
// SuperSprintManager::PositionCars
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::PositionCars()
{
unsigned int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
// figure out the start position ...
char carlocator[32];
sprintf( carlocator, "car%d", i + 1 );
CarStartLocator* loc = p3d::find<CarStartLocator>(carlocator);
rAssert( loc );
if ( loc )
{
rmt::Vector pos;
float facing;
loc->GetLocation( &pos );
facing = loc->GetRotation();
if ( mGoLeft )
{
//We go Left.
facing += rmt::PI;
}
rAssert( mVehicleSlots[ i ].mVehicle );
mVehicleSlots[ i ].mVehicle->SetInitialPosition( &pos );
mVehicleSlots[ i ].mVehicle->SetResetFacingInRadians( facing );
mVehicleSlots[ i ].mVehicle->Reset();
}
}
DisableAllControllers();
}
//=============================================================================
// SuperSprintManager::PositionAI
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::PositionAI()
{
///////////////////////////////////////////////////
// Go through all the waypoints, accumulating them...
//
Locator* waypoints[ MAX_AI_WAYPOINTS ];
int nWaypoints = 0;
// can either drive left around the track or right around the track
char waypointDir[4];
if( mGoLeft )
{
sprintf( waypointDir, "WPL" );
}
else
{
sprintf( waypointDir, "WPR" );
}
// iterate from 1 to MAX_AI_WAYPOINTS (inclusive)
char waypointName[8];
unsigned int i;
for( i = 1; i <= MAX_AI_WAYPOINTS; ++i )
{
if( i < 10 )
{
sprintf( waypointName, "%s0%d", waypointDir, i );
}
else
{
rAssert( i < 100 ); // keep it to 2 digits
sprintf( waypointName, "%s%d", waypointDir, i );
}
waypointName[5] = '\0';
Locator* wayloc = p3d::find<Locator>( waypointName );
if( wayloc == NULL )
{
// well... no more waypoints, just quit
break;
}
waypoints[ nWaypoints ] = wayloc;
nWaypoints++;
}
if( nWaypoints <= 0 )
{
rDebugPrintf( "SUPERSPRINT WARNING: Uh... We didn't see any waypoints"
"for AI. AI-controlled vehicles will not budge.\n" );
}
mNumCheckPointLocators = 0;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
// Put in the AI here...
const float smallTriggerRadius = 7.0f;
if( !mVehicleSlots[ i ].mIsHuman )
{
if ( mVehicleSlots[ i ].mVehicleAI == NULL )
{
mVehicleSlots[ i ].mVehicleAI = new WaypointAI( mVehicleSlots[ i ].mVehicle, false, smallTriggerRadius, true ); // indicate false to segment optimization
mVehicleSlots[ i ].mVehicleAI->SetUseMultiplier( false ); // no traffic in supersprint... no need for multiplier
mVehicleSlots[ i ].mVehicleAI->AddRef(); // Corresponding call to Release() will already call delete if refcount<=1
}
else
{
//Cleanup to restart
mVehicleSlots[ i ].mVehicleAI->Finalize();
}
mVehicleSlots[ i ].mVehicleAI->Initialize();
// Just before this, we obtained a list of waypoints...
// Add them to the AIs here
for( int j=0; j<nWaypoints; j++ )
{
static_cast<WaypointAI*>(mVehicleSlots[ i ].mVehicleAI)->AddWaypoint( waypoints[j] );
}
}
}
DisableAllAI();
p3d::inventory->PushSection();
p3d::inventory->SelectSection( "Level" );
HeapMgr()->PushHeap( GMA_TEMP );
tInventory::Iterator<EventLocator> it( p3d::inventory );
EventLocator* loc = it.First();
while( loc != NULL )
{
if ( loc->GetEventType() == LocatorEvent::CHECK_POINT && loc->GetData() > 0 )
{
mCheckPointLocators[ mNumCheckPointLocators ] = loc;
//mCheckPointLocators[ mNumCheckPointLocators ]->AddRef();
++mNumCheckPointLocators;
}
loc = it.Next();
}
HeapMgr()->PopHeap( GMA_TEMP );
p3d::inventory->PopSection();
for( i = 0; i < mNumCheckPointLocators; i++ )
{
rAssert( mCheckPointLocators[ i ] != NULL );
rmt::Vector locPos;
mCheckPointLocators[ i ]->GetPosition( &locPos );
//////////////////////////////////////////////////
// Get what the locator was placed on & other info
//
// NOTE: We assume that a collectible isn't going to move..
// and that it's always either on a road segment or
// an intersection... This is safe to do because
// the information below is only going to be used
// for race objectives (a subclass of collectibleobjective)
// which requires that its collectibles don't move around.
// It's not that bad to fix it if this changes... we
// will simply need to re-invoke FindClosestPathElement
// every frame, as the collectible moves around and
// remember the last valid (non-off-road) values.
//
RoadSegment* seg = NULL;
float segT = 0.0f;
float roadT = 0.0f;
RoadManager::PathElement closestElem;
closestElem.elem = NULL;
bool succeeded = VehicleAI::FindClosestPathElement( locPos, closestElem, seg, segT, roadT, true );
if( !succeeded )
{
char msg[512];
sprintf( msg, "Locator at (%0.1f,%0.1f,%0.1f) must either be placed on a roadsegment "
"or in an intersection! Woe be the designer who placed down this locator! "
"For now, the closest road segment will be chosen instead.\n",
locPos.x, locPos.y, -1 * locPos.z );
rAssertMsg( false, msg );
RoadSegment* closestSeg = NULL;
float dummy;
GetIntersectManager()->FindClosestRoad( locPos, 100.0f, closestSeg, dummy );
seg = (RoadSegment*) closestSeg;
segT = RoadManager::DetermineSegmentT( locPos, seg );
roadT = RoadManager::DetermineRoadT( seg, segT );
closestElem.elem = seg->GetRoad();
closestElem.type = RoadManager::ET_NORMALROAD;
}
mPathData[ i ].closestElem = closestElem;
mPathData[ i ].seg = seg;
mPathData[ i ].segT = segT;
mPathData[ i ].roadT = roadT;
mPathData[ i ].loc = mCheckPointLocators[ i ];
rAssert( mPathData[ i ].closestElem.elem != NULL );
}
}
//=============================================================================
// SuperSprintManager::DisableAllAI
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::DisableAllAI()
{
unsigned int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( !mVehicleSlots[ i ].mIsHuman )
{
mVehicleSlots[ i ].mVehicleAI->SetActive( false );
}
}
}
//=============================================================================
// SuperSprintManager::DisableAllControllers
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::DisableAllControllers()
{
GetInputManager()->SetGameState( Input::ACTIVE_SS_GAME );
unsigned int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; i++ )
{
int controllerID = GetInputManager()->GetControllerIDforPlayer( i );
if( controllerID != -1 )
{
GetInputManager()->SetRumbleForDevice( controllerID, false );
}
}
}
//=============================================================================
// SuperSprintManager::InitRaceData
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::InitRaceData()
{
unsigned int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
//Reset the player race data.
mPlayers[ i ].mBestLap = 0xffffffff;
mPlayers[ i ].mBestLapEntry = 0;
mPlayers[ i ].mBestTimeEntry = 0;
mPlayers[ i ].mLapTime = 0;
mPlayers[ i ].mNextCheckPoint = 0;
mPlayers[ i ].mNumLaps = 0;
mPlayers[ i ].mPosition = 0;
mPlayers[ i ].mWins = 0;
mPlayers[ i ].mRaceTime = 0;
mPlayers[ i ].mPoints = 0;
mPlayers[ i ].mDistToCheckpoint = NEAR_INFINITY;
mVehicleSlots[ i ].mVehicle->mNumTurbos = SuperSprintData::DEFAULT_TURBO_NUM;
mPositions[ i ] = i;
}
}
//=============================================================================
// SuperSprintManager::ResetRaceData
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::ResetRaceData()
{
unsigned int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
//Reset the player race data.
mPlayers[ i ].mBestLap = 0xffffffff;
mPlayers[ i ].mBestLapEntry = 0;
mPlayers[ i ].mBestTimeEntry = 0;
mPlayers[ i ].mLapTime = 0;
mPlayers[ i ].mNextCheckPoint = 0;
mPlayers[ i ].mNumLaps = 0;
mPlayers[ i ].mPosition = 0;
mPlayers[ i ].mRaceTime = 0;
mPlayers[ i ].mDistToCheckpoint = NEAR_INFINITY;
mVehicleSlots[ i ].mVehicle->mNumTurbos = SuperSprintData::DEFAULT_TURBO_NUM;
mPositions[ i ] = i;
}
}
//=============================================================================
// SuperSprintManager::PlaceCharactersInCars
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::PlaceCharactersInCars()
{
int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( mVehicleSlots[ i ].mState == SuperSprintData::CarData::SELECTED )
{
GetAvatarManager()->PutCharacterInCar( GetAvatarManager()->GetAvatarForPlayer( i )->GetCharacter(), mVehicleSlots[i].mVehicle );
if( !mVehicleSlots[ i ].mIsHuman )
{
GetVehicleCentral()->SetVehicleController(
mVehicleSlots[ i ].mActiveListIndex,
mVehicleSlots[ i ].mVehicleAI );
}
}
}
}
//=============================================================================
// SuperSprintManager::StartLoadingCars
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::LoadCars()
{
HeapMgr()->PushHeap( GMA_LEVEL_OTHER );
for( int i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
// Force unjoined positions to be AI-controlled
if( mVehicleSlots[ i ].mState == SuperSprintData::CarData::WAITING )
{
//Let's randomly pick a car.
unsigned int carNum = rand() % SuperSprintData::NUM_NAMES;
while ( strcmp( SuperSprintData::VEHICLE_NAMES[ carNum ].name, mVehicleSlots[ (i + 1) % SuperSprintData::NUM_PLAYERS ].mCarName ) == 0 ||
strcmp( SuperSprintData::VEHICLE_NAMES[ carNum ].name, mVehicleSlots[ (i + 2) % SuperSprintData::NUM_PLAYERS ].mCarName ) == 0 ||
strcmp( SuperSprintData::VEHICLE_NAMES[ carNum ].name, mVehicleSlots[ (i + 3) % SuperSprintData::NUM_PLAYERS ].mCarName ) == 0 )
{
carNum = rand() % SuperSprintData::NUM_NAMES;
}
SetVehicle( i, SuperSprintData::VEHICLE_NAMES[ carNum ].name );
// transit to SELECTED, so that our car will get loaded, below
mVehicleSlots[ i ].mState = SuperSprintData::CarData::SELECTED;
}
//Force undecided players to the current selection.
if ( mVehicleSlots[ i ].mState == SuperSprintData::CarData::SELECTING )
{
mVehicleSlots[ i ].mState = SuperSprintData::CarData::SELECTED;
}
if ( mVehicleSlots[ i ].mState == SuperSprintData::CarData::SELECTED )
{
char fileName[64];
sprintf( fileName, "art\\cars\\%s.p3d", mVehicleSlots[ i ].mCarName );
p3d::inventory->AddSection( mVehicleSlots[ i ].mCarName );
GetLoadingManager()->AddRequest( FILEHANDLER_LEVEL,
fileName,
GMA_LEVEL_OTHER,
mVehicleSlots[ i ].mCarName,
mVehicleSlots[ i ].mCarName );
}
}
//When we get this callback, the loading of all cars is done.
// GetLoadingManager()->AddCallback( this );
HeapMgr()->PopHeap( GMA_LEVEL_OTHER );
mDrawable->DoCountDownToo( false );
}
//=============================================================================
// SuperSprintManager::LoadCharacters
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::LoadCharacters()
{
unsigned int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if ( !mVehicleSlots[ i ].mIsHuman )
{
//We need to select a character for this AI.
unsigned int whichName = rand() % SuperSprintData::NUM_CHARACTER_NAMES;
unsigned int j;
for ( j = 0; j < SuperSprintData::NUM_CHARACTER_NAMES; ++j )
{
bool found = false;
unsigned int k;
for ( k = 0; k < SuperSprintData::NUM_PLAYERS && !found; ++k )
{
if ( SuperSprintData::CHARACTER_NAMES[ mPlayers[ k ].mCharacterIndex ] != '\0' &&
( mPlayers[ k ].mCharacterIndex == static_cast<int>( whichName ) ) )
{
//This name is taken.
found = true;
break;
}
}
if ( found )
{
whichName = ( whichName + 1 ) % SuperSprintData::NUM_CHARACTER_NAMES;
}
else
{
//We have a winner!
break;
}
}
rAssert( j < SuperSprintData::NUM_CHARACTER_NAMES );
SetCharacter( i, whichName );
}
GetCharacterManager()->AddPCCharacter( SuperSprintData::CHARACTER_NAMES[ mPlayers[ i ].mCharacterIndex ], "npd" );
}
}
//=============================================================================
// SuperSprintManager::EnumerateControllers
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::EnumerateControllers()
{
//Set up the controllers.
InputManager* im = GetInputManager();
unsigned int i;
for ( i = 0; i < Input::MaxControllers; ++i )
{
im->UnregisterMappable( i, this );
}
for ( i = 0; i < Input::MaxControllers; ++i )
{
int handle = im->RegisterMappable( i, this );
rAssert( handle != -1 );
}
}
//=============================================================================
// SuperSprintManager::SetupIcons
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::SetupIcons()
{
//Get and init the two flags.
mFFlag->Init( "fflag", rmt::Vector( 3.0f, 6.0f, -40.0f ), false, false );
mFFlag->ScaleByCameraDistance( 1.0f, 3.0f, 10.0f, 100.0f );
mWFlag->Init( "wflag", rmt::Vector( 1.8f, 6.0f, -40.0f ), false, false );
mWFlag->ScaleByCameraDistance( 1.0f, 3.0f, 10.0f, 100.0f );
int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
char name[64];
sprintf( name, "MiniArrow%dr", i + 1 ); //Start at 1
mPositionIcon[ 0 ][ i ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mPositionIcon[ 0 ][ i ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
sprintf( name, "MiniArrow%db", i + 1 ); //Start at 1
mPositionIcon[ 1 ][ i ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mPositionIcon[ 1 ][ i ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
sprintf( name, "MiniArrow%dy", i + 1 ); //Start at 1
mPositionIcon[ 2 ][ i ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mPositionIcon[ 2 ][ i ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
sprintf( name, "MiniArrow%dg", i + 1 ); //Start at 1
mPositionIcon[ 3 ][ i ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mPositionIcon[ 3 ][ i ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
sprintf( name, "MiniArrowP%d", i + 1 );
mPlayerID[ i ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mPlayerID[ i ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
}
char name[64];
sprintf( name, "MiniArrow%drGlow", 1 );
mNitroEffect[ 0 ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mNitroEffect[ 0 ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
sprintf( name, "MiniArrow%dbGlow", 2 );
mNitroEffect[ 1 ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mNitroEffect[ 1 ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
sprintf( name, "MiniArrow%dyGlow", 3 );
mNitroEffect[ 2 ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mNitroEffect[ 2 ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
sprintf( name, "MiniArrow%dgGlow", 4 );
mNitroEffect[ 3 ]->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false );
mNitroEffect[ 3 ]->ScaleByCameraDistance( MIN_SCALE, MAX_SCALE, MIN_DIST, MAX_DIST );
}
//=============================================================================
// SuperSprintManager::InitCamera
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::InitCamera()
{
for( int i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
SuperCamCentral* scc = GetSuperCamManager()->GetSCC( i );
rAssert( scc );
scc->SelectSuperCam( SuperCam::SUPER_SPRINT_CAM, SuperCamCentral::CUT | SuperCamCentral::QUICK, 0 );
}
}
int SuperSprintManager::GetOnlyHumanPlayerID()
{
int onlyHumanID = -1;
int humanCount = 0;
for( int i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
if( mVehicleSlots[ i ].mIsHuman )
{
onlyHumanID = i;
humanCount++;
}
}
if( humanCount == 1 ) // only return the ID of the one human player
{
return onlyHumanID;
}
return -1;
}
//=============================================================================
// SuperSprintManager::RestoreControllerState
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::RestoreControllerState()
{
unsigned int i;
for ( i = 0; i < Input::MaxControllers; ++i )
{
OnControllerConnect( i );
}
}
//=============================================================================
// SuperSprintManager::SetupTraps
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::SetupTraps()
{
//Get the spikes if we need them
if ( (RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B07 )
{
//Find the trap multicontroller.
p3d::inventory->PushSection();
p3d::inventory->SelectSection( "Default" );
mTrapController = p3d::find<AnimCollisionEntityDSG>( "spikes" );
mTrapController->AddRef();
//Set them running backwards so that it doesn't animate.
mTrapController->SetAnimationDirection( -1.0f );
p3d::inventory->PopSection();
rAssert( mTrapController );
}
else if ( (RenderEnums::LevelEnum)(GetCurrentLevelIndex() + RenderEnums::B00) == RenderEnums::B04 )
{
//Find the trap multicontroller.
p3d::inventory->PushSection();
p3d::inventory->SelectSection( "Default" );
mTrapController = p3d::find<AnimCollisionEntityDSG>( "pistons" );
mTrapController->AddRef();
//Set them running backwards so that it doesn't animate.
mTrapController->SetAnimationDirection( -1.0f );
p3d::inventory->PopSection();
rAssert( mTrapController );
}
}
//=============================================================================
// SuperSprintManager::PlayIntroCam
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::PlayIntroCam()
{
AnimatedCam::SetMulticontroller( "minigamecam" );
AnimatedCam::SetCamera( "minigamecamShape" );
AnimatedCam::CheckPendingCameraSwitch();
AnimatedCam::SetCameraTransitionFlags( SuperCamCentral::CUT | SuperCamCentral::FORCE );
}
//=============================================================================
// SuperSprintManager::UpdatePositionIcons
//=============================================================================
// Description: Comment
//
// Parameters: ( unsigned int milliseconds )
//
// Return: void
//
//=============================================================================
void SuperSprintManager::UpdatePositionIcons( unsigned int milliseconds )
{
CalculatePositions();
//Sort positions.
int i, j;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
rmt::Vector carPos;
mVehicleSlots[ i ].mVehicle->GetPosition( &carPos );
rmt::Box3D bbox;
mVehicleSlots[ i ].mVehicle->GetBoundingBox( &bbox );
carPos.y = bbox.high.y;
for ( j = 0; j < SuperSprintData::NUM_PLAYERS; ++j )
{
mPositionIcon[ i ][ j ]->ShouldRender( false );
}
mPlayerID[ i ]->ShouldRender( false );
mNitroEffect[ i ]->ShouldRender( false );
if ( mNumHumanPlayers == 1 )
{
bool pressed = false;
unsigned int k;
for ( k = 0; k < SuperSprintData::NUM_PLAYERS; ++k )
{
if ( mTogglePosition[ k ] && mVehicleSlots[ k ].mIsHuman )
{
pressed = true;
break;
}
}
//If the toggle button is pressed, show all the positions
if ( pressed )
{
mPositionIcon[ i ][ mPositions[ i ] - 1 ]->Move( carPos );
mPositionIcon[ i ][ mPositions[ i ] - 1 ]->Update( milliseconds );
mPositionIcon[ i ][ mPositions[ i ] - 1 ]->ShouldRender( true );
}
else
{
//If the camera is in top-view render otherwise don't
if ( !mVehicleSlots[ i ].mIsHuman ||
GetSuperCamManager()->GetSCC( 0 )->GetActiveSuperCam()->GetType() == SuperCam::SUPER_SPRINT_CAM ||
GetSuperCamManager()->GetSCC( 0 )->GetActiveSuperCam()->GetType() == SuperCam::ANIMATED_CAM )
{
if ( mVehicleSlots[ i ].mVehicle->mNumTurbos > 0 )
{
mNitroEffect[ i ]->Move( carPos );
mNitroEffect[ i ]->Update( milliseconds );
mNitroEffect[ i ]->ShouldRender( true );
}
else
{
mPlayerID[ i ]->Move( carPos );
mPlayerID[ i ]->Update( milliseconds );
mPlayerID[ i ]->ShouldRender( true );
}
}
}
}
else
{
//If the toggle button is pressed, show all the positions
if ( mTogglePosition[ i ] && mVehicleSlots[ i ].mIsHuman )
{
mPositionIcon[ i ][ mPositions[ i ] - 1 ]->Move( carPos );
mPositionIcon[ i ][ mPositions[ i ] - 1 ]->Update( milliseconds );
mPositionIcon[ i ][ mPositions[ i ] - 1 ]->ShouldRender( true );
}
else
{
if ( mVehicleSlots[ i ].mVehicle->mNumTurbos > 0 )
{
mNitroEffect[ i ]->Move( carPos );
mNitroEffect[ i ]->Update( milliseconds );
mNitroEffect[ i ]->ShouldRender( true );
}
else
{
mPlayerID[ i ]->Move( carPos );
mPlayerID[ i ]->Update( milliseconds );
mPlayerID[ i ]->ShouldRender( true );
}
}
}
}
}
//=============================================================================
// SuperSprintManager::GetCheckpointWith
//=============================================================================
// Description: Comment
//
// Parameters: ( char data )
//
// Return: Locator
//
//=============================================================================
Locator* SuperSprintManager::GetCheckpointWith( char data )
{
Locator* returnLoc = NULL;
unsigned int i;
for ( i = 0; i < mNumCheckPointLocators; ++i )
{
if ( mCheckPointLocators[ i ]->GetData() == (unsigned int)data )
{
returnLoc = mCheckPointLocators[ i ];
break;
}
}
return returnLoc;
}
//=============================================================================
// SuperSprintManager::GetPathDataWith
//=============================================================================
// Description: Comment
//
// Parameters: ( Locator* loc )
//
// Return: int
//
//=============================================================================
int SuperSprintManager::GetPathDataWith( Locator* loc )
{
int i;
for ( i = 0; i < MAX_AI_WAYPOINTS; ++i )
{
if ( mPathData[ i ].loc == loc )
{
return i;
}
}
return -1;
}
//=============================================================================
// SuperSprintManager::PositionCharacters
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void SuperSprintManager::PositionCharacters()
{
int i;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
char carlocator[32];
sprintf( carlocator, "car%d", i + 1 );
CarStartLocator* loc = p3d::find<CarStartLocator>(carlocator);
rAssert( loc );
if ( loc )
{
Character* character = GetCharacterManager()->GetCharacterByName( tEntity::MakeUID( SuperSprintData::CHARACTER_NAMES[ mPlayers[ i ].mCharacterIndex ] ) );
rmt::Vector pos;
loc->GetLocation( &pos );
character->RelocateAndReset( pos, 0.0f, true );
}
}
}
//=============================================================================
// SuperSprintManager::SuperSprintManager
//=============================================================================
// Description: Constructor.
//
// Parameters: None.
//
// Return: N/A.
//
//=============================================================================
SuperSprintManager::SuperSprintManager() :
Mappable( Input::ACTIVE_SS_GAME ),
mCurrentState( IDLE ),
mDrawable( NULL ),
mCountDownTime( 3000 ),
mCurrentPosition( 1 ),
mStartTime( 0 ),
mNumActivePlayers( 0 ),
mNumHumanPlayers( 0 ),
mNumHumansFinished( 0 ),
mNumLaps( 1 ),
mGoLeft( false ),
mNumCheckPoints( 0 ),
mCheckPoints( CHECKPOINT_LIST ),
mFFlag( NULL ),
mWFlag( NULL ),
mFFlagTimeout( 0 ),
mWFlagTimeout( 0 ),
mTrapController( NULL ),
mTrapTriggered( false )
{
mGameType = GameplayManager::GT_SUPERSPRINT;
SetNumPlayers( SuperSprintData::NUM_PLAYERS );
int i, j;
for ( i = 0; i < SuperSprintData::NUM_PLAYERS; ++i )
{
for ( j = 0; j < SuperSprintData::NUM_PLAYERS; ++j )
{
mPositionIcon[ i ][ j ] = NULL;
}
mPlayerID[ i ] = NULL;
mTogglePosition[ i ] = false;
mNitroEffect[ i ] = NULL;
}
}
//=============================================================================
// SuperSprintManager::~SuperSprintManager
//=============================================================================
// Description: Destructor.
//
// Parameters: None.
//
// Return: N/A.
//
//=============================================================================
SuperSprintManager::~SuperSprintManager()
{
}