1752 lines
63 KiB
C++
1752 lines
63 KiB
C++
//=============================================================================
|
|
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
|
|
//
|
|
// File: missionobjective.cpp
|
|
//
|
|
// Description: Implement MissionObjective
|
|
//
|
|
// History: 15/04/2002 + Created -- NAME
|
|
//
|
|
//=============================================================================
|
|
|
|
//========================================
|
|
// System Includes
|
|
//========================================
|
|
// Foundation Tech
|
|
#include <raddebug.hpp>
|
|
#include <string.h>
|
|
|
|
//========================================
|
|
// Project Includes
|
|
//========================================
|
|
|
|
#include <meta/locator.h>
|
|
#include <meta/carstartlocator.h>
|
|
#include <meta/zoneeventlocator.h>
|
|
|
|
#include <mission/gameplaymanager.h>
|
|
#include <mission/missionmanager.h>
|
|
#include <mission/objectives/missionobjective.h>
|
|
|
|
#include <presentation/gui/ingame/guimanageringame.h>
|
|
#include <presentation/gui/ingame/guiscreenhud.h>
|
|
#include <render/culling/worldscene.h>
|
|
#include <render/dsg/inststatentitydsg.h>
|
|
#include <render/rendermanager/rendermanager.h>
|
|
#include <presentation/gui/guisystem.h>
|
|
#include <presentation/gui/backend/guimanagerbackend.h>
|
|
|
|
#include <worldsim/character/character.h>
|
|
#include <worldsim/character/charactermanager.h>
|
|
|
|
#include <memory/srrmemory.h>
|
|
|
|
#include <render/IntersectManager/IntersectManager.h>
|
|
#include <worldsim/avatarmanager.h>
|
|
#include <roads/roadmanager.h>
|
|
#include <roads/intersection.h>
|
|
#include <roads/road.h>
|
|
#include <Render/DSG/AnimEntityDSG.h>
|
|
#include <Render/AnimEntityDSGManager/AnimEntityDSGManager.h>
|
|
#include <interiors/interiormanager.h>
|
|
#include <mission/charactersheet/charactersheetmanager.h>
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Global Data, Local Data, Local Classes
|
|
//
|
|
//******************************************************************************
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Public Member Functions
|
|
//
|
|
//******************************************************************************
|
|
|
|
//==============================================================================
|
|
// MissionObjective::MissionObjective
|
|
//==============================================================================
|
|
// Description: Constructor.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: N/A.
|
|
//
|
|
//==============================================================================
|
|
MissionObjective::MissionObjective() :
|
|
mObjType( OBJ_INVALID ),
|
|
mbFinished( false ),
|
|
mVehicle( NULL ),
|
|
mNumNPCs( 0 ),
|
|
mNumRemoveNPCs( 0 ),
|
|
mRockOut( false )
|
|
{
|
|
|
|
}
|
|
|
|
//==============================================================================
|
|
// MissionObjective::~MissionObjective
|
|
//==============================================================================
|
|
// Description: Destructor.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: N/A.
|
|
//
|
|
//==============================================================================
|
|
MissionObjective::~MissionObjective()
|
|
{
|
|
|
|
}
|
|
|
|
bool MissionObjective::AddNPCWaypoint( const char* npc, const char* location )
|
|
{
|
|
rTuneAssert( npc );
|
|
rTuneAssert( location );
|
|
|
|
for( unsigned int i = 0; i < mNumNPCs; ++i )
|
|
{
|
|
if( strcmp( mNPCNames[i], npc ) == 0 )
|
|
{
|
|
int numWays = mNPCs[i].numWayLocs;
|
|
rAssert( numWays >= 0 );
|
|
|
|
// add only if we have room
|
|
if( numWays >= (MAX_NPC_WAYPOINT_LOCATORS - 1) )
|
|
{
|
|
#if (RAD_TUNE || RAD_DEBUG)
|
|
char errMsg[ 256 ];
|
|
sprintf( errMsg, "Cannot add more NPC waypoints for %s", npc );
|
|
rTuneAssertMsg( false, errMsg );
|
|
#endif
|
|
return false;
|
|
}
|
|
mNPCs[i].wayLocs[ numWays ].SetText( location );
|
|
mNPCs[i].numWayLocs++;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
// if we got here, the npc is not in our list.
|
|
return false;
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::Initalize
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ()
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::Initialize()
|
|
{
|
|
#if defined(RAD_DEBUG) || defined(RAD_TUNE)
|
|
char errMsg[ 256 ];
|
|
#endif
|
|
|
|
//
|
|
// Trigger an event that this objective is now active
|
|
//
|
|
GetEventManager()->TriggerEvent( EVENT_MISSION_OBJECTIVE_NEW, reinterpret_cast< void* >( this ) );
|
|
|
|
mbFinished = false;
|
|
|
|
//Move the required NPCs to their new locations and store their old pos/rot.
|
|
unsigned int i;
|
|
|
|
for(i = 0; i < mNumRemoveNPCs; i++)
|
|
{
|
|
char name[64];
|
|
if(mRemoveNPCs[i].driver)
|
|
{
|
|
sprintf(name, "d_%s", mRemoveNPCs[i].name);
|
|
}
|
|
else
|
|
{
|
|
strcpy(name, mRemoveNPCs[i].name);
|
|
}
|
|
|
|
Character* c = GetCharacterManager()->GetCharacterByName(name);
|
|
if(c)
|
|
{
|
|
if(c->IsAmbient())
|
|
{
|
|
c->ResetAmbientPosition();
|
|
}
|
|
else
|
|
{
|
|
if(mRemoveNPCs[i].driver && c->GetTargetVehicle())
|
|
{
|
|
c->GetTargetVehicle()->SetDriver(NULL);
|
|
}
|
|
GetCharacterManager()->RemoveCharacter(c);
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < mNumNPCs; ++i )
|
|
{
|
|
if(mNPCs[ i ].driver)
|
|
{
|
|
Vehicle* vehicle = GetGameplayManager()->GetMissionVehicleByName(mNPCs[ i ].locator);
|
|
|
|
char name[64];
|
|
sprintf(name, "d_%s", mNPCNames[i]);
|
|
Character* character = GetCharacterManager( )->GetCharacterByName(name);
|
|
|
|
if(character && (character->GetTargetVehicle() == vehicle))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(character)
|
|
{
|
|
GetCharacterManager()->RemoveCharacter(character);
|
|
}
|
|
|
|
character = GetCharacterManager()->AddCharacter(CharacterManager::NPC, name, mNPCNames[i], "npd", NULL );
|
|
|
|
static_cast<NPCController*>(character->GetController())->TransitToState(NPCController::NONE);
|
|
character->SetTargetVehicle( vehicle );
|
|
character->AddToWorldScene();
|
|
character->GetStateManager()->SetState<CharacterAi::InCar>();
|
|
|
|
vehicle->SetDriver(character);
|
|
|
|
character->SetRole(Character::ROLE_DRIVER);
|
|
}
|
|
else
|
|
{
|
|
// pick an appropriate name based on if we are a bonus mission or not
|
|
bool hadToAdd = false;
|
|
|
|
mNPCs[ i ].npc = GetCharacterManager( )->GetMissionCharacter(mNPCNames[i]);
|
|
|
|
if( !mNPCs[ i ].npc )
|
|
{
|
|
char name[64];
|
|
hadToAdd = true;
|
|
if(GetGameplayManager()->GetCurrentMission()->IsBonusMission())
|
|
{
|
|
sprintf(name, "b_%s", mNPCNames[i]);
|
|
}
|
|
else
|
|
{
|
|
strcpy(name, mNPCNames[i]);
|
|
}
|
|
mNPCs[ i ].npc = GetCharacterManager()->AddCharacter(CharacterManager::NPC, name, mNPCNames[i], "npd", NULL );
|
|
mNPCs[ i ].npc->SetRole(Character::ROLE_MISSION);
|
|
}
|
|
else
|
|
{
|
|
mNPCs[ i ].npc->EnableAmbientDialogue(false);
|
|
}
|
|
|
|
|
|
rAssert( mNPCs[ i ].npc );
|
|
|
|
CarStartLocator* newPos = p3d::find<CarStartLocator>(mNPCs[ i ].locator);
|
|
|
|
// TODO : is this neccesary
|
|
mNPCs[ i ].npc->RemoveFromWorldScene();
|
|
mNPCs[ i ].npc->AddToWorldScene();
|
|
|
|
GetCharacterManager( )->SetGarbage(mNPCs[ i ].npc, false);
|
|
|
|
mNPCs[ i ].npc->AddRef();
|
|
|
|
NPCController* controller = (NPCController*) (mNPCs[ i ].npc->GetController());
|
|
rAssert( controller );
|
|
|
|
// set position & facing
|
|
// if we have no locator, just leave them where they are
|
|
if(newPos)
|
|
{
|
|
rmt::Vector oldpos, pos, dist;
|
|
newPos->GetLocation(&pos);
|
|
mNPCs[ i ].npc->GetPosition(oldpos);
|
|
dist.Sub(pos, oldpos);
|
|
|
|
bool loading = ((GetGuiSystem()->GetBackendManager()->GetCurrentScreen() == CGuiWindow::GUI_SCREEN_ID_LOADING) &&
|
|
GetGuiSystem()->GetBackendManager()->GetCurrentWindow()->IsRunning());
|
|
|
|
if(hadToAdd || (dist.Magnitude() > 20.0f) ||
|
|
((GetGameFlow()->GetCurrentContext() == CONTEXT_LOADING_GAMEPLAY) || loading))
|
|
{
|
|
mNPCs[ i ].npc->RelocateAndReset( pos, newPos->GetRotation() );
|
|
|
|
if(!hadToAdd)
|
|
{
|
|
if(mNPCs[ i ].npc->GetRole() != Character::ROLE_MISSION)
|
|
{
|
|
controller->SetTempWaypont(pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
// add the start locator as the first waypoint
|
|
if((mNPCs[ i ].npc->GetRole() == Character::ROLE_MISSION))
|
|
{
|
|
controller->ClearNPCWaypoints();
|
|
|
|
bool res = controller->AddNPCWaypoint( pos );
|
|
|
|
#if defined(RAD_DEBUG) || defined(RAD_TUNE)
|
|
sprintf( errMsg, "Can't add more waypoints for this objective NPC %s", mNPCNames[ i ] );
|
|
rTuneAssertMsg( res, errMsg );
|
|
#endif
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
#if defined(RAD_DEBUG) || defined(RAD_TUNE)
|
|
// for existing characters it's okay not to have a locator,
|
|
// but for new ones, its an error
|
|
sprintf( errMsg, "NPC %s created without valid locator (%s). Check spelling!\n",
|
|
mNPCNames[i], mNPCs[ i ].locator);
|
|
rTuneAssertMsg( false, errMsg );
|
|
#endif
|
|
}
|
|
|
|
if(mNPCs[ i ].npc->GetRole() == Character::ROLE_MISSION)
|
|
{
|
|
for( int j=0; j<mNPCs[ i ].numWayLocs; j++ )
|
|
{
|
|
Locator* loc = p3d::find<Locator>( mNPCs[ i ].wayLocs[ j ].GetUID() );
|
|
if( loc == NULL )
|
|
{
|
|
#if defined(RAD_DEBUG) || defined(RAD_TUNE)
|
|
sprintf( errMsg, "NPC Waypoint %s not found for NPC %s",
|
|
mNPCs[ i ].wayLocs[ j ].GetText(), mNPCNames[ i ] );
|
|
rTuneAssertMsg( false, errMsg );
|
|
#endif
|
|
continue;
|
|
}
|
|
rmt::Vector locPos;
|
|
loc->GetPosition( &locPos );
|
|
|
|
// the NPCController is created and assigned to the NPC in
|
|
// then NPCharacter constructor. So we should expect there
|
|
// to be a controller at this point
|
|
bool res = controller->AddNPCWaypoint( locPos );
|
|
|
|
#if defined(RAD_DEBUG) || defined(RAD_TUNE)
|
|
sprintf( errMsg, "Can't add more waypoints for this objective NPC %s", mNPCNames[ i ] );
|
|
rTuneAssertMsg( res, errMsg );
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GetCharacterManager()->AllowGarbageCollection(true);
|
|
|
|
GetCharacterManager()->GetCharacter(0)->SetRockinIdle(mRockOut);
|
|
OnInitialize();
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::Finalize
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ()
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::Finalize()
|
|
{
|
|
OnFinalize();
|
|
|
|
GetCharacterManager()->GetCharacter(0)->SetRockinIdle(false);
|
|
|
|
//return all NPCs to their original locations.
|
|
unsigned int i;
|
|
for ( i = 0; i < mNumNPCs; ++i )
|
|
{
|
|
if( mNPCs[ i ].driver)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
rAssert( mNPCs[ i ].npc );
|
|
|
|
// make all NPC's in this mission canidates for garbage colleciton
|
|
GetCharacterManager( )->SetGarbage(mNPCs[ i ].npc, true);
|
|
|
|
/***
|
|
mNPCs[ i ].npc->SetPosition( mNPCs[ i ].oldPos );
|
|
mNPCs[ i ].npc->SetFacingDir( mNPCs[ i ].oldRotation );
|
|
mNPCs[ i ].npc->UpdateTransformToLoco();
|
|
***/
|
|
mNPCs[ i ].npc->Release();
|
|
mNPCs[ i ].npc = NULL;
|
|
}
|
|
|
|
GetCharacterManager()->AllowGarbageCollection(false);
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::Update
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( float elapsedTime )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::Update( unsigned int elapsedTime )
|
|
{
|
|
OnUpdate( elapsedTime );
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::HandleEvent
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( EventEnum id, void* pEventData )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::HandleEvent( EventEnum id, void* pEventData )
|
|
{
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// MissionObjective::AddNPC
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( const char* name, CarStartLocator* newPos )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::AddNPC( const char* name, const char* loc, bool driver)
|
|
{
|
|
#if (RAD_TUNE || RAD_DEBUG)
|
|
char errMsg[ 128 ];
|
|
|
|
rTuneAssertMsg( name, "An NPC's name can't be null!" );
|
|
|
|
sprintf( errMsg, "Locator for NPC %s cannot be null!", name );
|
|
rTuneAssertMsg( loc, errMsg );
|
|
|
|
sprintf( errMsg, "Can't add more NPCs. Already reached max count of %d.", mNumNPCs );
|
|
rTuneAssertMsg( mNumNPCs < (MAX_NPCS - 1), errMsg );
|
|
#endif
|
|
|
|
//Add the NPC name to the list.
|
|
unsigned int len = strlen(name) < MAX_NPC_NAME_LENGTH - 1 ? strlen(name) : MAX_NPC_NAME_LENGTH - 2;
|
|
strncpy( mNPCNames[mNumNPCs], name, len );
|
|
mNPCNames[mNumNPCs][len] = '\0';
|
|
|
|
strcpy(mNPCs[ mNumNPCs ].locator, loc);
|
|
|
|
// NOTE: Don't need to add the char start locator to list of waypoints here
|
|
// because when AddCharacter is called on this NPC, the start locator
|
|
// will be automatically added first in the list of NPC waypoints
|
|
mNPCs[ mNumNPCs ].numWayLocs = 0;
|
|
|
|
mNPCs[ mNumNPCs ].driver = driver;
|
|
|
|
++mNumNPCs;
|
|
}
|
|
|
|
void MissionObjective::RemoveNPC( const char* npc, bool driver)
|
|
{
|
|
rAssert(mNumRemoveNPCs < MAX_NPCS);
|
|
strcpy(mRemoveNPCs[mNumRemoveNPCs].name, npc);
|
|
mRemoveNPCs[mNumRemoveNPCs].driver = driver;
|
|
mNumRemoveNPCs++;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Private Member Functions
|
|
//
|
|
//******************************************************************************
|
|
|
|
//=============================================================================
|
|
// MissionObjective::RegisterLocator
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( Locator* locator, int& hudIndex, bool primary, HudMapIcon::eIconType icon )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::RegisterLocator( Locator* locator,
|
|
int& hudIndex,
|
|
bool primary,
|
|
HudMapIcon::eIconType icon )
|
|
{
|
|
rmt::Vector destLoc;
|
|
locator->GetLocation( &destLoc );
|
|
|
|
RegisterPosition( destLoc, hudIndex, primary, icon, locator );
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::RegisterPosition
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( const rmt::Vector& pos, int& hudIndex, bool primary, HudMapIcon::eIconType icon )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::RegisterPosition( const rmt::Vector& pos,
|
|
int& hudIndex,
|
|
bool primary,
|
|
HudMapIcon::eIconType icon,
|
|
IHudMapIconLocator* hml )
|
|
{
|
|
CGuiScreenMultiHud* currentHud = GetCurrentHud();
|
|
if( currentHud )
|
|
{
|
|
hudIndex = currentHud->GetHudMap( 0 )->RegisterIcon( icon, pos, hml, primary );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::UnregisterLocator
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( int hudIndex )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::UnregisterLocator( int& hudIndex )
|
|
{
|
|
// unregister hud map icon
|
|
//
|
|
if( hudIndex != -1 )
|
|
{
|
|
CGuiScreenMultiHud* currentHud = GetCurrentHud();
|
|
if( currentHud != NULL )
|
|
{
|
|
currentHud->GetHudMap( 0 )->UnregisterIcon( hudIndex );
|
|
}
|
|
|
|
hudIndex = -1;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::AddEntity
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( char* entityname )
|
|
//
|
|
// Return: InstStatEntityDSG*
|
|
//
|
|
//=============================================================================
|
|
InstStatEntityDSG* MissionObjective::AddEntity( char* entityname, rmt::Vector pos )
|
|
{
|
|
MEMTRACK_PUSH_GROUP( "Mission - Entities" );
|
|
tDrawable* pGeometry = p3d::find<tDrawable>( entityname );
|
|
rAssert( pGeometry != NULL );
|
|
|
|
InstStatEntityDSG* pEnt =
|
|
new( GetGameplayManager()->GetCurrentMissionHeap() )
|
|
InstStatEntityDSG;
|
|
|
|
rAssert( pEnt != NULL );
|
|
|
|
//
|
|
// The entity takes overship of m, so spake Devin
|
|
//
|
|
rmt::Matrix* m = new( GetGameplayManager()->GetCurrentMissionHeap() ) rmt::Matrix;
|
|
|
|
m->Identity();
|
|
m->FillTranslate( pos );
|
|
|
|
pEnt->LoadSetUp( m, pGeometry );
|
|
|
|
MEMTRACK_POP_GROUP("Mission - Entities");
|
|
return pEnt;
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::DrawEntity
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( InstStatEntityDSG* entity )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::DrawEntity( InstStatEntityDSG* entity )
|
|
{
|
|
rAssert( entity != NULL );
|
|
GetRenderManager()->pWorldScene()->Add( entity );
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::HideEntity
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( InstStatEntityDSG* entity )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::HideEntity( InstStatEntityDSG* entity )
|
|
{
|
|
rAssert( entity != NULL );
|
|
GetRenderManager()->pWorldScene()->Remove( entity );
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::UnregisterPosition
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( int& hudIndex )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::UnregisterPosition( int& hudIndex )
|
|
{
|
|
UnregisterLocator( hudIndex );
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::ChangeIconType
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( int hudIndex, HudMapIcon::eIconType type )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
int MissionObjective::ChangeIconType( int hudIndex, HudMapIcon::eIconType type )
|
|
{
|
|
if( hudIndex != -1 )
|
|
{
|
|
CGuiScreenMultiHud* currentHud = GetCurrentHud();
|
|
if( currentHud != NULL )
|
|
{
|
|
return( currentHud->GetHudMap( 0 )->ChangeIconType( hudIndex, type ) );
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::GetObjectiveType
|
|
//=============================================================================
|
|
// Description: return what type of objective this is
|
|
//
|
|
// Parameters: none
|
|
//
|
|
// Return: ObjectiveTypeEnum - the type of this objective
|
|
//
|
|
//=============================================================================
|
|
MissionObjective::ObjectiveTypeEnum MissionObjective::GetObjectiveType() const
|
|
{
|
|
return mObjType;
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::SetObjectiveType
|
|
//=============================================================================
|
|
// Description: set the type of the objective
|
|
//
|
|
// Parameters: objType - the type of objective we're setting
|
|
//
|
|
// Return: NONE
|
|
//
|
|
//=============================================================================
|
|
void MissionObjective::SetObjectiveType( const ObjectiveTypeEnum objType )
|
|
{
|
|
mObjType = objType;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::UnlightPath( SwapArray<RoadManager::PathElement>& orPathRoute )
|
|
{
|
|
// rReleasePrintf("UnLightPath. 0x%x\n", orPathRoute.mpData );
|
|
int i;
|
|
for(i=orPathRoute.mUseSize-1; i>-1; i-- )
|
|
{
|
|
if( orPathRoute[i].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(false);
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(false);
|
|
}
|
|
}
|
|
for(i=GetAnimEntityDSGManager()->mpFloatingRightWayArrows.mUseSize-1; i>-1; i--)
|
|
{
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->SetVisibility(false);
|
|
}
|
|
for(i=GetAnimEntityDSGManager()->mpFloatingWrongWayArrows.mUseSize-1; i>-1; i--)
|
|
{
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->SetVisibility(false);
|
|
}
|
|
|
|
orPathRoute.ClearUse();
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetVisibility(false);
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetVisibility(false);
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::LightCurrentPath(SwapArray<RoadManager::PathElement>& orPathRoute )
|
|
{
|
|
int i;
|
|
for(i=orPathRoute.mUseSize-1; i>-1; i-- )
|
|
{
|
|
if( orPathRoute[i].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(true);
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(false);
|
|
}
|
|
}
|
|
for(i=GetAnimEntityDSGManager()->mpFloatingRightWayArrows.mUseSize-1; i>-1; i--)
|
|
{
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->SetVisibility(false);
|
|
}
|
|
for(i=GetAnimEntityDSGManager()->mpFloatingWrongWayArrows.mUseSize-1; i>-1; i--)
|
|
{
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->SetVisibility(false);
|
|
}
|
|
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetVisibility(true);
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetVisibility(false);
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::UnlightCurrentPath(SwapArray<RoadManager::PathElement>& orPathRoute )
|
|
{
|
|
int i;
|
|
for(i=orPathRoute.mUseSize-1; i>-1; i-- )
|
|
{
|
|
if( orPathRoute[i].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(false);
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(false);
|
|
}
|
|
}
|
|
for(i=GetAnimEntityDSGManager()->mpFloatingRightWayArrows.mUseSize-1; i>-1; i--)
|
|
{
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->SetVisibility(false);
|
|
}
|
|
for(i=GetAnimEntityDSGManager()->mpFloatingWrongWayArrows.mUseSize-1; i>-1; i--)
|
|
{
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->SetVisibility(false);
|
|
}
|
|
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetVisibility(false);
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetVisibility(false);
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::LightPathRightWay( SwapArray<RoadManager::PathElement>& orPathRoute, int iStart, int iPastEnd )
|
|
{
|
|
int i;
|
|
if( DirectionalArrowEnum::INTERSECTION & mArrowType )
|
|
{
|
|
iStart--;
|
|
for( i=iPastEnd-1; i>iStart; i-- )
|
|
{
|
|
if( orPathRoute[i].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(true);
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::LightPathWrongWay( SwapArray<RoadManager::PathElement>& orPathRoute, int iStart, int iPastEnd )
|
|
{
|
|
int i;
|
|
|
|
if( DirectionalArrowEnum::INTERSECTION & mArrowType )
|
|
{
|
|
iStart--;
|
|
for(i=iPastEnd; i>iStart; i-- )
|
|
{
|
|
if( orPathRoute[i].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->SetVisibility(false);
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->SetVisibility(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::UpdateLightPath( PathStruct& orPathStruct)
|
|
{
|
|
SwapArray<RoadManager::PathElement>& orPathRoute = orPathStruct.mPathRoute;
|
|
if(!GetCharacterSheetManager()->QueryNavSystemSetting())
|
|
{
|
|
UnlightCurrentPath(orPathRoute);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//LightCurrentPath(orPathRoute);
|
|
}
|
|
|
|
orPathStruct.mUpdateCount = (orPathStruct.mUpdateCount+1)%orPathStruct.msUpdateModulo;
|
|
if( orPathStruct.mUpdateCount == 0 )
|
|
UpdateGroundHeights(orPathRoute);
|
|
|
|
UpdateLongRoadArrows(orPathStruct);
|
|
|
|
rmt::Vector charPosn, charFacing, iconPosn, iconFacing, tempVect, tempVect2;
|
|
GetAvatarManager()->GetAvatarForPlayer(0)->GetPosition(charPosn);
|
|
GetAvatarManager()->GetAvatarForPlayer(0)->GetHeading(charFacing);
|
|
|
|
RoadManager::PathElement lastPathElem;
|
|
RoadSegment* pLastRoadSegment;
|
|
float lastSegmentT;
|
|
float lastRoadT;
|
|
int playerOnPathPosn;
|
|
float distPlayerFromRoad;
|
|
|
|
|
|
GetAvatarManager()->GetAvatarForPlayer(0)->GetLastPathInfo( lastPathElem,
|
|
pLastRoadSegment,
|
|
lastSegmentT,
|
|
lastRoadT );
|
|
if(lastPathElem.type == RoadManager::ET_INTERSECTION)
|
|
{
|
|
playerOnPathPosn = FindIntersectionInPath( orPathRoute, (Intersection*)lastPathElem.elem );
|
|
}
|
|
else
|
|
{
|
|
playerOnPathPosn = FindRoadInPath( orPathRoute, (Road*)lastPathElem.elem );
|
|
|
|
if(playerOnPathPosn>0)
|
|
{
|
|
((Intersection*)(orPathRoute[playerOnPathPosn-1].elem))->GetLocation(tempVect);
|
|
tempVect2.Sub( charPosn, tempVect );
|
|
distPlayerFromRoad = tempVect2.MagnitudeSqr(); //ensure it's out of view first, if we're setting it to red/wrong way
|
|
if(distPlayerFromRoad<120.0f)
|
|
playerOnPathPosn--;
|
|
}
|
|
}
|
|
|
|
if(playerOnPathPosn!=-1)
|
|
{
|
|
LightPathWrongWay(orPathRoute, 0, playerOnPathPosn);
|
|
LightPathRightWay(orPathRoute, playerOnPathPosn, orPathRoute.mUseSize);
|
|
}
|
|
|
|
/*
|
|
if(FindNearestRoadIconAhead(orPathRoute, charPosn, iconPosn, iconFacing))
|
|
{
|
|
charFacing.Normalize();
|
|
iconFacing.Normalize(); //if two per frame kills us, we're already dead.
|
|
|
|
if(iconFacing.Dot(charFacing)>-0.3f)
|
|
{
|
|
LightPathRightWay(orPathRoute);
|
|
}
|
|
else
|
|
{
|
|
LightPathWrongWay(orPathRoute);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// rAssert(false);
|
|
}
|
|
*/
|
|
}
|
|
//========================================================================
|
|
// missionobjective::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
int MissionObjective::FindIntersectionInPath(SwapArray<RoadManager::PathElement>& irPath, Intersection* ipIntToFind)
|
|
{
|
|
//
|
|
// Determine whether the players on the path that we want to light.
|
|
//
|
|
for(int i=irPath.mUseSize-1; i>-1; i--)
|
|
{
|
|
if(irPath[i].elem == ipIntToFind)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
//========================================================================
|
|
// missionobjective::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
int MissionObjective::FindRoadInPath(SwapArray<RoadManager::PathElement>& irPath, Road* ipRoadToFind)
|
|
{
|
|
//
|
|
// Determine whether the players on the path that we want to light.
|
|
//
|
|
for(int i=irPath.mUseSize-1; i>-1; i--)
|
|
{
|
|
if(irPath[i].type == RoadManager::ET_INTERSECTION)
|
|
continue;
|
|
if( (((Road*)(irPath[i].elem))->GetSourceIntersection() == ipRoadToFind->GetSourceIntersection()
|
|
&& ((Road*)(irPath[i].elem))->GetDestinationIntersection() == ipRoadToFind->GetDestinationIntersection())
|
|
||
|
|
(((Road*)(irPath[i].elem))->GetSourceIntersection() == ipRoadToFind->GetDestinationIntersection()
|
|
&& ((Road*)(irPath[i].elem))->GetDestinationIntersection() == ipRoadToFind->GetSourceIntersection())
|
|
) //found matching path
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// MissionObjective::UpdateGroundHeights
|
|
//
|
|
// This function is neccessary because not all ground intersects are
|
|
// loaded at any given time, due to memory considerations
|
|
//
|
|
// Should be called sparingly, since it needs to do ground intersects
|
|
// Solution: To be Amortised internally
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::UpdateGroundHeights( SwapArray<RoadManager::PathElement>& orPathRoute )
|
|
{
|
|
for(int i=orPathRoute.mUseSize-1; i>-1; i--)
|
|
{
|
|
if( orPathRoute[i].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->PlaceOnGround(0.2f, false);
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(1)->PlaceOnGround(0.2f, false);
|
|
}
|
|
}
|
|
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::UpdateLongRoadArrows( PathStruct& orPathStruct )
|
|
{
|
|
SwapArray<RoadManager::PathElement>& orPathRoute = orPathStruct.mPathRoute;
|
|
|
|
if( !(DirectionalArrowEnum::INTERSECTION & mArrowType) )
|
|
return;
|
|
|
|
//This is a temporary hack to prevent crashes, when the list is size 1
|
|
// it will be removed as soon as this system is cleaned up to follow paths
|
|
// arbitrarily instead of at the quantised road/intersection level.
|
|
if( orPathRoute.mUseSize<2 )
|
|
return;
|
|
|
|
RoadManager::PathElement lastPathElem;
|
|
RoadSegment* pLastRoadSegment;
|
|
float lastSegmentT;
|
|
float lastRoadT;
|
|
rmt::Vector playerPosn;
|
|
|
|
GetAvatarManager()->GetAvatarForPlayer(0)->GetLastPathInfo( lastPathElem,
|
|
pLastRoadSegment,
|
|
lastSegmentT,
|
|
lastRoadT );
|
|
|
|
GetAvatarManager()->GetAvatarForPlayer(0)->GetPosition(playerPosn);
|
|
if(lastPathElem.type == RoadManager::ET_INTERSECTION)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Determine whether the players on the path that we want to light.
|
|
//
|
|
for(int i=orPathRoute.mUseSize-1; i>-1; i--)
|
|
{
|
|
if(orPathRoute[i].type == RoadManager::ET_INTERSECTION)
|
|
continue;
|
|
if( (((Road*)(orPathRoute[i].elem))->GetSourceIntersection() == ((Road*)(lastPathElem.elem))->GetSourceIntersection()
|
|
&& ((Road*)(orPathRoute[i].elem))->GetDestinationIntersection() == ((Road*)(lastPathElem.elem))->GetDestinationIntersection())
|
|
||
|
|
(((Road*)(orPathRoute[i].elem))->GetSourceIntersection() == ((Road*)(lastPathElem.elem))->GetDestinationIntersection()
|
|
&& ((Road*)(orPathRoute[i].elem))->GetDestinationIntersection() == ((Road*)(lastPathElem.elem))->GetSourceIntersection())
|
|
) //found matching path
|
|
{
|
|
|
|
Road* pRoad = ((Road*)(orPathRoute[i].elem));
|
|
float roadLen = pRoad->GetRoadLength();
|
|
|
|
int numArrowsToPlace = static_cast< int >( ( roadLen / 40.0f ) - 1.0f );
|
|
|
|
if(numArrowsToPlace>5) numArrowsToPlace=5;
|
|
if(numArrowsToPlace<0) numArrowsToPlace=0;
|
|
|
|
RoadSegment* pRoadSegmentPlacement = NULL;
|
|
RoadSegment* pRoadSegReference = NULL;
|
|
rmt::Vector pathHeading, roadSegPlacementFacing, pathPosn, roadStartPosn, roadEndPosn, tempVect, tempVect2;
|
|
float distStartToNextRoad, distEndToNextRoad, scaleFactor, distPlayerFromRoad;
|
|
|
|
RoadSegment* pRoadStart = pRoad->GetRoadSegment(0);
|
|
RoadSegment* pRoadEnd = pRoad->GetRoadSegment(pRoad->GetNumRoadSegments()-1);
|
|
|
|
int playerRoadSegIndex = 0;
|
|
pLastRoadSegment->GetPosition(&tempVect);
|
|
RoadManager::FindClosestPointOnRoad( pRoad, tempVect, tempVect2, distPlayerFromRoad, playerRoadSegIndex );
|
|
|
|
|
|
//
|
|
//Determine if our path lands on a road heading the wrong direction
|
|
//If so, we need to invert arrow headings
|
|
//
|
|
pRoadEnd->GetPosition(&roadEndPosn);
|
|
pRoadStart->GetPosition(&roadStartPosn);
|
|
|
|
//
|
|
// Yay! Another Special Case
|
|
//
|
|
if(pRoadEnd==pRoadStart)
|
|
{
|
|
pRoadStart->GetCorner(0,roadStartPosn);
|
|
pRoadStart->GetCorner(1,roadEndPosn);
|
|
}
|
|
|
|
if(i>0)
|
|
{
|
|
rAssert(orPathRoute[i-1].type == RoadManager::ET_INTERSECTION);
|
|
((Intersection*)(orPathRoute[i-1].elem))->GetLocation(tempVect2);
|
|
|
|
//invert distances, since we're using the previous intersection in this case
|
|
tempVect.Sub(tempVect2, roadEndPosn);
|
|
distStartToNextRoad = tempVect.MagnitudeSqr();
|
|
tempVect.Sub(tempVect2, roadStartPosn);
|
|
distEndToNextRoad = tempVect.MagnitudeSqr();
|
|
}
|
|
else
|
|
{
|
|
if(orPathRoute.mUseSize==1) //return for now, since there's only one road, and we don't have origin, destination info
|
|
return;
|
|
|
|
rAssert(orPathRoute[i+1].type == RoadManager::ET_INTERSECTION);
|
|
((Intersection*)(orPathRoute[i+1].elem))->GetLocation(tempVect2);
|
|
|
|
tempVect.Sub(tempVect2, roadEndPosn);
|
|
distEndToNextRoad = tempVect.MagnitudeSqr();
|
|
tempVect.Sub(tempVect2, roadStartPosn);
|
|
distStartToNextRoad = tempVect.MagnitudeSqr();
|
|
}
|
|
|
|
if(distStartToNextRoad<distEndToNextRoad)
|
|
scaleFactor = -1.0f;
|
|
else
|
|
scaleFactor = 1.0f;
|
|
|
|
/*
|
|
if(i>0) //if we have an intersection previous
|
|
{
|
|
rAssert(orPathRoute[i-1].type == RoadManager::ET_INTERSECTION);
|
|
|
|
((Intersection*)(orPathRoute[i-1].elem))->AnimEntity(0)->GetAnimRootHeading(pathHeading);
|
|
((Intersection*)(orPathRoute[i-1].elem))->AnimEntity(0)->GetPosition(&pathPosn);
|
|
}
|
|
else
|
|
{
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetAnimRootHeading(pathHeading);
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetPosition(&pathPosn);
|
|
}
|
|
|
|
//
|
|
// Find out whic part of the road we're closer to, so that we can use that
|
|
// piece of road for directional reference
|
|
//
|
|
pRoadStart->GetPosition(0.0f,0.0f,&roadStartPosn);
|
|
pRoadEnd->GetPosition( 0.0f,0.0f,&roadEndPosn);
|
|
|
|
tempVect.Sub(roadStartPosn,pathPosn);
|
|
distToStart = tempVect.MagnitudeSqr();
|
|
|
|
tempVect.Sub(roadEndPosn,pathPosn);
|
|
distToEnd = tempVect.MagnitudeSqr();
|
|
|
|
if(distToStart<distToEnd)
|
|
pRoadSegReference = (RoadSegment*)pRoadStart;
|
|
else
|
|
pRoadSegReference = (RoadSegment*)pRoadEnd;
|
|
|
|
pRoadSegReference->GetEdgeNormal(0,tempVect);
|
|
if( tempVect.Dot(pathHeading)<0.0f )
|
|
scaleFactor = -1.0f;
|
|
else
|
|
scaleFactor = 1.0f;
|
|
*/
|
|
for(int j=5; j>0; j--)
|
|
{
|
|
if(j<=numArrowsToPlace)
|
|
{
|
|
float curDistPlacement = j*40.0f;
|
|
float realDistPlacement = 0.0f;
|
|
|
|
pRoad->FindRoadSegmentAtDist(curDistPlacement, &pRoadSegmentPlacement);
|
|
|
|
//if we're at the end of the path, cut arrows off past the goal
|
|
if(pRoad == orPathStruct.mpTargetRoadSeg->GetRoad() )
|
|
{
|
|
if( scaleFactor == 1.0f ) //if we're going forward on the road
|
|
{
|
|
if( pRoadSegmentPlacement->GetSegmentIndex() > orPathStruct.mpTargetRoadSeg->GetSegmentIndex() )
|
|
continue;
|
|
}
|
|
else // we're going backward on the road
|
|
{
|
|
if( pRoadSegmentPlacement->GetSegmentIndex() < orPathStruct.mpTargetRoadSeg->GetSegmentIndex() )
|
|
continue;
|
|
}
|
|
}
|
|
|
|
pRoadSegmentPlacement->GetPosition(0.0f, 0.0f, &tempVect);
|
|
|
|
UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j], tempVect);
|
|
UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j], tempVect);
|
|
|
|
tempVect2.Sub( playerPosn, tempVect );
|
|
distPlayerFromRoad = tempVect2.MagnitudeSqr(); //ensure it's out of view first
|
|
if( distPlayerFromRoad > 120.0f &&
|
|
( scaleFactor == 1.0f && ((int)pRoadSegmentPlacement->GetSegmentIndex()) < playerRoadSegIndex
|
|
|| scaleFactor == -1.0f && ((int)pRoadSegmentPlacement->GetSegmentIndex()) > playerRoadSegIndex)
|
|
)
|
|
{
|
|
//we're lighting a road piece further away from the goal than the user
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetVisibility(false);
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetVisibility(true);
|
|
}
|
|
else
|
|
{
|
|
//we're lighting a road piece further toward the goal than the user
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetVisibility(true);
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetVisibility(false);
|
|
}
|
|
|
|
//GetHeadingAlongPath(orPathRoute, i, (RoadSegment*)pRoadSegmentPlacement, tempVect);
|
|
|
|
//pRoadSegmentPlacement->GetPosition(0.0f, 0.0f, &tempVect2);
|
|
//tempVect.Sub( tempVect, tempVect2 );
|
|
|
|
pRoadSegmentPlacement->GetEdgeNormal(0,tempVect);
|
|
|
|
tempVect.Scale(scaleFactor);
|
|
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetAnimRootHeadingYUp( tempVect );
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetAnimRootHeadingYUp( tempVect );
|
|
/*
|
|
|
|
if( pRoadSegmentPlacement != NULL )
|
|
{
|
|
pRoadSegmentPlacement->GetPosition(0.0f, 0.0f, &tempVect);
|
|
|
|
UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j], tempVect);
|
|
UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j], tempVect);
|
|
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetVisibility(true);
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetVisibility(false);
|
|
|
|
pRoadSegmentPlacement->GetEdgeNormal(0,tempVect);
|
|
tempVect.Scale(scaleFactor);
|
|
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetAnimRootHeadingYUp( tempVect );
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetAnimRootHeadingYUp( tempVect );
|
|
}
|
|
else
|
|
{
|
|
rAssert(false);
|
|
}
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
tempVect.Set(0.0f,0.0f,0.0f);
|
|
|
|
UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j], tempVect);
|
|
UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j], tempVect);
|
|
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[j]->SetVisibility(false);
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[j]->SetVisibility(false);
|
|
}
|
|
}
|
|
|
|
|
|
i=-1;
|
|
}
|
|
}
|
|
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool MissionObjective::FindNearestRoadIconAhead
|
|
(
|
|
SwapArray<RoadManager::PathElement>& orPathRoute,
|
|
rmt::Vector& irPosn,
|
|
rmt::Vector& orIconPosn,
|
|
rmt::Vector& orIconFacing
|
|
)
|
|
{
|
|
float nearestInter = 36000000.0f;//6000.0f*6000.0f;
|
|
float temp;
|
|
rmt::Vector tempPosn;
|
|
bool retVal = false;
|
|
int i;
|
|
|
|
if( DirectionalArrowEnum::INTERSECTION & mArrowType )
|
|
{
|
|
//
|
|
// Go through the intersections in the path, finding the nearest
|
|
//
|
|
for(i=orPathRoute.mUseSize-1; i>-1; i--)
|
|
{
|
|
if( orPathRoute[i].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i].elem))->GetLocation(orIconPosn);
|
|
tempPosn.Sub(orIconPosn,irPosn);
|
|
|
|
temp = tempPosn.MagnitudeSqr();
|
|
|
|
if( temp < nearestInter )
|
|
{
|
|
nearestInter = temp;
|
|
((Intersection*)(orPathRoute[i].elem))->AnimEntity(0)->GetAnimRootHeading(orIconFacing);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go through the active right way markers, finding the nearest
|
|
//
|
|
for(i=GetAnimEntityDSGManager()->mpFloatingRightWayArrows.mUseSize-1; i>0; i--)
|
|
{
|
|
if(!GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->GetVisibility())
|
|
continue;
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->GetPosition(&orIconPosn);
|
|
tempPosn.Sub(orIconPosn,irPosn);
|
|
|
|
temp = tempPosn.MagnitudeSqr();
|
|
|
|
if( temp < nearestInter )
|
|
{
|
|
nearestInter = temp;
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[i]->GetAnimRootHeading(orIconFacing);
|
|
}
|
|
}
|
|
//
|
|
// Go through the active wrong way markers, finding the nearest
|
|
//
|
|
for(i=GetAnimEntityDSGManager()->mpFloatingWrongWayArrows.mUseSize-1; i>0; i--)
|
|
{
|
|
if(!GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->GetVisibility())
|
|
continue;
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->GetPosition(&orIconPosn);
|
|
tempPosn.Sub(orIconPosn,irPosn);
|
|
|
|
temp = tempPosn.MagnitudeSqr();
|
|
|
|
if( temp < nearestInter )
|
|
{
|
|
nearestInter = temp;
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[i]->GetAnimRootHeading(orIconFacing);
|
|
}
|
|
}
|
|
}
|
|
|
|
if( DirectionalArrowEnum::NEAREST_ROAD & mArrowType )
|
|
{
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetPosition(&orIconPosn);
|
|
tempPosn.Sub(orIconPosn,irPosn);
|
|
|
|
temp = tempPosn.MagnitudeSqr();
|
|
|
|
if( temp < nearestInter )
|
|
{
|
|
nearestInter = temp;
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetAnimRootHeading(orIconFacing);
|
|
}
|
|
}
|
|
|
|
if(nearestInter<36000000.0f)
|
|
retVal = true;
|
|
|
|
return retVal;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::LightPath
|
|
(
|
|
rmt::Vector& irTargetPosn,
|
|
PathStruct& orPathStruct
|
|
)
|
|
{
|
|
if( DirectionalArrowEnum::NEITHER & mArrowType )
|
|
return;
|
|
|
|
orPathStruct.mUpdateCount=0; //initialize the update for modulo updates (so we dont update arrows on ground height per frame)
|
|
SwapArray<RoadManager::PathElement>& orPathRoute = orPathStruct.mPathRoute;
|
|
// rReleasePrintf("LightPath. 0x%x\n", orPathRoute.mpData );
|
|
RoadSegment* pSourceRoadSeg = NULL;
|
|
RoadSegment* pTargetRoadSeg = NULL;
|
|
rmt::Vector sourcePosn, targetPosn, closestPosn;
|
|
float SourceTVal, TargetTVal;
|
|
|
|
if( orPathRoute.mUseSize != 0 )
|
|
{
|
|
//this shouldn't happen but we are going to ignore it.
|
|
rTuneAssert(0);
|
|
return;
|
|
}
|
|
|
|
if( GetInteriorManager()->IsInside() )
|
|
{
|
|
//Check for an all-interior mission, in which case,
|
|
//forget lighting entirely
|
|
GetAvatarManager()->GetAvatarForPlayer(0)->GetPosition(sourcePosn);
|
|
sourcePosn.Sub(sourcePosn,irTargetPosn);
|
|
|
|
//I'm assured that the interiors ar <100m in size and >=200m from the rest of the world
|
|
if(sourcePosn.MagnitudeSqr()< 10000.0f)
|
|
return;
|
|
|
|
GetInteriorManager()->ExteriorCharPosn(sourcePosn);
|
|
|
|
}
|
|
else
|
|
{
|
|
GetAvatarManager()->GetAvatarForPlayer(0)->GetPosition(sourcePosn);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// If Target is in an interior, and source is not, we want to get
|
|
// the target's exterior posn
|
|
//////////////////////////////////////////////////////////////////////////
|
|
tName interiorName = GetInteriorManager()->ClassifyPoint( irTargetPosn );
|
|
|
|
float dummy;
|
|
|
|
if(interiorName.GetUID()!= static_cast< tUID >( 0 ) )
|
|
{
|
|
ZoneEventLocator* pZEL = p3d::find<ZoneEventLocator>(interiorName.GetUID());
|
|
pZEL->GetPosition(&targetPosn);
|
|
GetIntersectManager()->FindClosestRoad(targetPosn, 50.0f, pTargetRoadSeg, dummy );
|
|
}
|
|
else
|
|
{
|
|
targetPosn = irTargetPosn;
|
|
}
|
|
|
|
GetIntersectManager()->FindClosestRoad(targetPosn, 50.0f, pTargetRoadSeg, dummy );
|
|
rAssert( pTargetRoadSeg != NULL );
|
|
|
|
GetIntersectManager()->FindClosestRoad(sourcePosn, 50.0f, pSourceRoadSeg, dummy );
|
|
rAssert( pSourceRoadSeg != NULL );
|
|
|
|
RoadManager::PathElement sourcePath, targetPath;
|
|
|
|
if( pSourceRoadSeg != NULL ) sourcePath.elem = pSourceRoadSeg->GetRoad();
|
|
sourcePath.type = RoadManager::ET_NORMALROAD;
|
|
|
|
if( pTargetRoadSeg != NULL ) targetPath.elem = pTargetRoadSeg->GetRoad();
|
|
targetPath.type = RoadManager::ET_NORMALROAD;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Determine Source and Target T Values
|
|
//////////////////////////////////////////////////////////////////////////
|
|
RoadManager* pRoadManager = RoadManager::GetInstance();
|
|
|
|
float closestDist;
|
|
int closestSegIndex;
|
|
pRoadManager->FindClosestPointOnRoad( (Road*)sourcePath.elem, sourcePosn,
|
|
closestPosn, closestDist, closestSegIndex );
|
|
|
|
SourceTVal = pRoadManager->DetermineRoadT( pSourceRoadSeg, pRoadManager->DetermineSegmentT( closestPosn, pSourceRoadSeg ) );
|
|
|
|
pRoadManager->FindClosestPointOnRoad( (Road*)targetPath.elem, targetPosn,
|
|
closestPosn, closestDist, closestSegIndex );
|
|
|
|
TargetTVal = pRoadManager->DetermineRoadT( pTargetRoadSeg, pRoadManager->DetermineSegmentT( closestPosn, pTargetRoadSeg ) );
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Find Path
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if( pTargetRoadSeg != NULL && pSourceRoadSeg != NULL )
|
|
{
|
|
RoadManager::GetInstance()->FindPathElementsBetween(
|
|
false,
|
|
sourcePath, SourceTVal, sourcePosn,
|
|
targetPath, TargetTVal, targetPosn,
|
|
orPathRoute );
|
|
}
|
|
else
|
|
{
|
|
rAssert(false);
|
|
//we should always have nav info for this
|
|
}
|
|
|
|
#ifdef RAD_DEBUG
|
|
pSourceRoadSeg->GetPosition( &mPathStart );
|
|
pTargetRoadSeg->GetPosition( &mPathEnd );
|
|
#endif
|
|
orPathStruct.mpTargetRoadSeg = pTargetRoadSeg;
|
|
orPathStruct.mTargetPosn = targetPosn;
|
|
|
|
AnimEntityDSG* pAnimEDSG;
|
|
AnimEntityDSG* pWrongwayAnimDSG;
|
|
rmt::Vector pathHeading;
|
|
rmt::Vector pathTemp;
|
|
int i;
|
|
|
|
if( DirectionalArrowEnum::INTERSECTION & mArrowType )
|
|
{
|
|
for( i=orPathRoute.mUseSize-1; i>-1; i-- )
|
|
{
|
|
//Set visibility and align arrows for path highlighting
|
|
if( orPathRoute[i].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i].elem))->GetLocation(sourcePosn);
|
|
pWrongwayAnimDSG = ((Intersection*)(orPathRoute[i].elem))->AnimEntity(1);
|
|
pAnimEDSG = ((Intersection*)(orPathRoute[i].elem))->AnimEntity(0);
|
|
pAnimEDSG->SetVisibility(true);
|
|
if( i+2 < orPathRoute.mUseSize )
|
|
//There's definitely some(other intersection) beyond this intersection
|
|
{
|
|
if( orPathRoute[i+1].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
((Intersection*)(orPathRoute[i+1].elem))->GetLocation(pathHeading);
|
|
}
|
|
else
|
|
{
|
|
((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(0)->GetPosition(0.0f,0.0f,&pathHeading);
|
|
((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(((Road*)(orPathRoute[i+1].elem))->GetNumRoadSegments()-1)->GetPosition(0.0f, 0.0f,&pathTemp);
|
|
if( (pathHeading - sourcePosn).MagnitudeSqr() > (pathTemp - sourcePosn).MagnitudeSqr() )
|
|
{
|
|
pathHeading = pathTemp;
|
|
}
|
|
}
|
|
}
|
|
else //No(other intersection) beyond this intersection
|
|
{
|
|
//Alpha semi-hack: Doing this because intersections aren't as easy
|
|
//to find because they're not in the tree. So, only do direct
|
|
//point if intersection is closer than the nearest road seg.
|
|
|
|
float intersectionToTarget = (targetPosn - sourcePosn).MagnitudeSqr();
|
|
|
|
((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(0)->GetPosition(0.0f,0.0f,&pathHeading);
|
|
((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(((Road*)(orPathRoute[i+1].elem))->GetNumRoadSegments()-1)->GetPosition(0.0f, 0.0f,&pathTemp);
|
|
if( (pathHeading - sourcePosn).MagnitudeSqr() > (pathTemp - sourcePosn).MagnitudeSqr() )
|
|
{
|
|
pathHeading = pathTemp;
|
|
}
|
|
|
|
if( //intersectionToTarget < (targetPosn - pathHeading).MagnitudeSqr() ||
|
|
intersectionToTarget < 1600.0f )
|
|
{
|
|
pathHeading = targetPosn;
|
|
}
|
|
/*
|
|
if( (targetPosn - sourcePosn).MagnitudeSqr() < 900.0f)
|
|
{
|
|
pathHeading = targetPosn;
|
|
}
|
|
else
|
|
{
|
|
((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(0)->GetPosition(0.0f,0.0f,&pathHeading);
|
|
((Road*)(orPathRoute[i+1].elem))->GetRoadSegment(((Road*)(orPathRoute[i+1].elem))->GetNumRoadSegments()-1)->GetPosition(0.0f, 0.0f,&pathTemp);
|
|
if( (pathHeading - sourcePosn).MagnitudeSqr() > (pathTemp - sourcePosn).MagnitudeSqr() )
|
|
{
|
|
pathHeading = pathTemp;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
pathHeading.Sub( pathHeading, sourcePosn );
|
|
//pAnimEDSG->PlaceOnGround( 0.2f );
|
|
pAnimEDSG->SetAnimRootHeadingYUp( pathHeading );
|
|
pWrongwayAnimDSG->SetAnimRootHeadingYUp( pathHeading );
|
|
}
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//move the floating arrow to the correct place
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
pSourceRoadSeg->GetPosition(0.0f, 0.0f, &sourcePosn);
|
|
UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0], sourcePosn);
|
|
UpdateAnimPosition(GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0], sourcePosn);
|
|
|
|
if( DirectionalArrowEnum::NEAREST_ROAD & mArrowType )
|
|
{
|
|
/*
|
|
rmt::Box3D oldBBox;
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->GetBoundingBox( &oldBBox );
|
|
pSourceRoadSeg->GetPosition(0.0f, 0.0f, &sourcePosn);
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetPosition( sourcePosn );
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->PlaceOnGround( 0.2f );
|
|
GetRenderManager()->pWorldScene()->Move(oldBBox, GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]);
|
|
|
|
|
|
|
|
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->GetBoundingBox( &oldBBox );
|
|
pSourceRoadSeg->GetPosition(0.0f, 0.0f, &sourcePosn);
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetPosition( sourcePosn );
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->PlaceOnGround( 0.2f );
|
|
GetRenderManager()->pWorldScene()->Move(oldBBox, GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]);
|
|
*/
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetVisibility(true);
|
|
|
|
i = 0;
|
|
if(i+1<orPathRoute.mUseSize) //There's something in this path
|
|
{
|
|
if( orPathRoute[i+1].type == RoadManager::ET_INTERSECTION )
|
|
{
|
|
GetHeadingAlongPath(orPathRoute, i, pSourceRoadSeg, pathHeading);
|
|
//todo: extract this code into a single function to call from for all long roads too.
|
|
}
|
|
else
|
|
{
|
|
((Road*)(orPathRoute[i].elem))->GetRoadSegment(0)->GetPosition(0.0f,0.0f,&pathHeading);
|
|
((Road*)(orPathRoute[i].elem))->GetRoadSegment(((Road*)(orPathRoute[i].elem))->GetNumRoadSegments()-1)->GetPosition(0.0f, 0.0f,&pathTemp);
|
|
if( (pathHeading - sourcePosn).MagnitudeSqr() > (pathTemp - sourcePosn).MagnitudeSqr() )
|
|
{
|
|
pathHeading = pathTemp;
|
|
}
|
|
}
|
|
}
|
|
else //Nothing in this path
|
|
{
|
|
pathHeading = targetPosn;
|
|
}
|
|
pathHeading.Sub( pathHeading, sourcePosn );
|
|
GetAnimEntityDSGManager()->mpFloatingRightWayArrows[0]->SetAnimRootHeadingYUp( pathHeading );
|
|
GetAnimEntityDSGManager()->mpFloatingWrongWayArrows[0]->SetAnimRootHeadingYUp( pathHeading );
|
|
}
|
|
if(!GetCharacterSheetManager()->QueryNavSystemSetting())
|
|
{
|
|
UnlightCurrentPath(orPathRoute);
|
|
return;
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::GetHeadingAlongPath
|
|
(
|
|
SwapArray<RoadManager::PathElement>& irPathRoute, int i,
|
|
RoadSegment* ipSourceRoadSeg,
|
|
rmt::Vector& orPathHeading
|
|
)
|
|
{
|
|
// bool invertResults;
|
|
// rmt::Vector pathTemp2, pathTemp;
|
|
rmt::Vector tempVect, tempVect2;
|
|
rmt::Vector roadEndPosn, roadStartPosn;
|
|
float distStartToNextRoad, distEndToNextRoad, scaleFactor;
|
|
|
|
RoadSegment* pRoadStart = ipSourceRoadSeg->GetRoad()->GetRoadSegment(0);
|
|
RoadSegment* pRoadEnd = ipSourceRoadSeg->GetRoad()->GetRoadSegment(ipSourceRoadSeg->GetRoad()->GetNumRoadSegments()-1);
|
|
|
|
//
|
|
// Yay! Another Special Case
|
|
//
|
|
if(pRoadEnd==pRoadStart)
|
|
{
|
|
pRoadStart->GetCorner(0,roadStartPosn);
|
|
pRoadStart->GetCorner(1,roadEndPosn);
|
|
}
|
|
else
|
|
{
|
|
pRoadStart->GetPosition( &roadStartPosn );
|
|
pRoadEnd->GetPosition( &roadEndPosn );
|
|
}
|
|
|
|
|
|
if(i>0)
|
|
{
|
|
rAssert(irPathRoute[i-1].type == RoadManager::ET_INTERSECTION);
|
|
((Intersection*)(irPathRoute[i-1].elem))->GetLocation(tempVect2);
|
|
|
|
//invert distances, since we're using the previous intersection in this case
|
|
tempVect.Sub(tempVect2, roadEndPosn);
|
|
distStartToNextRoad = tempVect.MagnitudeSqr();
|
|
tempVect.Sub(tempVect2, roadStartPosn);
|
|
distEndToNextRoad = tempVect.MagnitudeSqr();
|
|
}
|
|
else
|
|
{
|
|
if(irPathRoute.mUseSize==1) //return for now, since there's only one road, and we don't have origin, destination info
|
|
return;
|
|
|
|
rAssert(irPathRoute[i+1].type == RoadManager::ET_INTERSECTION);
|
|
((Intersection*)(irPathRoute[i+1].elem))->GetLocation(tempVect2);
|
|
|
|
tempVect.Sub(tempVect2, roadEndPosn);
|
|
distEndToNextRoad = tempVect.MagnitudeSqr();
|
|
tempVect.Sub(tempVect2, roadStartPosn);
|
|
distStartToNextRoad = tempVect.MagnitudeSqr();
|
|
}
|
|
|
|
if(distStartToNextRoad<distEndToNextRoad)
|
|
scaleFactor = -1.0f;
|
|
else
|
|
scaleFactor = 1.0f;
|
|
|
|
ipSourceRoadSeg->GetEdgeNormal(0,orPathHeading);
|
|
|
|
orPathHeading.Scale(scaleFactor);
|
|
ipSourceRoadSeg->GetPosition(0.0f, 0.0f, &tempVect);
|
|
orPathHeading.Add(tempVect);
|
|
|
|
/*
|
|
if(i+1 < irPath.mUseSize)
|
|
{
|
|
((Intersection*)(irPath[i+1].elem))->GetLocation(orPathHeading);
|
|
if(((Intersection*)(irPath[i+1].elem)) == ipSourceRoadSeg->GetRoad()->GetSourceIntersection())
|
|
invertResults=true;
|
|
else
|
|
invertResults=false;
|
|
}
|
|
else
|
|
{
|
|
((Intersection*)(irPath[i-1].elem))->GetLocation(orPathHeading);
|
|
if(((Intersection*)(irPath[i-1].elem)) == ipSourceRoadSeg->GetRoad()->GetSourceIntersection())
|
|
invertResults=true;
|
|
else
|
|
invertResults=false;
|
|
}
|
|
|
|
if(ipSourceRoadSeg->GetSegmentIndex()+1 > ((Road*)(irPath[i].elem))->GetNumRoadSegments()-1)
|
|
ipSourceRoadSeg->GetPosition(0.0f,0.0f,&pathTemp);
|
|
else
|
|
((Road*)(irPath[i].elem))->GetRoadSegment(ipSourceRoadSeg->GetSegmentIndex()+1)->GetPosition(0.0f,0.0f,&pathTemp);
|
|
|
|
float roadToIntersection1 = (orPathHeading - pathTemp).MagnitudeSqr();
|
|
|
|
if(ipSourceRoadSeg->GetSegmentIndex() == 0)
|
|
ipSourceRoadSeg->GetPosition(0.0f,0.0f,&pathTemp2);
|
|
else
|
|
((Road*)(irPath[i].elem))->GetRoadSegment(ipSourceRoadSeg->GetSegmentIndex()-1)->GetPosition(0.0f,0.0f,&pathTemp2);
|
|
|
|
float roadToIntersection2 = (orPathHeading - pathTemp2).MagnitudeSqr();
|
|
|
|
if( roadToIntersection1 < roadToIntersection2 && !invertResults )
|
|
{
|
|
orPathHeading = pathTemp;
|
|
}
|
|
else
|
|
{
|
|
orPathHeading = pathTemp2;
|
|
}*/
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void MissionObjective::UpdateAnimPosition( AnimEntityDSG* pAnimEntityDSG, rmt::Vector& irPosn )
|
|
{
|
|
rmt::Box3D oldBBox;
|
|
pAnimEntityDSG->GetBoundingBox( &oldBBox );
|
|
pAnimEntityDSG->SetPosition( irPosn );
|
|
pAnimEntityDSG->PlaceOnGround( 0.2f, false );
|
|
GetRenderManager()->pWorldScene()->Move(oldBBox, pAnimEntityDSG );
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::IsPattyAndSelmaDialog
|
|
//=============================================================================
|
|
// Description: determines if this is a patty and selma dialog objective
|
|
//
|
|
// Parameters: NONE
|
|
//
|
|
// Return: true/false - is this patty and selma talking to one another?
|
|
//
|
|
//=============================================================================
|
|
bool MissionObjective::IsPattyAndSelmaDialog() const
|
|
{
|
|
unsigned int i = 0;
|
|
for( ; i < mNumNPCs; ++i )
|
|
{
|
|
if( strcmp( mNPCNames[ i ], "patty" ) == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
if( strcmp( mNPCNames[ i ], "zmale1" ) == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
if( strcmp( mNPCNames[ i ], "zmale2" ) == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
if( strcmp( mNPCNames[ i ], "zmale3" ) == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//=============================================================================
|
|
// MissionObjective::IsRaceDialog
|
|
//=============================================================================
|
|
// Description: in a race dialog, you will be talking to milhouse, ralph, or
|
|
// nelson
|
|
//
|
|
// Parameters: NONE
|
|
//
|
|
// Return: true/false - is this one of the race characters we're talking
|
|
// to
|
|
//
|
|
//=============================================================================
|
|
bool MissionObjective::IsRaceDialog() const
|
|
{
|
|
unsigned int i = 0;
|
|
for( ; i < mNumNPCs; ++i )
|
|
{
|
|
if( strcmp( mNPCNames[ i ], "milhouse" ) == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
if( strcmp( mNPCNames[ i ], "ralph" ) == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
if( strcmp( mNPCNames[ i ], "nelson" ) == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|