//=============================================================================
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
//
// File: state.cpp
//
// Description: Implementation of class State
//
// History: 6/12/2002 + Created -- NAME
//
//=============================================================================
//========================================
// System Includes
//========================================
// Foundation Tech
#include <raddebug.hpp>
//========================================
// Project Includes
//========================================
#include <ai/state.h>
#include <ai/statemanager.h>
#include <worldsim/character/character.h>
#include <worldsim/character/charactercontroller.h>
#include <worldsim/character/charactermanager.h>
#include <worldsim/avatarmanager.h>
#include <worldsim/hitnrunmanager.h>
#include <ai/sequencer/action.h>
#include <ai/sequencer/actioncontroller.h>
#include <ai/sequencer/sequencer.h>
#include <ai/actionbuttonhandler.h>
#include <events/eventmanager.h>
#include <events/eventenum.h>
#include <worldsim/redbrick/vehicle.h>
#include <worldsim/redbrick/vehiclecontroller/vehiclecontroller.h>
#include <worldsim/redbrick/vehiclecontroller/vehiclemappable.h>
#include <worldsim/redbrick/vehiclecontroller/humanvehiclecontroller.h>
#include <worldsim/redbrick/geometryvehicle.h>
#include <worldsim/worldphysicsmanager.h>
#include <simcollision/collisionmanager.hpp>
#include <worldsim/avatarmanager.h>
#include <interiors/interiormanager.h>
#include <gameflow/gameflow.h>
#include <main/game.h>
#include <meta/locator.h>
#include <cheats/cheatinputsystem.h>
#include <cheats/cheats.h>
#include <gameflow/gameflow.h>
#include <contexts/contextenum.h>
#include <camera/relativeanimatedcam.h>
#include <camera/supercammanager.h>
#include <camera/supercamcentral.h>
#include <camera/supercam.h>
#include <contexts/context.h>
#include <presentation/gui/guisystem.h>
#include <presentation/gui/ingame/guimanageringame.h>
#include <presentation/gui/ingame/guiscreeniriswipe.h>
namespace CharacterAi
{
//******************************************************************************
//
// Global Data, Local Data, Local Classes
//
//******************************************************************************
const int MAX_CLASS_SIZE = 32; // bytes.
FBMemoryPool State::sMemoryPool( MAX_CLASS_SIZE, 32, GMA_LEVEL_OTHER );
static const char* sGetOutPassenger[] =
{
"get_out_of_car_open_door",
"get_out_of_car",
"get_out_of_car_close_door"
};
static const char* sGetOutDriver[] =
{
"get_out_of_car_open_door_driver",
"get_out_of_car_driver",
"get_out_of_car_close_door_driver"
};
static const char* sGetOutHighPassenger[] =
{
"get_out_of_car_open_door",
"get_out_of_car_high",
"get_out_of_car_close_door_high"
};
static const char* sGetOutHighDriver[] =
{
"get_out_of_car_open_door_driver",
"get_out_of_car_high_driver",
"get_out_of_car_close_door_high_driver"
};
static const char* sGetInPassenger[] =
{
"get_into_car_open_door",
"get_into_car",
"get_into_car_close_door"
};
static const char* sGetInDriver[] =
{
"get_into_car_open_door_driver",
"get_into_car_driver",
"get_into_car_close_door_driver"
};
static const char* sGetInHighPassenger[] =
{
"get_into_car_open_door_high",
"get_into_car_high",
"get_into_car_close_door"
};
static const char* sGetInHighDriver[] =
{
"get_into_car_open_door_high_driver",
"get_into_car_high_driver",
"get_into_car_close_door_driver"
};
//******************************************************************************
//
// Public Member Functions
//
//******************************************************************************
//==============================================================================
// State::State
//==============================================================================
// Description: Constructor.
//
// Parameters: None.
//
// Return: N/A.
//
//==============================================================================
State::State( Character* pCharacter )
:
mpCharacter( pCharacter )
{
}
//==============================================================================
// State::~State
//==============================================================================
// Description: Destructor.
//
// Parameters: None.
//
// Return: N/A.
//
//==============================================================================
State::~State()
{
mpCharacter = 0;
}
/*
==============================================================================
InCar::InCar
==============================================================================
Description: Comment
Parameters:( Character* pCharacter )
Return: InCar
=============================================================================
*/
InCar::InCar( Character* pCharacter )
:
State( pCharacter )
{
m_InCarAction = new InCarAction(pCharacter);
m_InCarAction->AddRef();
m_GetOutState = GETOUT_NONE;
}
InCar::~InCar( void )
{
m_InCarAction->Release();
}
void InCar::Enter( void )
{
if(!mpCharacter->GetTargetVehicle())
{
return;
}
mpCharacter->DoGroundIntersect(false);
m_GetOutState = GETOUT_NONE;
if(mpCharacter == GetCharacterManager()->GetCharacter(0))
{
GetVehicleCentral()->ActivateVehicleTriggers(false);
}
// if we did a git in, in car shoudl already be true, if not, need to force a little
if(!mpCharacter->IsInCar())
{
mpCharacter->GetActionController()->Clear();
mpCharacter->SetInCar( true );
mpCharacter->UpdateTransformToInCar();
}
mIsDriver = (mpCharacter->GetTargetVehicle()->mpDriver == mpCharacter) ||
(!mpCharacter->GetTargetVehicle()->HasDriver());
rmt::Vector seat = mIsDriver ?
mpCharacter->GetTargetVehicle()->GetDriverLocation() :
mpCharacter->GetTargetVehicle()->GetPassengerLocation();
bool busy = mpCharacter->GetActionController()->IsBusy();
if(!m_InCarAction->IsRunning())
{
m_InCarAction->SetStatus(SLEEPING);
}
// add the in car action (not very interesting) to the character sequencer
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
pSeq->AddAction( new Position(mpCharacter, seat, 0.0f, true));
if(!busy)
{
pSeq->AddAction( m_InCarAction);
}
pSeq->EndSequence();
mpCharacter->SetInCar( true );
if(!mpCharacter->GetTargetVehicle()->mVisibleCharacters)
{
mpCharacter->RemoveFromWorldScene();
}
else
{
mpCharacter->SetScale(mpCharacter->GetTargetVehicle()->mCharacterScale);
}
mpCharacter->RemoveFromPhysics();
}
void InCar::Exit( void )
{
if(mpCharacter == GetCharacterManager()->GetCharacter(0))
{
Vehicle::sDoBounce = false;
}
this->m_InCarAction->Done();
this->m_InCarAction->Clear();
mpCharacter->AddToPhysics();
if( mpCharacter->GetTargetVehicle() != NULL )
{
if( (mpCharacter->GetTargetVehicle()->GetDriver() == mpCharacter) && (mpCharacter->GetRole() == Character::ROLE_PEDESTRIAN))
{
mpCharacter->GetTargetVehicle()->SetDriver(NULL);
}
}
}
void InCar::SequenceAction( void )
{
Vehicle* pVehicle = mpCharacter->GetTargetVehicle( );
if(!pVehicle)
{
return;
}
rAssert(pVehicle);
if(!m_InCarAction->IsRunning())
{
m_InCarAction->SetStatus(SLEEPING);
}
// add the in car action (not very interesting) to the character sequencer
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
pSeq->AddAction( m_InCarAction);
pSeq->EndSequence();
rmt::Vector localPos = mpCharacter->GetPuppet()->GetPosition();
rmt::Vector seatPos;
if(mIsDriver)
{
seatPos = pVehicle->GetDriverLocation();
}
else
{
seatPos = pVehicle->GetPassengerLocation();
}
seatPos.y = localPos.y;
mpCharacter->GetPuppet()->SetPosition(seatPos);
if(mpCharacter == GetCharacterManager()->GetCharacter(0))
{
Vehicle::sDoBounce = true;
}
}
void InCar::Update( float timeins )
{
Vehicle* pVehicle = mpCharacter->GetTargetVehicle( );
if((!pVehicle) ||
((pVehicle->mVehicleDestroyed) &&
(GetGameFlow()->GetCurrentContext() != CONTEXT_DEMO) &&
(GetGameFlow()->GetCurrentContext() != CONTEXT_SUPERSPRINT)))
{
mpCharacter->GetActionController()->Clear();
mpCharacter->GetStateManager()->SetState<GetOut>();
return;
}
CharacterController::eIntention theIntention = CharacterController::NONE;
bool actionDown = false;
if(!GetHitnRunManager()->IsWaitingForReset())
{
theIntention = mpCharacter->GetController()->GetIntention();
#ifdef RAD_WIN32
actionDown = mpCharacter->GetController()->IsButtonDown(CharacterController::GetOutCar);
#else
actionDown = mpCharacter->GetController()->IsButtonDown(CharacterController::DoAction);
#endif
}
bool brake = false;
if( GetGameFlow()->GetCurrentContext() != CONTEXT_SUPERSPRINT )
{
switch(m_GetOutState)
{
case GETOUT_NONE:
{
#ifdef RAD_WIN32
if (theIntention == CharacterController::GetOutCar)
#else
if (theIntention == CharacterController::DoAction)
#endif
{
m_GetOutState = (pVehicle->GetSpeedKmh() < 30.0f) ? GETOUT_COMITTED : GETOUT_TRYING;
mpCharacter->GetTargetVehicle()->mGeometryVehicle->ShowBrakeLights();
}
}
break;
case GETOUT_TRYING :
{
if(!actionDown)
{
m_GetOutState = GETOUT_NONE;
mpCharacter->GetTargetVehicle()->mGeometryVehicle->HideBrakeLights();
VehicleController* controller = GetVehicleCentral()->GetVehicleController(GetVehicleCentral()->GetVehicleId(pVehicle));
if(controller)
{
rAssert(dynamic_cast<HumanVehicleController*>(controller));
static_cast<HumanVehicleController*>(controller)->GetMappable()->GetButton(VehicleMappable::Brake)->SetValue(0.0f);
static_cast<HumanVehicleController*>(controller)->GetMappable()->GetButton(VehicleMappable::HandBrake)->SetValue(0.0f);
}
break;
}
if ( pVehicle->GetSpeedKmh() < 30.0f &&
!pVehicle->IsUnstable() &&
!pVehicle->IsAirborn() )
{
m_GetOutState = GETOUT_COMITTED;
}
brake = true;
}
break;
case GETOUT_COMITTED :
{
if ( pVehicle->GetSpeedKmh() < 3.0f )
{
mpCharacter->GetActionController()->Clear();
VehicleController* controller = GetVehicleCentral()->GetVehicleController(GetVehicleCentral()->GetVehicleId(pVehicle));
if(controller)
{
rAssert(dynamic_cast<HumanVehicleController*>(controller));
static_cast<HumanVehicleController*>(controller)->GetMappable()->GetButton(VehicleMappable::Gas)->SetValue(0.0f);
static_cast<HumanVehicleController*>(controller)->GetMappable()->GetButton(VehicleMappable::Brake)->SetValue(0.0f);
static_cast<HumanVehicleController*>(controller)->GetMappable()->GetButton(VehicleMappable::HandBrake)->SetValue(1.0f);
}
mpCharacter->GetTargetVehicle()->mGeometryVehicle->HideBrakeLights();
mpCharacter->GetStateManager()->SetState<CharacterAi::GetOut>();
return;
}
else
{
VehicleController* v = GetVehicleCentral()->GetVehicleController(GetVehicleCentral()->GetVehicleId(pVehicle));
if(v && (v->GetGas() > 0.0f))
{
m_GetOutState = GETOUT_NONE;
mpCharacter->GetTargetVehicle()->mGeometryVehicle->HideBrakeLights();
VehicleController* controller = GetVehicleCentral()->GetVehicleController(GetVehicleCentral()->GetVehicleId(pVehicle));
static_cast<HumanVehicleController*>(controller)->GetMappable()->GetButton(VehicleMappable::HandBrake)->SetValue(0.0f);
}
else
{
brake = true;
}
}
}
break;
break;
}
}
if(brake)
{
VehicleController* controller = GetVehicleCentral()->GetVehicleController(GetVehicleCentral()->GetVehicleId(pVehicle));
if(controller)
{
rAssert(dynamic_cast<HumanVehicleController*>(controller));
static_cast<HumanVehicleController*>(controller)->GetMappable()->GetButton(VehicleMappable::Gas)->SetValue(0.0f);
static_cast<HumanVehicleController*>(controller)->GetMappable()->GetButton(VehicleMappable::HandBrake)->SetValue(1.0f);
}
}
if(m_InCarAction->IsRunning())
{
/*
if(mpCharacter->GetController()->IsButtonDown(CharacterController::Attack) && (m_GetOutState == GETOUT_NONE) )
{
m_InCarAction->IWannaRock(true);
}
*/
VehicleController* v = GetVehicleCentral()->GetVehicleController(GetVehicleCentral()->GetVehicleId(mpCharacter->GetTargetVehicle(), false));
if(v)
{
bool duh;
float steer = v->GetSteering(duh);
Action* action = NULL;
float speed = mpCharacter->GetTargetVehicle()->GetSpeedKmh();
if(mIsDriver)
{
if((rmt::Abs(steer) > 0.5) && (speed > 5.0f))
{
action = new SteerAction(mpCharacter, (steer < 0) ? "turn_left_driver" : "turn_right_driver", 10.0f);
}
else if (mpCharacter->GetTargetVehicle()->IsInReverse())
{
action = new ReverseAction(mpCharacter, "look_back_driver", 25.0f);
}
else if ((mpCharacter->GetTargetVehicle()->GetAccelMss() > 8.0f) && (speed < 20.0f))
{
action = new AccelAction(mpCharacter, "accelerate_driver", 15.0f);
}
else if((mpCharacter->GetTargetVehicle()->GetAccelMss() < -10.0f) && (speed > 50.0f))
{
action = new DecelAction(mpCharacter, "decelerate_driver", 15.0f);
}
else if(mpCharacter->GetTargetVehicle()->GetAccelMss() < -25.0f)
{
if(mpCharacter->GetTargetVehicle()->mVelocityCM.DotProduct(mpCharacter->GetTargetVehicle()->mVehicleFacing) > 0.0f)
{
action = new PlayAnimationAction(mpCharacter, "crash_driver");
}
}
}
else // passenger
{
if((rmt::Abs(steer) > 0.5) && (speed > 50.0f))
{
action = new SteerAction(mpCharacter, (steer < 0) ? "sway_right" : "sway_left", 20.0f);
}
}
if(action)
{
m_InCarAction->Done();
m_InCarAction->Clear();
mpCharacter->GetActionController()->SequenceSingleAction(action);
}
}
}
if( theIntention == CharacterController::CelebrateSmall )
{
m_InCarAction->Done();
m_InCarAction->Clear();
mpCharacter->GetActionController()->SequenceSingleAction( new PlayAnimationAction( mpCharacter, mIsDriver ? "in_car_victory_small_driver" : "in_car_victory_small"));
return;
}
if( theIntention == CharacterController::CelebrateBig )
{
m_InCarAction->Done();
m_InCarAction->Clear();
mpCharacter->GetActionController()->SequenceSingleAction(new PlayAnimationAction( mpCharacter, mIsDriver ? "in_car_victory_large_driver" : "in_car_victory_large"));
return;
}
if( theIntention == CharacterController::WaveHello)
{
m_InCarAction->Done();
m_InCarAction->Clear();
mpCharacter->GetActionController()->SequenceSingleAction( new PlayAnimationAction( mpCharacter, "wave_driver"));
return;
}
if( theIntention == CharacterController::WaveGoodbye)
{
m_InCarAction->Done();
m_InCarAction->Clear();
mpCharacter->GetActionController()->SequenceSingleAction( new PlayAnimationAction( mpCharacter, "wave_goodbye_driver"));
return;
}
}
/*
==============================================================================
Loco::Loco
==============================================================================
Description: Comment
Parameters( Character* pCharacter )
Returns:
=============================================================================
*/
Loco::Loco( Character* pCharacter )
:
State( pCharacter ),
mLastActionFrame(0)
{
}
Loco::~Loco( void )
{
}
void Loco::Enter( void )
{
if( mpCharacter->GetRole() != Character::ROLE_PEDESTRIAN )
{
mpCharacter->AddToWorldScene();
}
mpCharacter->SetScale(1.0f);
mpCharacter->UpdateTransformToLoco();
mpCharacter->DoGroundIntersect(true);
mpCharacter->SetInCar( false );
mpCharacter->SetTargetVehicle( NULL );
mpCharacter->GetWalkerLocomotionAction()->PlayDriver();
if(mpCharacter == GetCharacterManager()->GetCharacter(0))
{
GetVehicleCentral()->ActivateVehicleTriggers(true);
}
if(!mpCharacter->GetActionController()->IsBusy())
{
SequenceAction();
}
}
void Loco::Exit( void )
{
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
mpCharacter->GetWalkerLocomotionAction()->Done();;
mpCharacter->GetWalkerLocomotionAction()->AllowIdle(false);
mpCharacter->SetSimpleLoco(false);
}
void Loco::SequenceAction( void )
{
mpCharacter->SetSimpleLoco(false);
mpCharacter->GetWalkerLocomotionAction()->AllowIdle(false);
CharacterController::eIntention theIntention = mpCharacter->GetController()->GetIntention();
if((theIntention == CharacterController::Attack) && GetCheatInputSystem()->IsCheatEnabled(CHEAT_ID_KICK_TOGGLES_CHARACTER_MODEL))
{
mpCharacter->GetController()->SetIntention(CharacterController::NONE);
GetCharacterManager()->NextCheatModel();
return;
}
// if we are doing a kick, and in the action range of a power coupling,
// turn the kick into an aciton
// Wow, is this ever a hack.
if(( theIntention == CharacterController::Attack) && mpCharacter->GetActionButtonHandler( ))
{
if(dynamic_cast<ActionButton::DestroyObject*>(mpCharacter->GetActionButtonHandler( )))
{
theIntention = CharacterController::DoAction;
mpCharacter->GetController()->SetIntention(theIntention);
}
}
// give the actionbutton handler (if any) a crack at things
if ( (mpCharacter->GetActionButtonHandler( ) != (ActionButton::ButtonHandler*)0) && ((mLastActionFrame + 3) < GetGame()->GetFrameCount()) )
{
if ( mpCharacter->GetActionButtonHandler()->ButtonPressed( mpCharacter ) )
{
mLastActionFrame = GetGame()->GetFrameCount();
return;
}
}
mpCharacter->GetController()->ClearIntention();
// Sequence in the Dodge animation
if( theIntention == CharacterController::Dodge )
{
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
if( mpCharacter->IsNPC() ) // change NPC controller state when dodging is done
{
pSeq->BeginSequence();
pSeq->AddAction(new ChangeNPCControllerState(mpCharacter, NPCController::DODGING));
pSeq->EndSequence();
}
pSeq->BeginSequence();
Action* pAction = new DodgeAction( mpCharacter );
pSeq->AddAction( pAction );
pSeq->EndSequence();
if( mpCharacter->IsNPC() ) // change NPC controller state when dodging is done
{
pSeq->BeginSequence();
pSeq->AddAction(new ChangeNPCControllerState(mpCharacter, NPCController::FOLLOWING_PATH));
pSeq->EndSequence();
}
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
// Sequence in the jump animation
if ( theIntention == CharacterController::Jump && !GetInteriorManager()->IsInside())
{
if( !mpCharacter->IsNPC() &&
mpCharacter->GetSimState()->GetControl() == sim::simSimulationCtrl )
{
// if player character is in simulation control and jump button was pressed,
// we transit him back to AI control
mpCharacter->GetSimState()->SetControl( sim::simAICtrl );
mpCharacter->GetSimState()->ResetVelocities();
mpCharacter->OnTransitToAICtrl();
}
else
{
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
JumpAction* pAction = mpCharacter->GetJumpLocomotionAction();
pAction->Reset(CharacterTune::sfJumpHeight, false);
pSeq->AddAction( pAction );
pSeq->EndSequence();
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
}
// Sequence in the Cringe animation
if( theIntention == CharacterController::Cringe )
{
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
if( mpCharacter->IsNPC() )
{
pSeq->BeginSequence();
pSeq->AddAction(new ChangeNPCControllerState(mpCharacter, NPCController::CRINGING));
pSeq->EndSequence();
}
pSeq->BeginSequence();
Action* pAction = new CringeAction( mpCharacter );
pSeq->AddAction( pAction );
pSeq->EndSequence();
if( mpCharacter->IsNPC() )
{
pSeq->BeginSequence();
pSeq->AddAction(new ChangeNPCControllerState(mpCharacter, NPCController::FOLLOWING_PATH));
pSeq->EndSequence();
}
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
// Sequence in the TurnRight anim
if( theIntention == CharacterController::TurnRight )
{
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
Action* pAction = new PlayAnimationAction( mpCharacter, "turn60_CW" ); //, 50.0f );
pSeq->AddAction( pAction );
pSeq->EndSequence();
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
// Sequence in the TurnLeft anim
if( theIntention == CharacterController::TurnLeft )
{
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
Action* pAction = new PlayAnimationAction( mpCharacter, "turn60_CCW" );//, 50.0f );
pSeq->AddAction( pAction );
pSeq->EndSequence();
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
// Sequence in the attack anim
if( theIntention == CharacterController::Attack )
{
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
pSeq->AddAction( new PlayAnimationAction( mpCharacter, "break_quick" ));
pSeq->AddAction( new KickAction( mpCharacter, 0.25f ));
pSeq->EndSequence();
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
if( theIntention == CharacterController::CelebrateSmall )
{
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
PlayAnimationAction* action = new PlayAnimationAction( mpCharacter, "victory_small" );
action->AbortWhenMovementOccurs(true);
pSeq->AddAction(action);
pSeq->EndSequence();
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
if( theIntention == CharacterController::CelebrateBig )
{
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
pSeq->AddAction( new PlayAnimationAction( mpCharacter, "victory_large" ));
pSeq->EndSequence();
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
// Only do the test for turbo when we are not jumping.
//
if ( mpCharacter->GetController()->IsButtonDown( CharacterController::Dash ) && !GetInteriorManager()->IsInside())
{
mpCharacter->SetTurbo( true );
}
else
{
mpCharacter->SetTurbo( false );
}
if ( mpCharacter->IsInCollision() )
{
// Only play the animation if the character is running fast enough.
//
if ( false ) //mpCharacter->IsTurbo() && mpCharacter->GetDesiredSpeed() > 0.0f )
{
// Speed is good, now check the hit angle.
// [6/26/2002]
//
if ( mpCharacter->CanStaggerCollision( ) )
{
mpCharacter->GetActionController()->Clear();
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
Action* pAction = 0;
// Play run_into_object.
//
pSeq->BeginSequence();
pAction = new PlayAnimationAction( mpCharacter, "run_into_object" );
pSeq->AddAction( pAction );
pSeq->EndSequence( );
mpCharacter->ResetSpeed( );
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
return;
}
}
}
// nothing else got sequenced, do the default
if(mpCharacter->GetWalkerLocomotionAction()->GetStatus() != RUNNING)
{
mpCharacter->GetWalkerLocomotionAction()->SetStatus(SLEEPING);
}
mpCharacter->GetWalkerLocomotionAction()->AllowIdle(true);
mpCharacter->GetWalkerLocomotionAction()->PlayDriver();
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
pSeq->AddAction( mpCharacter->GetWalkerLocomotionAction());
pSeq->EndSequence();
mpCharacter->SetSimpleLoco(true);
}
void Loco::Update( float timeins )
{
}
/*
==============================================================================
GetIn
==============================================================================
*/
GetIn::GetIn( Character* pCharacter )
:
State( pCharacter ),
mObstructed(false),
mFirst(true),
mCollisionFailure(4)
{
}
GetIn::~GetIn( void )
{
}
void GetIn::Enter( void )
{
if(mFirst)
{
GetEventManager()->TriggerEvent( EVENT_GETINTOVEHICLE_START, mpCharacter );
mFirst = false;
}
if(!mpCharacter->GetTargetVehicle()->mIrisTransition && !mObstructed && (mpCharacter->GetTargetVehicle()->GetSpeedKmh() <= 1.0f))
{
if(mpCharacter->GetWalkerLocomotionAction()->GetStatus() != RUNNING)
{
mpCharacter->GetWalkerLocomotionAction()->SetStatus(SLEEPING);
}
mpCharacter->GetWalkerLocomotionAction()->PlayDriver();
if(mpCharacter == GetCharacterManager()->GetCharacter(0))
{
GetVehicleCentral()->ActivateVehicleTriggers(false);
}
// figure out how to get into the car
int nWaypoints;
rmt::Vector waypoints[4];
bool slide;
bool jump;
CalcGetInPath(&nWaypoints, waypoints, &slide, &jump);
if(jump)
{
mObstructed = true;
mpCharacter->GetActionController()->Clear();
Enter();
/*
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
pSeq->AddAction( new FragileArrive( mpCharacter, waypoints[0]) );
mpCharacter->GetJumpLocomotionAction()->Reset(1.9f);
pSeq->AddAction(mpCharacter->GetJumpLocomotionAction());
pSeq->EndSequence( );
*/
return;
}
rmt::Vector getinPosition = waypoints[nWaypoints - 1];
if( ( nWaypoints >= 3 ) && ( mpCharacter->GetTargetVehicle()->mpDriver != NULL ) )
{
GetEventManager()->TriggerEvent( EVENT_WRONG_SIDE_DUMBASS,
static_cast<Vehicle*>(mpCharacter->GetTargetVehicle()) );
}
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
bool isDriver = mpCharacter->GetTargetVehicle()->HasDriver() ? false : true;
Vehicle::Door door = (isDriver && !slide) ? Vehicle::DOOR_DRIVER : Vehicle::DOOR_PASSENGER;
Action* pAction = 0;
mpCharacter->GetTargetVehicle()->UpdateDoorState();
bool high = false;
if(isDriver)
{
high = mpCharacter->GetTargetVehicle()->GetDriverLocation().y > CharacterTune::sGetInHeightThreshold;
}
else
{
high = mpCharacter->GetTargetVehicle()->GetPassengerLocation().y > CharacterTune::sGetInHeightThreshold;
}
const char** anims = NULL;
if(high)
{
if(isDriver && !slide)
{
anims = sGetInHighDriver;
}
else
{
anims = sGetInHighPassenger;
}
}
else
{
if(isDriver && !slide)
{
anims = sGetInDriver;
}
else
{
anims = sGetInPassenger;
}
}
// add actions for all the get in waypoints
for(int i = 0; i < nWaypoints; i++)
{
pSeq->BeginSequence();
pAction = new Arrive( mpCharacter, waypoints[i], i == nWaypoints - 1 );
pSeq->AddAction( pAction );
// SlaveLoco
//
pAction = 0;
pAction = mpCharacter->GetWalkerLocomotionAction();
pSeq->AddAction( mpCharacter->GetWalkerLocomotionAction() );
pSeq->EndSequence( );
}
// Orient
//
pSeq->BeginSequence();
rmt::Matrix mat = mpCharacter->GetTargetVehicle( )->GetTransform();
pAction = new Orient( mpCharacter, mat.Row( 2 ) );
pSeq->AddAction( pAction );
// SlaveLoco
//
pAction = 0;
pAction = mpCharacter->GetWalkerLocomotionAction();
pSeq->AddAction( pAction );
pSeq->EndSequence( );
// Open Door Anim
//
if(mpCharacter->GetTargetVehicle()->NeedToOpenDoor(door))
{
float delay = CharacterTune::sGetInOpenDelay;
float time = CharacterTune::sGetInOpenSpeed;
float scale = 30.0f / CharacterTune::sfGetInOutOfCarAnimSpeed;
pSeq->BeginSequence();
pAction = new PlayAnimationAction( mpCharacter, anims[ 0 ], CharacterTune::sfGetInOutOfCarAnimSpeed);
pSeq->AddAction( pAction );
pSeq->AddAction( new CarDoorAction(mpCharacter->GetTargetVehicle(), Vehicle::DOORACTION_OPEN, door, delay * scale, time * scale));
pSeq->EndSequence( );
}
// Get In Car Anim
//
pSeq->BeginSequence();
pAction = new PlayAnimationAction( mpCharacter, anims[ 1 ], CharacterTune::sfGetInOutOfCarAnimSpeed);
pSeq->AddAction( pAction );
pSeq->EndSequence( );
rmt::Vector seat;
if(isDriver && !slide)
{
seat = mpCharacter->GetTargetVehicle()->GetDriverLocation();
}
else
{
seat = mpCharacter->GetTargetVehicle()->GetPassengerLocation();
}
pSeq->BeginSequence();
pSeq->AddAction( new ChangeLocomotion(mpCharacter, ChangeLocomotion::INCAR) );
pSeq->AddAction( new ChangeState<InCar>(mpCharacter));
pSeq->AddAction( new TriggerEventAction(EVENT_GETINTOVEHICLE_END, mpCharacter));
pSeq->EndSequence( );
pSeq->BeginSequence();
pSeq->AddAction( new DelayAction(0.05f));
pSeq->EndSequence( );
pSeq->BeginSequence();
pSeq->AddAction( new Position(mpCharacter, seat, 0.0f, true));
pSeq->AddAction( new PlayAnimationAction( mpCharacter, "in_car_idle", 300.0f));
pSeq->EndSequence( );
// Close Door Anim
//
if(mpCharacter->GetTargetVehicle()->HasActiveDoor(door) || mpCharacter->GetTargetVehicle()->NeedToCloseDoor(door))
{
float delay = CharacterTune::sGetInCloseDelay;
float time = CharacterTune::sGetInCloseSpeed;
float scale = 30.0f / CharacterTune::sfGetInOutOfCarAnimSpeed;
pSeq->BeginSequence();
pAction = new PlayAnimationAction( mpCharacter, anims[ 2 ], CharacterTune::sfGetInOutOfCarAnimSpeed);
pSeq->AddAction( new CarDoorAction(mpCharacter->GetTargetVehicle(), Vehicle::DOORACTION_CLOSE, door, delay * scale, time * scale));
pSeq->AddAction( pAction );
pSeq->EndSequence( );
}
if(slide)
{
rmt::Vector seatDist = mpCharacter->GetTargetVehicle()->GetPassengerLocation() -
mpCharacter->GetTargetVehicle()->GetDriverLocation();
bool seatClose = seatDist.Magnitude() < 0.1f;
rmt::Vector v = mpCharacter->GetTargetVehicle()->GetPassengerLocation();
pSeq->BeginSequence();
pSeq->AddAction( new Position(mpCharacter, v, 0.0f, true));
pSeq->EndSequence( );
v = mpCharacter->GetTargetVehicle()->GetDriverLocation();
pSeq->BeginSequence();
pSeq->AddAction( new Position(mpCharacter, v, 0.5f, true));
if(!seatClose)
{
pSeq->AddAction( new PlayAnimationAction(mpCharacter, "seatmove"));
}
pSeq->EndSequence( );
if(mpCharacter->GetTargetVehicle()->NeedToCloseDoor(Vehicle::DOOR_DRIVER))
{
float delay = CharacterTune::sGetInCloseDelay;
float time = CharacterTune::sGetInCloseSpeed;
float scale = 30.0f / CharacterTune::sfGetInOutOfCarAnimSpeed;
pSeq->BeginSequence();
pAction = new PlayAnimationAction( mpCharacter, "get_into_car_close_door_driver", CharacterTune::sfGetInOutOfCarAnimSpeed);
pSeq->AddAction( new CarDoorAction(mpCharacter->GetTargetVehicle(), Vehicle::DOORACTION_CLOSE, Vehicle::DOOR_DRIVER, delay * scale, time * scale));
pSeq->AddAction( pAction );
pSeq->EndSequence( );
}
}
pSeq->BeginSequence();
pSeq->AddAction( new ReleaseDoorsAction(mpCharacter->GetTargetVehicle()));
pSeq->EndSequence( );
}
else
{
//Do an iris wipe in
GetGuiSystem()->HandleMessage( GUI_MSG_START_IRIS_WIPE_CLOSE );
//Set the speed of the wipe
CGuiScreenIrisWipe* iw = static_cast<CGuiScreenIrisWipe*>(GetGuiSystem()->GetInGameManager()->FindWindowByID( CGuiWindow::GUI_SCREEN_ID_IRIS_WIPE ));
const float speed = 1.0f;
iw->SetRelativeSpeed( speed );
//add listener
GetEventManager()->AddListener( this, EVENT_GUI_IRIS_WIPE_CLOSED );
//Pause gameplay
GetGameFlow()->GetContext( CONTEXT_GAMEPLAY )->Suspend();
}
}
void GetIn::HandleEvent( EventEnum id, void* pUserData )
{
if ( id == EVENT_GUI_IRIS_WIPE_CLOSED )
{
mpCharacter->RemoveFromPhysics();
GetEventManager()->RemoveListener( this, EVENT_GUI_IRIS_WIPE_CLOSED );
Vehicle* pVehicle = mpCharacter->GetTargetVehicle();
rAssert( pVehicle );
rmt::Vector pos;
pVehicle->GetPosition( &pos );
GetAvatarManager()->PutCharacterInCar( mpCharacter, pVehicle );
if(!pVehicle->mVisibleCharacters)
{
mpCharacter->RemoveFromWorldScene();
}
GetSuperCamManager()->GetSCC( 0 )->SelectSuperCam( SuperCam::FOLLOW_CAM, SuperCamCentral::CUT, 0 ); //Override the auto one
//TODO: SWITCH MODELS
//Wipe out when we are finished moving.
GetGuiSystem()->HandleMessage( GUI_MSG_START_IRIS_WIPE_OPEN );
GetGameFlow()->GetContext( CONTEXT_GAMEPLAY )->Resume();
GetEventManager()->TriggerEvent( EVENT_GETINTOVEHICLE_END, mpCharacter );
pVehicle->MoveDoor(Vehicle::DOOR_DRIVER, Vehicle::DOORACTION_CLOSE, 0.0f);
pVehicle->MoveDoor(Vehicle::DOOR_PASSENGER, Vehicle::DOORACTION_CLOSE, 0.0f);
}
}
// figure out how to get into the car from an arbitrary location
void GetIn::CalcGetInPath(int* nWaypoints, rmt::Vector* waypoints, bool* doingSlide, bool* jump)
{
const float origedge = 0.75f; // how far want to be from the car at the nav points ( TODO : make this tunable?)
const float edge = origedge / 1.414f; // x & z need to be sacled by sqrt(2) to make the diagonal distance right ;
rmt::Vector box = mpCharacter->GetTargetVehicle()->GetExtents();
bool isDriver = mpCharacter->GetTargetVehicle()->HasDriver() ? false : true;
// grab matrices to get from car space to world space (we do all our work in car space)
rmt::Matrix carToWorld = mpCharacter->GetTargetVehicle( )->GetTransform();
rmt::Matrix worldToCar = mpCharacter->GetTargetVehicle( )->GetTransform();
worldToCar.Invert();
// get character position in car space
rmt::Vector characterPosition;
mpCharacter->GetPosition(characterPosition);
characterPosition.Transform(worldToCar);
*doingSlide = false;
*jump = false;
*nWaypoints = 0;
if((characterPosition.y > (-box.y / 2)) &&
(characterPosition.x < box.x) &&
(characterPosition.x > -box.x) &&
(characterPosition.z < box.z) &&
(characterPosition.z > -box.z))
{
// get in position (car space)
rmt::Vector getinPosition = CharacterTune::sGetInPosition;
getinPosition = -getinPosition;
getinPosition.Add(mpCharacter->GetTargetVehicle( )->GetDriverLocation());
// swap get in poistion for driver
characterPosition.x = getinPosition.x - 0.5f;
// add final get in position to waypoints
characterPosition.Transform( carToWorld );
waypoints[(*nWaypoints)++] = characterPosition;
*jump = true;
return;
}
if(isDriver && mpCharacter->GetTargetVehicle()->mAllowSlide)
{
rmt::Vector driverPosition = CharacterTune::sGetInPosition;
driverPosition.x = -driverPosition .x;
driverPosition.Add(mpCharacter->GetTargetVehicle( )->GetDriverLocation());
rmt::Vector passPosition = CharacterTune::sGetInPosition;
passPosition.Add(mpCharacter->GetTargetVehicle( )->GetPassengerLocation());
driverPosition.Sub(characterPosition);
passPosition.Sub(characterPosition);
if(characterPosition.x > (box.x - 0.5f))
{
isDriver = false;
*doingSlide = true;
}
}
// these are the edges of the car from a walking perspective
float carFront = box.z + (edge);
float carRear = -box.z - (edge);;
float carNearSide = (box.x + edge) * (isDriver ? -1 : 1);
float carFarSide = (box.x + edge) * (isDriver ? 1 : -1);
// get in position (car space)
rmt::Vector getinPosition = CharacterTune::sGetInPosition;
// swap get in poistion for driver
if ( isDriver )
{
// mirror over x.
getinPosition.x = -getinPosition.x;
getinPosition.Add(mpCharacter->GetTargetVehicle( )->GetDriverLocation());
}
else
{
getinPosition.Add(mpCharacter->GetTargetVehicle( )->GetPassengerLocation());
}
// are we in fron of the car or behind
bool front = characterPosition.z > 0;
bool onside = true;
if(((characterPosition.z > box.z) || (characterPosition.z < -box.z)) &&
(isDriver ? (characterPosition.x > -(box.x - (edge / 2))) : (characterPosition.x < (box.x - (edge / 2))) ))
{
onside = false;
}
if(((characterPosition.z < box.z) && (characterPosition.z > -box.z)) &&
(isDriver ? (characterPosition.x > 0) : (characterPosition.x < 0)))
{
onside = false;
}
if(!onside)
{
// we are offside, need some more nav points
// are we on the other side of the car
if((characterPosition.z < box.z) && (characterPosition.z > -box.z))
{
// add far corner to waypoints
rmt::Vector tmpPosition(0,0,0);
tmpPosition.z += front ? carFront : carRear;
tmpPosition.x += carFarSide;
tmpPosition.Transform( carToWorld );
waypoints[(*nWaypoints)++] = tmpPosition;
}
// add near corner to waypoints
rmt::Vector tmpPosition(0,0,0);
tmpPosition.z += front ? carFront : carRear;
tmpPosition.x += carNearSide;
tmpPosition.Transform( carToWorld );
waypoints[(*nWaypoints)++] = tmpPosition;
}
// add final get in position to waypoints
getinPosition.Transform( carToWorld );
waypoints[(*nWaypoints)++] = getinPosition;
}
void GetIn::SequenceAction( void )
{
Enter();
}
void GetIn::Update( float timeins )
{
if(mpCharacter->CollidedThisFrame() && (mCollisionFailure == 0) && !mpCharacter->GetJumpLocomotionAction()->IsInJump())
{
mObstructed = true;
mpCharacter->GetActionController()->Clear();
Enter();
}
if(mCollisionFailure)
{
mCollisionFailure--;
}
}
void GetIn::Exit( void )
{
if(!mpCharacter->GetTargetVehicle()->mVisibleCharacters)
{
mpCharacter->RemoveFromWorldScene();
}
mpCharacter->GetWalkerLocomotionAction()->StopDriver();
mpCharacter->GetWalkerLocomotionAction()->Done();;
}
/*
==============================================================================
GetOut
==============================================================================
*/
GetOut::GetOut( Character* pCharacter )
:
State( pCharacter ),
mObstructed(false),
mFirst(true),
mPanic(false)
{
}
GetOut::~GetOut( void )
{
}
void GetOut::Enter( void )
{
bool destroyed = !mpCharacter->GetTargetVehicle() || mpCharacter->GetTargetVehicle()->mVehicleDestroyed;
bool iris = !destroyed && (mObstructed || mpCharacter->GetTargetVehicle()->mIrisTransition);
if(mFirst)
{
mFirst = false;
GetEventManager()->TriggerEvent( EVENT_GETOUTOFVEHICLE_START, mpCharacter );
}
if ( !iris || mpCharacter != GetCharacterManager()->GetCharacter(0))
{
mpCharacter->AddToWorldScene();
mpCharacter->SetScale(1.0f);
DoGetOut();
}
else
{
//Do an iris wipe in
GetGuiSystem()->HandleMessage( GUI_MSG_START_IRIS_WIPE_CLOSE );
//Set the speed of the wipe
CGuiScreenIrisWipe* iw = static_cast<CGuiScreenIrisWipe*>(GetGuiSystem()->GetInGameManager()->FindWindowByID( CGuiWindow::GUI_SCREEN_ID_IRIS_WIPE ));
const float speed = 1.0f;
iw->SetRelativeSpeed( speed );
//add listener
GetEventManager()->AddListener( this, EVENT_GUI_IRIS_WIPE_CLOSED );
//Pause gameplay
GetGameFlow()->GetContext( CONTEXT_GAMEPLAY )->Suspend();
if(mpCharacter->GetTargetVehicle())
{
mpCharacter->GetTargetVehicle()->SetOutOfCarSimState();
}
}
}
static sim::TArray< sim::RayIntersectionInfo > sIntersectInfo( 64 );
void GetOut::HandleEvent( EventEnum id, void* pUserData )
{
if ( id == EVENT_GUI_IRIS_WIPE_CLOSED )
{
GetEventManager()->RemoveListener( this, EVENT_GUI_IRIS_WIPE_CLOSED );
Character* character = GetAvatarManager()->GetAvatarForPlayer( 0 )->GetCharacter();
Vehicle* car = GetAvatarManager()->GetAvatarForPlayer( 0 )->GetVehicle();
GetEventManager()->TriggerEvent( EVENT_GETOUTOFVEHICLE_END, character );
car->MoveDoor(Vehicle::DOOR_DRIVER, Vehicle::DOORACTION_CLOSE, 0.0f);
car->MoveDoor(Vehicle::DOOR_PASSENGER, Vehicle::DOORACTION_CLOSE, 0.0f);
character->SetInCar( false );
character->SetTargetVehicle( NULL );
character->AddToWorldScene();
mpCharacter->SetScale(1.0f);
// get in position (car space)
rmt::Vector getOutPosition = CharacterTune::sGetInPosition;
int isDriver = car->HasDriver() ? 0 : 1;
if(!mObstructed)
{
// swap get in poistion for driver
if ( isDriver )
{
// mirror over x.
getOutPosition.x = -getOutPosition.x;
getOutPosition.Add( car->GetDriverLocation() );
}
else
{
getOutPosition.Add( car->GetPassengerLocation() );
}
getOutPosition.Transform( car->GetTransform() );
rmt::Vector carPos;
car->GetPosition(&carPos);
getOutPosition.y = carPos.y - car->GetExtents().y;
// check if point we want to teleport to is objstructed
sIntersectInfo.Clear();
float fOldRayThickness = sim::RayIntersectionInfo::sRayThickness;
static float sfCharacterRayThickness = 0.3f;
sim::RayIntersectionInfo::sRayThickness = sfCharacterRayThickness;
bool bFoundIntersect = false;
float outDist = VERY_LARGE;
float currentDist = outDist;
HeapMgr()->PushHeap( GMA_TEMP );
// adds in the list the collision object interfering with the ray and ordered according to their distance to the source.
// use sim::RayIntersectionInfo::SetMethod(method) to set the method
// use sim::RayIntersectionInfo::SetReturnClosestOnly(true/false) if you need only the closest object
// nb. if SetReturnClosestOnly(true) is used, the previous returned list can be used as a cache.
sim::RayIntersectionInfo::SetReturnClosestOnly( false );
sim::RayIntersectionInfo::SetMethod( sim::RayIntersectionVolume );
rmt::Vector rayOrg;
mpCharacter->GetPosition(rayOrg);
rmt::Vector rayEnd = getOutPosition;
HeapMgr()->PopHeap( GMA_TEMP );
// Test ray against remaining collision objects.
//
GetWorldPhysicsManager()->mCollisionManager->DetectRayIntersection(sIntersectInfo, rayOrg, rayEnd, false, car->mCollisionAreaIndex );
for ( int i = 0; i < sIntersectInfo.GetSize( ); i++ )
{
if ( sIntersectInfo[ i ].mCollisionVolume &&
(sIntersectInfo[ i ].mCollisionVolume->GetCollisionObject()->GetSimState()->mAIRefPointer != mpCharacter ) &&
(sIntersectInfo[ i ].mCollisionVolume->GetCollisionObject()->GetSimState()->mAIRefPointer != car ))
{
mObstructed = true;
break;
}
}
sim::RayIntersectionInfo::sRayThickness = fOldRayThickness;
}
if(mObstructed)
{
car->GetPosition(&getOutPosition);
getOutPosition.y += car->GetExtents().y + 0.2f;
}
rmt::Vector facing = car->GetTransform().Row(0);
if(isDriver)
{
facing.Scale(-1.0f);
}
GetAvatarManager()->PutCharacterOnGround( character, car );
character->RelocateAndReset( getOutPosition, choreo::GetWorldAngle(facing.x, facing.z), true, true );
character->SnapToGround();
rmt::Vector newPos;
character->GetPosition(&newPos);
float dist = mObstructed ? 3.0f : 1.0f;
if(rmt::Abs(getOutPosition.y - newPos.y) > dist)
{
car->GetPosition(&getOutPosition);
getOutPosition.y += car->GetExtents().y + 0.2f;
character->RelocateAndReset( getOutPosition, choreo::GetWorldAngle(facing.x, facing.z), true, true );
}
GetVehicleCentral()->ActivateVehicleTriggers(true);
#ifdef RAD_WIN32
GetSuperCamManager()->GetSCC( 0 )->SelectSuperCam( SuperCam::ON_FOOT_CAM, SuperCamCentral::CUT, 0 );
#else
GetSuperCamManager()->GetSCC( 0 )->SelectSuperCam( SuperCam::WALKER_CAM, SuperCamCentral::CUT, 0 );
#endif
//Wipe out when we are finished moving.
GetGuiSystem()->HandleMessage( GUI_MSG_START_IRIS_WIPE_OPEN );
GetGameFlow()->GetContext( CONTEXT_GAMEPLAY )->Resume();
}
}
void GetOut::Exit( void )
{
}
void GetOut::SequenceAction( void )
{
Enter();
}
void GetOut::Update( float timeins )
{
if(mpCharacter->CollidedThisFrame() && !mPanic)
{
mObstructed = true;
mpCharacter->GetActionController()->Clear();
Enter();
}
}
void GetOut::DoGetOut( void )
{
mPanic = !mpCharacter->GetTargetVehicle() || mpCharacter->GetTargetVehicle()->mVehicleDestroyed;
bool mIsDriver;
if(mpCharacter->GetTargetVehicle())
{
mIsDriver = (mpCharacter->GetTargetVehicle()->mpDriver == mpCharacter) ||
((mpCharacter->GetTargetVehicle()->mVehicleType != VT_TRAFFIC) &&
(mpCharacter->GetTargetVehicle()->mpDriver == NULL));
}
else
{
mIsDriver = false;
}
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
if(mPanic)
{
mpCharacter->AddToWorldScene();
if(mpCharacter->GetRole() == Character::ROLE_DRIVER)
{
GetCharacterManager()->SetGarbage(mpCharacter, true);
}
mpCharacter->SetFacingDir( mIsDriver ? (rmt::PI / 2) : -(rmt::PI / 2));
mpCharacter->SetDesiredDir( mIsDriver ? (rmt::PI / 2) : -(rmt::PI / 2));
pSeq->BeginSequence();
pSeq->AddAction( new DelayAction(0.5f));
pSeq->EndSequence( );
pSeq->BeginSequence();
pSeq->AddAction( new GroundSnap(mpCharacter));
pSeq->EndSequence( );
pSeq->BeginSequence();
pSeq->AddAction( new ChangeLocomotion(mpCharacter, ChangeLocomotion::WALKING) );
pSeq->EndSequence( );
pSeq->BeginSequence();
pSeq->AddAction( new DodgeAction(mpCharacter) );
pSeq->EndSequence( );
pSeq->BeginSequence();
pSeq->AddAction( new ChangeState<Loco>(mpCharacter));
pSeq->AddAction( new TriggerEventAction(EVENT_GETOUTOFVEHICLE_END, mpCharacter));
pSeq->EndSequence( );
}
else
{
int isDriver = mpCharacter->GetTargetVehicle()->HasDriver() ? 0 : 1;
Vehicle::Door door = isDriver ? Vehicle::DOOR_DRIVER : Vehicle::DOOR_PASSENGER;
Action* pAction = 0;
mpCharacter->GetTargetVehicle()->UpdateDoorState();
bool high = true;
rmt::Vector seat;
if(isDriver)
{
high = mpCharacter->GetTargetVehicle()->GetDriverLocation().y > CharacterTune::sGetInHeightThreshold;
seat = mpCharacter->GetTargetVehicle()->GetDriverLocation();
}
else
{
high = mpCharacter->GetTargetVehicle()->GetPassengerLocation().y > CharacterTune::sGetInHeightThreshold;
seat = mpCharacter->GetTargetVehicle()->GetPassengerLocation();
}
const char** anims = NULL;
if(high)
{
if(isDriver)
{
anims = sGetOutHighDriver;
}
else
{
anims = sGetOutHighPassenger;
}
}
else
{
if(isDriver)
{
anims = sGetOutDriver;
}
else
{
anims = sGetOutPassenger;
}
}
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
pSeq->AddAction( new DelayAction(0.1f));
pSeq->EndSequence( );
pSeq->BeginSequence();
pSeq->AddAction( new Position(mpCharacter, seat, 0.0f, true));
pSeq->EndSequence( );
// Play get_out_of_car_open_door
if(mpCharacter->GetTargetVehicle()->NeedToOpenDoor(door))
{
float delay = CharacterTune::sGetOutOpenDelay;
float time = CharacterTune::sGetOutOpenSpeed;
float scale = 30.0f / CharacterTune::sfGetInOutOfCarAnimSpeed;
pSeq->BeginSequence();
pAction = new PlayAnimationAction( mpCharacter, anims[ 0 ], CharacterTune::sfGetInOutOfCarAnimSpeed );
pSeq->AddAction( new CarDoorAction(mpCharacter->GetTargetVehicle(), Vehicle::DOORACTION_OPEN, door, delay * scale, time * scale));
pSeq->AddAction( pAction );
pSeq->EndSequence( );
}
if(0)
{
pSeq->BeginSequence();
pSeq->AddAction( new DelayAction(2.0f));
pSeq->EndSequence( );
}
// Play get_out_of_car
//
pSeq->BeginSequence();
pSeq->AddAction( new ChangeLocomotion(mpCharacter, ChangeLocomotion::WALKING) );
pSeq->EndSequence( );
if(0)
{
pSeq->BeginSequence();
pSeq->AddAction( new DelayAction(0.5f));
pSeq->EndSequence( );
}
pSeq->BeginSequence();
pSeq->AddAction( new GroundSnap(mpCharacter));
pAction = new PlayAnimationAction( mpCharacter, anims[ 1 ], CharacterTune::sfGetInOutOfCarAnimSpeed);
pSeq->AddAction( pAction );
pSeq->EndSequence( );
if(0)
{
pSeq->BeginSequence();
pSeq->AddAction( new DelayAction(2.0f));
pSeq->EndSequence( );
}
pSeq->BeginSequence();
pSeq->AddAction( new ChangeState<Loco>(mpCharacter));
pSeq->AddAction( new TriggerEventAction(EVENT_GETOUTOFVEHICLE_END, mpCharacter));
// Play get_out_of_car_close_door
if(mpCharacter->GetTargetVehicle()->HasActiveDoor(door))
{
float delay = CharacterTune::sGetOutCloseDelay;
float time = CharacterTune::sGetOutCloseSpeed;
float scale = 30.0f / CharacterTune::sfGetInOutOfCarAnimSpeed;
PlayAnimationAction* pAction = new PlayAnimationAction( mpCharacter, anims [ 2 ], CharacterTune::sfGetInOutOfCarAnimSpeed);
pAction->AbortWhenMovementOccurs(true);
pSeq->AddAction( new CarDoorAction(mpCharacter->GetTargetVehicle(), Vehicle::DOORACTION_CLOSE, door, delay * scale, time * scale, mpCharacter, pSeq));
pSeq->AddAction( pAction );
}
pSeq->EndSequence( );
}
}
/*
==============================================================================
InSim::InSim
==============================================================================
Description: Comment
Parameters( Character* pCharacter )
Returns:
=============================================================================
*/
InSim::InSim( Character* pCharacter )
:
State( pCharacter )
{
}
InSim::~InSim( void )
{
}
void InSim::Enter( void )
{
// clear previous actions
mpCharacter->GetActionController()->Clear();
// Sequence in the flail and get-up actions
Sequencer* pSeq = mpCharacter->GetActionController()->GetNextSequencer();
pSeq->BeginSequence();
pSeq->AddAction( new FlailAction( mpCharacter ) );
pSeq->EndSequence();
pSeq->BeginSequence();
pSeq->AddAction( new GetUpAction( mpCharacter ) );
pSeq->EndSequence();
/*
pSeq->BeginSequence();
pSeq->AddAction( new ChangeState<Loco>( mpCharacter ) );
pSeq->EndSequence();
*/
return;
}
void InSim::Exit( void )
{
}
void InSim::SequenceAction( void )
{
// SequenceAction gets called when no other actions are left to do.
// In this state, it means that we're just done "getting up"...
// so time to transit back to Loco state...
mpCharacter->GetStateManager()->SetState<Loco>();
}
void InSim::Update( float timeins )
{
}
};