//============================================================================= // Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. // // File: mission.cpp // // Description: Implement Mission // // History: 15/04/2002 + Created -- NAME // //============================================================================= //======================================== // System Includes //======================================== // Foundation Tech #include #include //======================================== // Project Includes //======================================== #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //****************************************************************************** // // Global Data, Local Data, Local Classes // //****************************************************************************** const float MS_PER_SEC = 1000.0f; const float SEC_IN_MSEC = 0.001f; const int FINAL_DELAY = 3000; //How long to delay changing stages when this one is marked "final" const int COMPLETE_DELAY = 0; //How long to delay changing stages when this one shows COMPLETE const int MAX_NUM_STATEPROP_COLLECTIBLES = 10; //****************************************************************************** // // Public Member Functions // //****************************************************************************** //============================================================================== // Mission::Mission //============================================================================== // Description: Constructor. // // Parameters: None. // // Return: N/A. // //============================================================================== Mission::Mission() : mIsStreetRace1Or2( false ), mNumMissionStages( 0 ), mCurrentStage( -1 ), #ifdef RAD_GAMECUBE mHeap( GMA_GC_VMM ), #else mHeap( GMA_LEVEL_MISSION ), #endif mbComplete( false ), mbIsLastStage( false ), mMissionTimer( 0 ), mState( STATE_WAITING ), mLastStageState( MissionStage::STAGE_IDLE ), //mNumVehicles( 0 ), mVehicleRestart( NULL ), mPlayerRestart( NULL ), mDynaloadLoc( NULL ), mStreetRacePropsLoad(NULL), mStreetRacePropsUnload(NULL), mResetToStage( 0 ), mSundayDrive( false ), mBonusMisison( false ), mNumBonusObjectives( 0 ), mIsForcedCar( false ), mbAutoRepairCar(false), mbSwappedCars(false), mbTriggerPattyAndSelmaScreen(false), mFinalDelay( -1 ), mCompleteDelay( -1 ), mChangingStages( false ), mNoTimeUpdate(false ), mJumpBackStage( false ), mJumpBackBy( 1 ), mNumStatePropCollectibles( 0 ), mStatePropCollectibles( NULL ), mDoorStars( NULL ), mInitPedGroupId( 0 ), mShowHUD( true ), mNumValidFailureHints( -1 ) { strcpy( mcName, "" ); mbCarryOverOutOfCarCondition = false; unsigned int i; for ( i = 0; i < MAX_BONUS_OBJECTIVES; ++i ) { mBonusObjectives[ i ] = NULL; } mElapsedTimems = 0; for (int j =0; jRelease(); mVehicles[ i ] = NULL; } */ if ( mDynaloadLoc ) { mDynaloadLoc->Release(); } unsigned int k; for ( k = 0; k < mNumBonusObjectives; ++k ) { delete mBonusObjectives[ k ]; mBonusObjectives[ k ] = NULL; } mNumBonusObjectives = 0; if ( mStreetRacePropsLoad ) { mStreetRacePropsLoad->ReleaseVerified(); } if ( mStreetRacePropsUnload ) { mStreetRacePropsUnload->ReleaseVerified(); } // Release all statepropcollectibles and remove them from the world for ( int i = 0 ; i < mNumStatePropCollectibles ; i++ ) { StatePropCollectible* collectible = mStatePropCollectibles[i]; if ( collectible ) { collectible->RemoveFromDSG(); collectible->Release(); } } delete [] mStatePropCollectibles; mStatePropCollectibles = NULL; mNumStatePropCollectibles = 0; if ( mDoorStars ) { delete mDoorStars; } } //============================================================================= // Mission::AddPlayerVehicle //============================================================================= // Description: Comment // // Parameters: ( Vehicle* vehicle ) // // Return: void // //============================================================================= /* void Mission::AddVehicle( Vehicle* vehicle ) { rAssert( vehicle != NULL ); int i; for ( i = 0; i < mNumVehicles; ++i ) { if ( mVehicles[ i ] == vehicle ) { //We've already got this one! return; } } rAssert( mNumVehicles < MAX_VEHICLES ); mVehicles[ mNumVehicles ] = vehicle; vehicle->AddRef(); mNumVehicles++; } */ //============================================================================= // Mission::GetVehicleByName //============================================================================= // Description: Comment // // Parameters: ( char* name ) // // Return: Vehicle // //============================================================================= /* Vehicle* Mission::GetVehicleByName( char* name ) { Vehicle* vehicle = NULL; for( int i = 0; i < mNumVehicles; i++ ) { if( strcmp( mVehicles[ i ]->GetName(), name ) == 0 ) { vehicle = mVehicles[ i ]; break; } } // TODOGREG - is this what we want to do here? // if mission doesn't have one of these, do we really want to return one from vehicle central?????????? if ( !vehicle ) { vehicle = GetVehicleCentral()->GetVehicleByName( name ); } return vehicle; } */ //============================================================================= // Mission::Initialize //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void Mission::Initialize( GameMemoryAllocator heap) { mHeap = heap; unsigned int i; for ( i = 0; i < mNumBonusObjectives; ++i ) { mBonusObjectives[ i ]->Initialize(); } mbComplete = false; mbIsLastStage = false; mJumpBackStage = false; mJumpBackBy = 1; SetToStage( -1 ); mState = STATE_WAITING; //if missions are forced cars turn off phone booths if(mIsForcedCar == true) { GetGameplayManager()->DisablePhoneBooths(); } if(mbAutoRepairCar == true) { //GetGameplayManager()->GetCurrentVehicle()->ResetDamageState(); if (GetGameplayManager()->GetCurrentVehicle() != NULL) { if (GetGameplayManager()->GetCurrentVehicle()->IsVehicleDestroyed() == true) { GetEventManager()->TriggerEvent(EVENT_REPAIR_CAR); } } } else { if (IsSundayDrive() == true ||IsWagerMission()== true ) { } else { mbAutoRepairCar = true; } } //Purchase rewards only in sunday drive. ActionButton::PurchaseReward::SetEnabled( mSundayDrive ); GetEventManager()->AddListener(this, EVENT_ENTER_INTERIOR_TRANSITION_START); GetEventManager()->AddListener(this, EVENT_ENTER_INTERIOR_END); GetEventManager()->AddListener(this, EVENT_EXIT_INTERIOR_START); GetEventManager()->AddListener(this, EVENT_EXIT_INTERIOR_END); //chuck: Adding this to handle the patty and selma done talking event. since this class will now trigger screen. GetEventManager()->AddListener(this, EVENT_GUI_TRIGGER_PATTY_AND_SELMA_SCREEN); //Try to setup the doorstars if this is sunday drive rAssert( mDoorStars == NULL ); if ( mSundayDrive ) { int level = GetGameplayManager()->GetCurrentLevelIndex() + 1; if ( level == 5 ) { level = 2; } else if ( level == 6 ) { level = 3; } else if ( level == 7 ) { level = 4; } char name[ 64 ]; sprintf( name, "l%d_doorstars", level ); mDoorStars = new AnimatedIcon(); mDoorStars->Init( name, rmt::Vector( 0.0f, 0.0f, 0.0f ), true, false ); } if( strncmp( mcName, "sr1", 3 ) == 0 || strncmp( mcName, "sr2", 3 ) == 0 ) { mIsStreetRace1Or2 = true; } else { mIsStreetRace1Or2 = false; } } //============================================================================= // Mission::Finalize //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void Mission::Finalize() { SetToStage( -1 ); //chuck adding draw synch I hope to fix the level 5 m1 crash when user aborts missions. p3d::pddi->DrawSync(); //Stop harrass cars from spawning GameplayManager* gameplayManager = GetGameplayManager(); if ( gameplayManager != NULL ) { ChaseManager* chaseManager = gameplayManager->GetChaseManager(0); if ( chaseManager != NULL ) { chaseManager->ClearAllObjects(); chaseManager->SetMaxObjects(0); } gameplayManager->EmptyMissionVehicleSlots(); } int i; for ( i = 0; i < mNumMissionStages; i++ ) { delete mMissionStages[ i ]; mMissionStages[ i ] = NULL; } // Remove all collectibles from the vehicles GetVehicleCentral()->DetachAllCollectibles(); // Release all statepropcollectibles and remove them from the world for ( int i = 0 ; i < mNumStatePropCollectibles ; i++ ) { StatePropCollectible* collectible = mStatePropCollectibles[i]; if ( collectible ) { collectible->RemoveFromDSG(); collectible->Release(); p3d::inventory->Remove( collectible ); collectible = NULL; } } mNumStatePropCollectibles = 0; /* for ( j = 0; j < mNumVehicles; ++j ) { //bool succeeded = GetVehicleCentral()->RemoveVehicleFromActiveList( mVehicles[ j ] ); // rAssert( succeeded ); mVehicles[ j ]->Release(); mVehicles[ j ] = NULL; } mNumVehicles = 0; */ mNumMissionStages = 0; mbComplete = false; mbIsLastStage = false; unsigned int k; for ( k = 0; k < mNumBonusObjectives; ++k ) { mBonusObjectives[ k ]->Finalize(); delete mBonusObjectives[ k ]; } mNumBonusObjectives = 0; //This is a safety catch GetEventManager()->RemoveAll( this ); // // TODO: Dump all the mission vehicles (player & AI) // //Dump the car if this is a forced car mission if ( mIsForcedCar ) { //re-enable phone booths GetGameplayManager()->EnablePhoneBooths(); Character* player = GetAvatarManager()->GetAvatarForPlayer( 0 )->GetCharacter(); Vehicle* forcedCar = GetGameplayManager()->GetVehicleInSlot(GameplayManager::eOtherCar); Vehicle* currCar = GetAvatarManager()->GetAvatarForPlayer(0)->GetVehicle(); if(currCar && currCar->mVehicleID == VehicleEnum::HUSKA) { currCar = GetVehicleCentral()->mHuskPool.FindOriginalVehicleGivenHusk(currCar); } if ( forcedCar != NULL && currCar == forcedCar && (mbSwappedCars == false) ) { //locking forced car since we are done with it. forcedCar->TransitToAI(); //The character is in the forced car GetAvatarManager()->PutCharacterOnGround( player, forcedCar ); //Move the character somewhere reasonable rmt::Vector pos; player->GetPosition( &pos ); float rotation = player->GetFacingDir(); const Road* road; RoadSegment* roadSeg; int segIndex; float in; float lateral; if ( RoadManager::GetInstance()->FindRoad( pos, &road, &roadSeg, segIndex, in, lateral, true ) ) { //We're on a road set our position to the side of the road. roadSeg->GetPosition( 0.5f, 0.5f, &pos ); } else { //Am I in an intersection? Intersection* intersection = RoadManager::GetInstance()->FindIntersection( pos ); if ( intersection != NULL ) { //Take the first road going out of the intersection and //put the player on the corner. const Road* road = intersection->GetRoadOut( 0 ); if(!road) { road = intersection->GetRoadIn( 0 ); } if(road) { roadSeg = road->GetRoadSegment( 0 ); roadSeg->GetPosition( 0.5f, 0.5f, &pos ); } } else { // we're not on a road or on an intersection. get the "closeset" road float distance; RoadSegment* segment; GetIntersectManager()->FindClosestRoad( pos, 50.0f, //yay the magic numbers i just made this one up segment, distance ); rAssert( segment != NULL ); segment->GetPosition( &pos ); } } rmt::Vector CharacterPositionVsCar; rmt::Vector CharacterPositionVsCharacterStartPosition; player->GetPosition(CharacterPositionVsCar); player->GetPosition(CharacterPositionVsCharacterStartPosition); //subtract the character position from the forced car start locator CharacterPositionVsCar.Sub(GetGameplayManager()->mPlayerAndCarInfo.mForceLocation); //subtract the character's position from the original start position. CharacterPositionVsCharacterStartPosition.Sub(GetGameplayManager()->mPlayerAndCarInfo.mPlayerPosition); float vaule1,vaule2; //distance between character and the forced cars respawn locator vaule1 = rmt::Sqrt(CharacterPositionVsCar.MagnitudeSqr()); //distance between character and the spot where they talked to NPC to start mission. vaule2 = rmt::Sqrt(CharacterPositionVsCharacterStartPosition.MagnitudeSqr()); //if the character is less than 2 meter from the forced carstart location then place them at the spot that //they were in when starting the talk to objective that started this mission if (vaule1 < 2.0f && vaule2 < 20.0f) { pos = GetGameplayManager()->mPlayerAndCarInfo.mPlayerPosition; } player->RelocateAndReset( pos, rotation, true ); //GetGameplayManager()->PutPlayerInCar( true ); //Hackish way to put the player in the car in the next / prev stage / mission //GetGameplayManager()->mShouldLoadDefaultVehicle = true; GetEventManager()->TriggerEvent( EVENT_CHARACTER_POS_RESET ); } GetGameplayManager()->ClearVehicleSlot(GameplayManager::eOtherCar); } //unload streetrace props if there are any for this mission InitStreetRacePropUnload(); mbSwappedCars = false; if ( mDoorStars ) { delete mDoorStars; mDoorStars = NULL; } } //============================================================================= // Mission::SetToStage //============================================================================= // Description: Comment // // Parameters: (unsigned int index) // // Return: void // //============================================================================= void Mission::SetToStage( int index, bool resetting ) { if( index == mCurrentStage ) { return; } MissionStage* stage = GetCurrentStage(); if( stage != NULL ) { stage->Finalize(); } stage = GetStage( index ); //Test if this is a "locked" stage and see if you can do it. if ( stage && stage->GetMissionLocked() ) { if ( UnlockStage( stage ) ) { //Now we always play the dialogue. // //Go to the next stage // rAssert( index < MAX_STAGES ); // ++index; } } mCurrentStage = index; stage = GetCurrentStage(); if( stage != NULL ) { unsigned int time; MissionStage::StageTimeType type; stage->GetStageTime( type, time ); switch( type ) { case MissionStage::STAGETIME_NOT_TIMED: { mMissionTimer = -1; break; } case MissionStage::STAGETIME_ADD: { mMissionTimer += static_cast( time * MS_PER_SEC ); break; } case MissionStage::STAGETIME_SET: { mMissionTimer = static_cast( time * MS_PER_SEC ); break; } default: { rAssert( false ); break; } } // new // greg // jan 10, 2003 // loop through up to and including this stage and // re-initialize the vehicle stuff if(resetting) { ResetPlayer(); int i; for(i = 0; i < index; i++) { GetStage(i)->VehicleInfoInitialize(); GetStage(i)->VehicleFinalize(); } } stage->Initialize(); // Is this the start of the mission? // if( index == 0 ) { mState = STATE_INPROGRESS; } } } //============================================================================= // Mission::NextStage //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void Mission::NextStage() { SetToStage( mCurrentStage + 1 ); } //============================================================================= // Mission::PrevStage //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void Mission::PrevStage() { rAssert( mCurrentStage != -1 ); if ( mCurrentStage == 0 ) { //We're on the first stage. GetCurrentStage()->Finalize(); ResetStage(); } else { SetToStage( mCurrentStage - 1 ); } } //============================================================================= // Mission::ResetStage //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void Mission::ResetStage() { GetCurrentStage()->Reset(); } //============================================================================= // Mission::HandleEvent //============================================================================= // Description: Comment // // Parameters: ( EventEnum id, void* pEventData ) // // Return: void // //============================================================================= void Mission::HandleEvent( EventEnum id, void* pEventData ) { if((id == EVENT_ENTER_INTERIOR_TRANSITION_START) || (id == EVENT_EXIT_INTERIOR_START)) { mNoTimeUpdate = true; } else if ((id == EVENT_ENTER_INTERIOR_END) || (id == EVENT_EXIT_INTERIOR_END)) { mNoTimeUpdate = false; } else if ( id == EVENT_GUI_MISSION_START ) { //Dirty dirty GetCurrentStage()->Start(); GetGameFlow()->GetContext( CONTEXT_GAMEPLAY )->Resume(); if ( GetCurrentStage()->StartBonusObjective() ) { StartBonusObjectives(); } } else if ( id == EVENT_GUI_TRIGGER_PATTY_AND_SELMA_SCREEN) { mbTriggerPattyAndSelmaScreen = true; } else { MissionStage* pStage = GetCurrentStage(); if( pStage != NULL ) { pStage->HandleEvent( id, pEventData ); } } } //============================================================================= // Mission::Update //============================================================================= // Description: Comment // // Parameters: ( unsigned int elapsedTime ) // // Return: void // //============================================================================= void Mission::Update( unsigned int elapsedTime ) { if ( mChangingStages ) { DoStageChange(); } MissionStage* stage = GetCurrentStage(); // MS9: take this out! There should always be a stage if( stage == NULL ) return; rAssert( stage != NULL ); BEGIN_PROFILE( "Mission Update" ); MissionStage::MissionStageState state = stage->GetProgress(); ContextEnum currentContext = GetGameFlow()->GetCurrentContext(); if( currentContext == CONTEXT_PAUSE ) { state = MissionStage::STAGE_INPROGRESS; } switch( state ) { case MissionStage::STAGE_INPROGRESS: { if (GetCurrentStage() != NULL) { if( mMissionTimer >=1 && !mNoTimeUpdate && GetCurrentStage()->mbDisablePlayerControlForCountDown != true) { if(GetCurrentStage()->QueryUseElapsedTime() ==true) //make timer count up if stage is using elasped time. { mMissionTimer += elapsedTime; } else { mMissionTimer -= elapsedTime; } mElapsedTimems += elapsedTime; //Chuck:only trigger red flashing timer if we aren't using elasped time. if( ( mMissionTimer <= 10000 ) && ( mMissionTimer + elapsedTime > 10000 ) && ( stage->GetFinalStage() && !(GetCurrentStage()->QueryUseElapsedTime()) ) ) { GetEventManager()->TriggerEvent( EVENT_TIME_RUNNING_OUT ); } } GetCurrentStage()->Update( elapsedTime ); unsigned int i; for ( i = 0; i < mNumBonusObjectives; ++i ) { mBonusObjectives[ i ]->Update( elapsedTime ); } break; } } case MissionStage::STAGE_COMPLETE: { if( state == mLastStageState && mFinalDelay == -1 && mCompleteDelay == -1 ) { break; } mbComplete = mCurrentStage == mNumMissionStages-1; if ( mFinalDelay == -1 && stage->GetFinalStage() && mbComplete ) { //Setup the delay and skip outta here. MissionStage* thisStage = this->GetCurrentStage(); MissionObjective* objective = thisStage->GetObjective(); if( objective->IsPattyAndSelmaDialog() ) { mFinalDelay = 0; } else { mFinalDelay = FINAL_DELAY; // // Tell the GUI system that the mission succeeded // if(!IsSundayDrive()) { GetGuiSystem()->HandleMessage( GUI_MSG_INGAME_MISSION_COMPLETE ); } } //TODO: Send off the bonus mission info too. GetEventManager()->TriggerEvent( EVENT_MISSION_SUCCESS ); if( stage->GetObjective()->GetObjectiveType() == MissionObjective::OBJ_LOSETAIL ) { GetEventManager()->TriggerEvent( EVENT_TAIL_LOST_DIALOG ); } else { GetEventManager()->TriggerEvent( EVENT_MISSION_SUCCESS_DIALOG ); } break; } else if ( stage->GetFinalStage() && mbComplete ) { if ( static_cast(elapsedTime) >= mFinalDelay ) { //All done, carry on. mFinalDelay = -1; } else { //Decrement the time and get outta here. WE pause to show the mission complete stuff. mFinalDelay -= elapsedTime; break; } } // trigger stage complete event // unsigned int showStageComplete = stage->IsShowStageComplete() ? 1 : 0; if ( showStageComplete && mCompleteDelay == -1 ) { //We need to delay the mission stage change to prevent weirdness. mCompleteDelay = COMPLETE_DELAY; GetEventManager()->TriggerEvent( EVENT_STAGE_COMPLETE, reinterpret_cast( showStageComplete ) ); if( stage->GetObjective()->GetObjectiveType() == MissionObjective::OBJ_LOSETAIL ) { GetEventManager()->TriggerEvent( EVENT_TAIL_LOST_DIALOG ); } break; } else if ( showStageComplete ) { if ( mCompleteDelay > static_cast(elapsedTime) ) { mCompleteDelay -= elapsedTime; break; } else { //We're good. mCompleteDelay = -1; } } if ( stage->GetFinalStage() || mbComplete ) { mState = STATE_SUCCESS; if ( stage->GetFinalStage() ) { //To Do::MESA Insert Call to CharacterSheetManager to update //character sheet with complete and bonus object stuff if (mBonusObjectives[0] != NULL) { int seconds = (mElapsedTimems /1000); GetCharacterSheetManager()->SetMissionComplete(GetGameplayManager()->GetCurrentLevelIndex(),mcName,mBonusObjectives[0]->GetSuccessful(),seconds ); } else { int seconds = (mElapsedTimems/1000); GetCharacterSheetManager()->SetMissionComplete(GetGameplayManager()->GetCurrentLevelIndex(),mcName,false,seconds); } if ( mbTriggerPattyAndSelmaScreen == true) { GetGuiSystem()->HandleMessage( GUI_MSG_GOTO_SCREEN, CGuiWindow::GUI_SCREEN_ID_MISSION_SUCCESS, CLEAR_WINDOW_HISTORY ); GetEventManager()->TriggerEvent( EVENT_GUI_ENTERING_MISSION_SUCCESS_SCREEN ); GetGameFlow()->SetContext( CONTEXT_PAUSE ); InitStreetRacePropUnload(); mbTriggerPattyAndSelmaScreen = false; } } //This is silly.... Dirty too. At least it's not the GUI doing it. //Really this just updates the state of all the missions. GAH. GetGameplayManager()->ContinueGameplay(); if ( mCurrentStage != -1 ) { //GetCurrentStage()->Reset(); GetCurrentStage()->Start(); if ( GetCurrentStage()->StartBonusObjective() ) { StartBonusObjectives(); } } } else { SetupStageChange(); } break; } case MissionStage::STAGE_FAILED: { unsigned int i; unsigned int numConditions; bool isChaseCondition = false; if( state == mLastStageState ) { break; } mState = STATE_FAILED; //if we fail a forced car relock the forced car if ( IsForcedCar() == true) { if (GetGameplayManager()-> mVehicleSlots[GameplayManager::eOtherCar].mp_vehicle != NULL) { GetGameplayManager()-> mVehicleSlots[GameplayManager::eOtherCar].mp_vehicle->ActivateTriggers(false); } } // Tell the GUI system that mission failed // GetGuiSystem()->HandleMessage( GUI_MSG_INGAME_MISSION_FAILED ); // get the failure condition // MissionCondition* failedCondition = stage->GetFailureCondition(); rTuneAssertMsg( failedCondition != NULL, "WTF?? How could there be no failure condition?" ); // // Determine whether any of the conditions involve chases // numConditions = stage->GetNumConditions(); for( i = 0; i < numConditions; i++ ) { if( stage->GetCondition( i )->IsChaseCondition() ) { isChaseCondition = true; break; } } GetEventManager()->TriggerEvent( EVENT_MISSION_FAILURE, reinterpret_cast( failedCondition ) ); mbComplete = true; // // We need to re-enable world rendering if we failed because of // entering an interior // bool entering = GetInteriorManager()->IsEntering(); if( entering ) { GetRenderManager()->mpLayer( RenderEnums::LevelSlot )->Thaw(); } if(IsBonusMission()) { GetCharacterManager()->ResetBonusCharacters(); } break; } case MissionStage::STAGE_BACKUP: { //This is a bad thing. rAssert( false ); /* PrevStage(); GetCurrentStage()->Start(); */ break; } default: { // whatever break; } } mLastStageState = state; if ( mDoorStars ) { mDoorStars->Update( elapsedTime ); } DoUpdate( elapsedTime ); END_PROFILE( "Mission Update" ); } //============================================================================= // Mission::IsComplete //============================================================================= // Description: Comment // // Parameters: () // // Return: bool // //============================================================================= bool Mission::IsComplete() { return( mbComplete ); } //============================================================================= // Mission::SetRestartDyanload //============================================================================= // Description: Comment // // Parameters: ( const char* loadString ) // // Return: void // //============================================================================= void Mission::SetRestartDynaload( const char* loadString, const char* interior) { HeapMgr()->PushHeap (GMA_LEVEL_MISSION); MEMTRACK_PUSH_GROUP( "Mission - Dynaload" ); if ( mDynaloadLoc ) { mDynaloadLoc->Release(); } if( strcmp( loadString, "" ) != 0 ) { mDynaloadLoc = new ZoneEventLocator; mDynaloadLoc->AddRef(); mDynaloadLoc->SetZoneSize( strlen(loadString) + 1 ); mDynaloadLoc->SetZone( loadString ); mDynaloadLoc->SetPlayerEntered(); if(interior) { mDynaloadLoc->SetName(interior); } } else { mDynaloadLoc = NULL; } MEMTRACK_POP_GROUP( "Mission - Dynaload" ); HeapMgr()->PopHeap (GMA_LEVEL_MISSION); } //============================================================================= // Mission::AddBonusObjective //============================================================================= // Description: Comment // // Parameters: ( BonusObjective* bo ) // // Return: void // //============================================================================= void Mission::AddBonusObjective( BonusObjective* bo ) { rAssert( mNumBonusObjectives < MAX_BONUS_OBJECTIVES ); mBonusObjectives[ mNumBonusObjectives ] = bo; ++mNumBonusObjectives; } //============================================================================= // Mission::StartBonusObjectives //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void Mission::StartBonusObjectives() { unsigned int i; for ( i = 0; i < mNumBonusObjectives; ++i ) { mBonusObjectives[ i ]->Start(); } } //============================================================================= // Mission::SetForcedCar //============================================================================= // Description: Comment // // Parameters: ( bool isForced ) // // Return: void // //============================================================================= void Mission::SetForcedCar( bool isForced ) { mIsForcedCar = isForced; } //============================================================================= // Mission::SetMissionTime //============================================================================= // Description: Comment // // Parameters: ( int timeMilliseconds ) // // Return: void // //============================================================================= void Mission::SetMissionTime( int timeMilliseconds ) { mMissionTimer = timeMilliseconds; } //============================================================================= // Mission::CreateStatePropCollectible //============================================================================= // Description: Creates a new statepropcollectible and places it at the given locator // // Parameters: name of the CStateProp data chunk in the inventory, name of the locator // // Return: void // //============================================================================= void Mission::CreateStatePropCollectible( const char* statepropname, const char* locatorname, int collisionattributes ) { // No space in the array, bail if ( mNumStatePropCollectibles >= MAX_NUM_STATEPROP_COLLECTIBLES ) return; HeapMgr()->PushHeap (GMA_LEVEL_MISSION); Locator* locator = p3d::find< Locator >( locatorname ); if ( locator ) { CStatePropData* propdata = p3d::find< CStatePropData >(statepropname); if ( propdata ) { // Get the locator's position rmt::Vector locatorposition; locator->GetPosition( &locatorposition ); // Fill out a translation matrix rmt::Matrix transform; transform.Identity(); transform.FillTranslate( locatorposition ); StatePropCollectible* collectible = new StatePropCollectible(); CollisionAttributes* collAttr = GetATCManager()->CreateCollisionAttributes( PROP_MOVEABLE, collisionattributes, 2.242f ); collAttr->AddRef(); collectible->LoadSetup( propdata, 0, transform, collAttr, false, NULL ); collAttr->Release(); collectible->SetName( statepropname ); p3d::inventory->Store( collectible ); // Add it to the internal list of prop collectibles // Allocate a new list if necessary if ( mNumStatePropCollectibles == 0 ) { mStatePropCollectibles = new StatePropCollectible*[ MAX_NUM_STATEPROP_COLLECTIBLES ]; } mStatePropCollectibles[ mNumStatePropCollectibles ] = collectible; collectible->AddRef(); mNumStatePropCollectibles++; } else { rReleaseAssertMsg("can't find stateprop %s\n",statepropname); } } else { rReleaseAssertMsg("can't find locator %s\n",locatorname); } HeapMgr()->PopHeap (GMA_LEVEL_MISSION); } //============================================================================= // Mission::AttachStatePropCollectible //============================================================================= // Description: Creates and attaches a new statepropcollectible on a vehicle // // Parameters: name of the CStateProp data chunk in the inventory, name of the vehicle // // Return: void // //============================================================================= void Mission::AttachStatePropCollectible( const char* statepropname, const char* vehicleName, int collisionattributes ) { // No space in the array, bail if ( mNumStatePropCollectibles >= MAX_NUM_STATEPROP_COLLECTIBLES ) return; CStatePropData* statePropData = p3d::find< CStatePropData > (statepropname); if ( statePropData ) { Vehicle* vehicle = GetVehicleCentral()->GetVehicleByName( vehicleName ); StatePropCollectible* stateprop = new StatePropCollectible(); rmt::Matrix transform; transform.Identity(); // Create some collision attributes. Unfort I may just have to leave these hardcoded. // Settings seem to make very little difference anyway. CollisionAttributes* collAttr = GetATCManager()->CreateCollisionAttributes( PROP_MOVEABLE, collisionattributes, 2.242f ); collAttr->AddRef(); stateprop->LoadSetup( statePropData, 0, transform, collAttr, false ); collAttr->Release(); // Add it to scenegraph stateprop->AddToDSG(); vehicle->AttachCollectible( stateprop ); // Add it to the internal list of prop collectibles // Allocate a new list if necessary if ( mNumStatePropCollectibles == 0 ) { mStatePropCollectibles = new StatePropCollectible*[ MAX_NUM_STATEPROP_COLLECTIBLES ]; } stateprop->SetName( statepropname ); p3d::inventory->Store( stateprop ); mStatePropCollectibles[ mNumStatePropCollectibles ] = stateprop; stateprop->AddRef(); mNumStatePropCollectibles++; } } //============================================================================= // Mission::Reset //============================================================================= // Description: Comment // // Parameters: ( bool JumpStage ) // // Return: void // //============================================================================= void Mission::Reset( bool jumpStage ) { mbComplete = false; mState = STATE_INPROGRESS; mbIsLastStage = false; mElapsedTimems = 0; mbCarryOverOutOfCarCondition = false; //Reset ChaseManager Spawn Rate incase of Retries GameplayManager* gameplayManager = GetGameplayManager(); if ( gameplayManager != NULL ) { ChaseManager* chaseManager = gameplayManager->GetChaseManager(0); if ( chaseManager != NULL ) { chaseManager->SetMaxObjects(0); } gameplayManager->MakeSureHusksAreReverted(); // do this rather than let GameplayManager catch event below, because that's too late I think } SetToStage( -1 ); if ( jumpStage ) { SetToStage( mResetToStage, jumpStage ); // repair car on mission reset or retry GetEventManager()->TriggerEvent(EVENT_REPAIR_CAR); } else { SetToStage( 0 ); } //Reset the bonus objectives. unsigned int i; for ( i = 0; i < mNumBonusObjectives; ++i ) { mBonusObjectives[ i ]->Reset(); } GetEventManager()->TriggerEvent( EVENT_MISSION_RESET, (void*)( jumpStage ) ); GetCharacterSheetManager()->IncrementMissionAttempt(GetGameplayManager()->GetCurrentLevelIndex(),this->mcName); InitStreetRacePropLoad(); //make sure our current car doesn't have locked doors //since forced cars have locked doors. if(IsForcedCar()) { if(GetGameplayManager()->mVehicleSlots[GameplayManager::eOtherCar].mp_vehicle != NULL) { GetGameplayManager()->mVehicleSlots[GameplayManager::eOtherCar].mp_vehicle->ActivateTriggers(true); } } } //============================================================================= // Mission::ResetPlayer //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void Mission::ResetPlayer() { //This is where we get the reset data and apply it. Sounds good eh? Character* player = GetCharacterManager()->GetCharacter( 0 ); //This is the player... Vehicle* car = GetGameplayManager()->GetCurrentVehicle(); //Current car if( mVehicleRestart != NULL ) { GetGameplayManager()->PlaceVehicleAtLocator( car, mVehicleRestart ); } //if ( mPlayerRestart == NULL || IsForcedCar() || IsRaceMission() ) if ( mPlayerRestart == NULL || IsRaceMission() ) { rmt::Vector pos; mVehicleRestart->GetLocation( &pos ); player->RelocateAndReset( pos, 0, true ); if (GetGameplayManager()->GetCurrentVehicle()->mVehicleDestroyed != true) { GetAvatarManager()->PutCharacterInCar( player, car ); } } else { //TODO: Make a put player on ground type thingie. I shouldn't have to know about this. GetGameplayManager()->PlaceCharacterAtLocator( player, mPlayerRestart ); GetAvatarManager()->PutCharacterOnGround( player, car ); } GetEventManager()->TriggerEvent( EVENT_CHARACTER_POS_RESET ); //Let's cut the camera. GetSuperCamManager()->GetSCC( 0 )->NoTransition(); GetSuperCamManager()->GetSCC( 0 )->DoCameraCut(); } //============================================================================= // Mission::InitDynaLoad //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void Mission::InitDynaLoad() { rTuneAssertMsg( mDynaloadLoc, "DYNALOAD information is required in all missions!" ); GetEventManager()->TriggerEvent( EVENT_FIRST_DYNAMIC_ZONE_START, mDynaloadLoc ); // set the pedgroup sheeyatsu... if( 0 <= mInitPedGroupId && mInitPedGroupId < PedestrianManager::MAX_MODEL_GROUPS ) { PedestrianManager::GetInstance()->SwitchModelGroup( mInitPedGroupId ); PedestrianManager::SetDefaultModelGroup( mInitPedGroupId ); } } void Mission::SetInitPedGroup( int initGroupId ) { rTuneAssert( 0 <= mInitPedGroupId && mInitPedGroupId < PedestrianManager::MAX_MODEL_GROUPS ); mInitPedGroupId = initGroupId; } //============================================================================= // Mission::DialogueCharactersTeleported //============================================================================= // Description: Comment // // Parameters: () // // Return: bool // //============================================================================= bool Mission::DialogueCharactersTeleported() { if ( !GetCurrentStage() || !(GetCurrentStage()->GetObjective()) ) { //DAMN THOSE COSMIC RAYS! return false; //No cut. } if ( GetCurrentStage()->GetObjective()->GetObjectiveType() == MissionObjective::OBJ_DIALOGUE ) { return static_cast(GetCurrentStage()->GetObjective())->CharactersReset(); } return false; } //============================================================================= // Mission::GetCurrentStage //============================================================================= // Description: Comment // // Parameters: () // // Return: inline // //============================================================================= MissionStage* Mission::GetCurrentStage() { if(( mCurrentStage >= 0 ) && (mCurrentStage < (int)mNumMissionStages )) { return( mMissionStages[ mCurrentStage ] ); } else { return( NULL ); } } //============================================================================= // Mission::GetMissionTimeLeftInSeconds //============================================================================= // Description: Comment // // Parameters: () // // Return: unsigned // //============================================================================= int Mission::GetMissionTimeLeftInSeconds() { return( static_cast( mMissionTimer * SEC_IN_MSEC )); } //============================================================================= // Mission::GetMissionTimeLeftInMilliSeconds //============================================================================= // Description: Comment // // Parameters: () // // Return: unsigned // //============================================================================= int Mission::GetMissionTimeLeftInMilliSeconds() { return( mMissionTimer ); } //****************************************************************************** // // Private Member Functions // //****************************************************************************** //============================================================================= // Mission::DoUpdate //============================================================================= // Description: Comment // // Parameters: ( int elapsedTime ) // // Return: void // //============================================================================= void Mission::DoUpdate( int elapsedTime ) { } //============================================================================= // Mission::SetBonusMission //============================================================================= // Description: sets a flag if this is a bonus mission // // Parameters: NONE // // Return: void // //============================================================================= void Mission::SetBonusMission() { mBonusMisison = true; } //============================================================================= // Mission::IsBonusMission //============================================================================= // Description: Comment // // Parameters: ( int elapsedTime ) // // Return: void // //============================================================================= bool Mission::IsBonusMission() { if( IsRaceMission() ) { return false; } return mBonusMisison; } //============================================================================= // Mission::IsBonusMission //============================================================================= // Description: determines if this mission is a special road race // // Parameters: ( int elapsedTime ) // // Return: void // //============================================================================= bool Mission::IsRaceMission() { if( ( mcName[ 0 ] == 's' ) && ( mcName[ 1 ] == 'r' ) ) { return true; } return false; } //============================================================================= // Mission::IsWagerMission //============================================================================= // Description: determines if this mission is a wager mission or not // // Parameters: NONE // // Return: bool - is it or isn't it? // //============================================================================= bool Mission::IsWagerMission() { if( ( mcName[ 0 ] == 'g' ) && ( mcName[ 1 ] == 'r' ) ) { return true; } return false; } //============================================================================= // Mission::UnlockStage //============================================================================= // Description: Comment // // Parameters: ( MissionStage* stage ) // // Return: bool // //============================================================================= bool Mission::UnlockStage( MissionStage* stage ) { unsigned int i; for ( i = 0; i < MAX_LOCK_REQUIREMENTS; ++i ) { const MissionStage::LockRequirement& requirement = stage->GetLockRequirement( i ); if ( requirement.mType == MissionStage::LockRequirement::NONE ) { continue; } //Test this against what the character has. if ( requirement.mType == MissionStage::LockRequirement::CAR ) { if ( strcmp( GetGameplayManager()->GetCurrentVehicle()->mName, requirement.mName ) != 0 ) { //Failed the car test. return false; } } else if ( requirement.mType == MissionStage::LockRequirement::SKIN /*Should test for skins.*/ ) { Character* character = GetAvatarManager()->GetAvatarForPlayer(0)->GetCharacter(); if ( strcmp( GetCharacterManager()->GetModelName( character ), requirement.mName ) != 0 ) { //failed the skin test return false; } } } return true; } //============================================================================= // Mission::LoadStreetRaceProps //============================================================================= // Description: Load the p3d file that contains the instanced streetrace props // // Parameters: ( const char* loadString ) // // Return: void // //============================================================================= void Mission::LoadStreetRaceProps( const char* loadString ) { HeapMgr()->PushHeap (GMA_LEVEL_MISSION); MEMTRACK_PUSH_GROUP( "Mission - StreetRaceProps" ); //clear any junk if ( mStreetRacePropsLoad != NULL) { mStreetRacePropsLoad->ReleaseVerified(); } if( strcmp( loadString, "" ) != 0 ) { mStreetRacePropsLoad = new ZoneEventLocator; mStreetRacePropsLoad->AddRef(); mStreetRacePropsLoad->SetZoneSize( strlen(loadString) + 1 ); mStreetRacePropsLoad->SetZone( loadString ); mStreetRacePropsLoad->SetPlayerEntered(); } else { mStreetRacePropsLoad = NULL; } MEMTRACK_POP_GROUP( "Mission - StreetRaceProps" ); HeapMgr()->PopHeap (GMA_LEVEL_MISSION); } //============================================================================= // Mission::LoadStreetRaceProps //============================================================================= // Description: Unload the p3d file that contains the instanced streetrace props // // Parameters: ( const char* loadString ) // // Return: void // //============================================================================= void Mission::UnloadStreetRaceProps( const char* loadString ) { HeapMgr()->PushHeap (GMA_LEVEL_MISSION); MEMTRACK_PUSH_GROUP( "Mission - StreetRacePropsUnload" ); //clear any junk if ( mStreetRacePropsUnload != NULL) { mStreetRacePropsUnload->ReleaseVerified(); } if( strcmp( loadString, "" ) != 0 ) { mStreetRacePropsUnload = new ZoneEventLocator; mStreetRacePropsUnload->AddRef(); mStreetRacePropsUnload->SetZoneSize( strlen(loadString) + 1 ); mStreetRacePropsUnload->SetZone( loadString ); mStreetRacePropsUnload->SetPlayerEntered(); } else { mStreetRacePropsUnload = NULL; } MEMTRACK_POP_GROUP( "Mission - StreetRacePropsUnload" ); HeapMgr()->PopHeap (GMA_LEVEL_MISSION); } void Mission::SetupStageChange() { mChangingStages = true; GetCurrentStage()->DoTransition(); } void Mission::DoStageChange() { // if( !GetInteriorManager()->IsEntering() && !GetInteriorManager()->IsExiting() ) { GetGuiSystem()->HandleMessage( GUI_MSG_RESUME_INGAME ); } MissionStage* currStage = GetCurrentStage(); if ( currStage->GetMissionLocked() && !UnlockStage( currStage ) ) { //Display the new message and stop the next stage from displaying its message rAssert( currStage->GetStartMessageIndex() >= 0 ); GetGuiSystem()->HandleMessage( GUI_MSG_INGAME_DISPLAY_PROMPT, currStage->GetStartMessageIndex() ); GetEventManager()->TriggerEvent( EVENT_STAGE_TRANSITION_FAILED ); GetStage( mCurrentStage + 1 )->ShowStartMessageIndex( false ); NextStage(); } else if ( mJumpBackStage ) { rTuneAssertMsg( (mCurrentStage - mJumpBackBy) >= 0, "Jumping back too far!" ); SetToStage( mCurrentStage - mJumpBackBy ); mJumpBackStage = false; } else { NextStage(); } GetCurrentStage()->Start(); if ( GetCurrentStage()->StartBonusObjective() ) { StartBonusObjectives(); } mChangingStages = false; } void Mission::SetSwappedCarsFlag(bool flag) { mbSwappedCars = flag; } bool Mission::GetSwappedCarsFlag() { return mbSwappedCars; } void Mission::InitStreetRacePropLoad() { //Chuck: Trigger the loading of the Street Race Specify Props if (mStreetRacePropsLoad != NULL) { GetEventManager()->TriggerEvent( (EventEnum)(EVENT_LOCATOR+LocatorEvent::DYNAMIC_ZONE), mStreetRacePropsLoad ); // about to do a street race so disable peds and parked cars if( IsRaceMission() ) { PedestrianManager::GetInstance()->DumpAllPedModels(); } else { PedestrianManager::GetInstance()->RemoveAllPeds(); } PedestrianManager::GetInstance()->AllowAddingPeds(false); GetPCM().DisableParkedCars(); } } void Mission::InitStreetRacePropUnload() { if (mStreetRacePropsUnload != NULL) { //Chuck: Trigger the unloading of the Street Race Specify Props GetEventManager()->TriggerEvent( (EventEnum)(EVENT_LOCATOR+LocatorEvent::DYNAMIC_ZONE), mStreetRacePropsUnload ); // street race done so reenable peds and parked cars PedestrianManager::GetInstance()->AllowAddingPeds(true); GetPCM().EnableParkedCars(); } } //============================================================================= // Mission::ShowHUD //============================================================================= // Description: Comment // // Parameters: // // Return: inline // //============================================================================= void Mission::ShowHUD( bool isShowHUD ) { mShowHUD = isShowHUD; CGuiScreenHud* currentHud = GetCurrentHud(); if( currentHud != NULL ) { currentHud->SetVisible( isShowHUD ); } } bool Mission::CanMDKCar(Vehicle* pVehicle,MissionStage* pStage) { //search for the input stage. int counter =0; int i = 0; int index =0; for (i = 0;iGetVehicle(j) == pVehicle) { counter++; } }//end of vehicle search loop } }//end of out missionstage loop if ( counter > 0) { return false; } else { return true; } }