mirror of
https://github.com/UberGames/EF2GameSource.git
synced 2024-11-10 06:31:42 +00:00
2830 lines
69 KiB
C++
2830 lines
69 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Logfile:: /EF2/Code/DLLs/game/CinematicArmature.cpp $
|
|
// $Revision:: 44 $
|
|
// $Author:: Singlis $
|
|
// $Date:: 9/26/03 2:36p $
|
|
//
|
|
// Copyright (C) 2002 by Ritual Entertainment, Inc.
|
|
// All rights reserved.
|
|
//
|
|
// This source is may not be distributed and/or modified without
|
|
// expressly written permission by Ritual Entertainment, Inc.
|
|
//
|
|
// DESCRIPTION:
|
|
// Implementation of Cinematic Armature classes.
|
|
//
|
|
|
|
#include "_pch_cpp.h"
|
|
#include "CinematicArmature.h"
|
|
|
|
bool CinematicArmature::_debug = false ;
|
|
|
|
//----------------------------------------------------------------
|
|
// C I N E M A T I C A R M A T U R E
|
|
//----------------------------------------------------------------
|
|
CinematicArmature theCinematicArmature ;
|
|
|
|
Event EV_CinematicArmature_PlayCinematic
|
|
(
|
|
"playCinematic",
|
|
EV_CONSOLE | EV_SCRIPTONLY,
|
|
"sS",
|
|
"cinematic originname",
|
|
"Play the current cinematic or the specified one once."
|
|
);
|
|
Event EV_CinematicArmature_PlayCinematicAt
|
|
(
|
|
"playCinematicAt",
|
|
EV_CONSOLE | EV_SCRIPTONLY,
|
|
"sVF",
|
|
"cinematic origin yaw",
|
|
"Play a cinematic at the specified origin with optional yaw rotatioin."
|
|
);
|
|
Event EV_CinematicArmature_Debug
|
|
(
|
|
"debug",
|
|
EV_CONSOLE | EV_SCRIPTONLY,
|
|
NULL,
|
|
NULL,
|
|
"Turns on debugging information for cinematics."
|
|
);
|
|
|
|
CLASS_DECLARATION( Listener, CinematicArmature, NULL )
|
|
{
|
|
{ &EV_CinematicArmature_PlayCinematic, &CinematicArmature::playCinematic },
|
|
{ &EV_CinematicArmature_PlayCinematicAt, &CinematicArmature::playCinematicAt },
|
|
{ &EV_CinematicArmature_Debug, &CinematicArmature::debugCinematics },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
//===============================================================
|
|
// Name: CinematicArmature
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Constructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
CinematicArmature::CinematicArmature() :
|
|
_cinematic( NULL )
|
|
{
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: ~CinematicArmature
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Destructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
CinematicArmature::~CinematicArmature( void )
|
|
{
|
|
deleteAllCinematics();
|
|
_cinematicList.FreeObjectList();
|
|
_cinematic = NULL ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: deleteAllCinematics
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Deletes all the cinematics currently in the
|
|
// list.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicArmature::deleteAllCinematics( void )
|
|
{
|
|
int numCinematics = _cinematicList.NumObjects();
|
|
for (int cinematicIdx = 1; cinematicIdx <= numCinematics; cinematicIdx++)
|
|
{
|
|
Cinematic *cinematic = _cinematicList.ObjectAt(cinematicIdx);
|
|
delete cinematic ;
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: clearCinematicsList
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Removes all the outstanding cinematics in the
|
|
// list. Leaves the mediocre ones.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicArmature::clearCinematicsList( void )
|
|
{
|
|
_cinematicList.ClearObjectList();
|
|
// deleteAllCinematics();
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: getCinematic
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Retrieves the cinematic with the specified name.
|
|
//
|
|
// Parameters: const str& -- name of the cinematic to retrieve.
|
|
//
|
|
// Returns: Cinematic* -- pointer to the specified cinematic.
|
|
// Returns 0 (NULL) if not found.
|
|
//
|
|
//===============================================================
|
|
Cinematic* CinematicArmature::getCinematicByName( const str &cinematicName )
|
|
{
|
|
int numCinematics = _cinematicList.NumObjects();
|
|
for (int cinematicIndex = 1; cinematicIndex <= numCinematics; cinematicIndex++)
|
|
{
|
|
Cinematic *cinematic = _cinematicList.ObjectAt(cinematicIndex);
|
|
if (cinematic->targetname == cinematicName)
|
|
return cinematic ;
|
|
}
|
|
return 0 ; // NULL
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: playCinematic
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Plays (starts) the specified cinematic. This
|
|
// event also loads the cinematic if it is not already
|
|
// loaded (where as start will give an error). This
|
|
// event is a shorthand for loading and starting a
|
|
// cinematic.
|
|
//
|
|
// Parameters: Event* -- EV_CinematicArmature_PlayCinematic
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicArmature::playCinematic( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() >= 1)
|
|
{
|
|
str cinematicName = ev->GetString( 1 );
|
|
_cinematic = getCinematicByName( cinematicName ) ;
|
|
if ( !_cinematic )
|
|
{
|
|
if ( !loadCinematic( cinematicName ))
|
|
{
|
|
ev->Error("playCinematic: Unable to load cinematic %s\n", cinematicName.c_str() );
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
else if ( !_cinematic )
|
|
{
|
|
ev->Error("startCinematic: No current cinematic to start!" );
|
|
return ;
|
|
}
|
|
|
|
assert( _cinematic ) ;
|
|
|
|
str originName ;
|
|
if ( ev->NumArgs() == 2 )
|
|
{
|
|
originName = ev->GetString( 2 );
|
|
}
|
|
|
|
_cinematic->startAtNamedOrigin( originName );
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: playCinematicAt
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Plays a cinematic at a dynamically specified origin
|
|
// and yaw rotation.
|
|
//
|
|
// Parameters: Event* -- EV_CinematicArmature_PlayCinematicAt
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicArmature::playCinematicAt( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() >= 1)
|
|
{
|
|
str cinematicName = ev->GetString( 1 );
|
|
_cinematic = getCinematicByName( cinematicName ) ;
|
|
if ( !_cinematic )
|
|
{
|
|
if ( !loadCinematic( cinematicName ))
|
|
{
|
|
ev->Error("playCinematicat: Unable to load cinematic %s\n", cinematicName.c_str() );
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
else if ( !_cinematic )
|
|
{
|
|
ev->Error("playCinematicat: No current cinematic to start!" );
|
|
return ;
|
|
}
|
|
|
|
assert( _cinematic ) ;
|
|
Vector origin( 0.0f, 0.0f, 0.0f ) ;
|
|
float yaw = 0.0f ;
|
|
|
|
if ( ev->NumArgs() >= 2 )
|
|
{
|
|
origin = ev->GetVector( 2 );
|
|
}
|
|
|
|
if ( ev->NumArgs() == 3 )
|
|
{
|
|
yaw = ev->GetFloat( 3 );
|
|
}
|
|
|
|
_cinematic->startAtOrigin( origin, yaw );
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: loadCinematic
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Loads a cinematic from disk. This will always
|
|
// reload the cinematic.
|
|
//
|
|
// Parameters: const str& -- name of the cinematic to load (.cin file)
|
|
//
|
|
// Returns: bool -- true if load was successful.
|
|
//
|
|
//===============================================================
|
|
bool CinematicArmature::loadCinematic( const str &cinematicName )
|
|
{
|
|
CinematicPtr cinematic = 0 ;
|
|
str filename;
|
|
|
|
filename = "cins/";
|
|
filename += cinematicName ;
|
|
filename += ".cin";
|
|
|
|
cinematic = new Cinematic ( filename );
|
|
if ( !cinematic->load() )
|
|
{
|
|
return false ;
|
|
}
|
|
|
|
_cinematicList.AddObject(cinematic);
|
|
_cinematic = cinematic ; // current cinematic gets set
|
|
|
|
return true ;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: debugCinematics
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Toggles debugging info on cinematics
|
|
//
|
|
// Parameters: Event * -- not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicArmature::debugCinematics( Event * )
|
|
{
|
|
_debug = !_debug ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: createCinematic
|
|
// Class: CinematicArmature
|
|
//
|
|
// Description: Creates a new cinematic and returns it. The cinematic
|
|
// created is loaded from the .cin file with the same
|
|
// name.
|
|
//
|
|
// Parameters: const str &cinematicName
|
|
//
|
|
// Returns: Cinematic* -- the Cinematic created. If the
|
|
// cinematic isn't found, returns 0.
|
|
//
|
|
//===============================================================
|
|
Cinematic* CinematicArmature::createCinematic( const str &cinematicName )
|
|
{
|
|
if ( loadCinematic( cinematicName ) )
|
|
{
|
|
return _cinematic ;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
// C I N E M A T I C A C T O R
|
|
//---------------------------------------------------------------
|
|
CLASS_DECLARATION( Listener, CinematicActor, NULL )
|
|
{
|
|
{ &EV_Actor_ControlLost, &CinematicActor::actorControlLostEvent },
|
|
{ &EV_Actor_BehaviorFinished, &CinematicActor::actorBehaviorFinishedEvent },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
//===============================================================
|
|
// Name: CinematicActor
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Constructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
CinematicActor::CinematicActor( void ) :
|
|
_name(""),
|
|
_tiki(""),
|
|
_anim(""),
|
|
_moveAnim("walk"),
|
|
_snapToSpot( false ),
|
|
_ignorePain( true ),
|
|
_ignoreSight( true ),
|
|
_ignoreSound( true ),
|
|
_origin(0.0f, 0.0f, 0.0f),
|
|
_yaw( 0.0f ),
|
|
_isAtSpot( false ),
|
|
_isAnimDone( false ),
|
|
_hasActorControl( false ),
|
|
_rootActor( false ),
|
|
_removeAfter( false ),
|
|
_afterBehavior( CINEMATIC_ACTOR_AFTER_BEHAVIOR_LEAVE_WITH_AI ),
|
|
_state( CINEMATIC_ACTOR_STATE_INACTIVE ),
|
|
_actor( 0 )
|
|
{
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: reset
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Resets the internal state of the actor to what it
|
|
// is before a cinematic begins. Useful for ensuring
|
|
// that the cinematic can be replayed correctly.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::reset( void )
|
|
{
|
|
_state = CINEMATIC_ACTOR_STATE_INACTIVE ;
|
|
_hasActorControl = false ;
|
|
_isAtSpot = false ;
|
|
_isAnimDone = false ;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: setAnim
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Sets the animation for this actor. Also caches
|
|
// the animation.
|
|
//
|
|
// Parameters: const str& -- the animation name.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::setAnim( const str &anim )
|
|
{
|
|
_anim = anim ;
|
|
CacheResource( _anim );
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: setAfterBehavior
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Sets the behavior enumeration from the specified
|
|
// string for the actor. The after behavior controls
|
|
// what the actor does after the cinematic completes.
|
|
//
|
|
// Parameters: const str& -- string description of after behaviors.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::setAfterBehavior( const str &actorBehaviorName )
|
|
{
|
|
if ( actorBehaviorName == "REMOVE" )
|
|
{
|
|
_afterBehavior = CINEMATIC_ACTOR_AFTER_BEHAVIOR_REMOVE_FROM_GAME ;
|
|
_removeAfter = true ;
|
|
}
|
|
else if ( actorBehaviorName == "LEAVE" || actorBehaviorName == "AI" ) // for legacy reasons, leave means leave with ai
|
|
{
|
|
_afterBehavior = CINEMATIC_ACTOR_AFTER_BEHAVIOR_LEAVE_WITH_AI ;
|
|
}
|
|
else if ( actorBehaviorName == "NOAI" )
|
|
{
|
|
_afterBehavior = CINEMATIC_ACTOR_AFTER_BEHAVIOR_LEAVE_NO_AI ;
|
|
}
|
|
else if ( actorBehaviorName == "FREEZE" )
|
|
{
|
|
_afterBehavior = CINEMATIC_ACTOR_AFTER_BEHAVIOR_LEAVE_FREEZE ;
|
|
}
|
|
else if ( actorBehaviorName == "KILL" )
|
|
{
|
|
_afterBehavior = CINEMATIC_ACTOR_AFTER_BEHAVIOR_KILL ;
|
|
}
|
|
else // for legacy reasons default is to kill them.
|
|
{
|
|
_afterBehavior = CINEMATIC_ACTOR_AFTER_BEHAVIOR_KILL ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: handleControlLostEvent
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Handles the EV_Actor_ControlLost event.
|
|
// This disables the control flag.
|
|
//
|
|
// Parameters: Event* -- the event caught
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::actorControlLostEvent( Event * )
|
|
{
|
|
_hasActorControl = false ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: actorBehaviorFinishedEvent
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Handles the EV_Actor_BehaviorFinished event.
|
|
// Snaps the actor to the final origin.
|
|
//
|
|
// Parameters: Event* -- the event that triggered this function.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::actorBehaviorFinishedEvent( Event * )
|
|
{
|
|
assert( _actor );
|
|
|
|
switch ( _state )
|
|
{
|
|
case CINEMATIC_ACTOR_STATE_MOVING:
|
|
_actor->setOrigin( _origin );
|
|
_turnActor( true );
|
|
break ;
|
|
case CINEMATIC_ACTOR_STATE_TURNING:
|
|
_isAtSpot = true ;
|
|
_state = CINEMATIC_ACTOR_STATE_PLAYING ;
|
|
break ;
|
|
case CINEMATIC_ACTOR_STATE_PLAYING:
|
|
_isAnimDone = true ;
|
|
_state = CINEMATIC_ACTOR_STATE_FINISHED ;
|
|
break ;
|
|
default:
|
|
// if its not one of the above, probably something
|
|
// has gone terribly wrong (actor killed) and we need
|
|
// to mark this CinematicActor as no longer available.
|
|
break ;
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: turnActor
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Turns the actor to face the starting orientation.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::_turnActor( bool useAnims )
|
|
{
|
|
assert( _actor );
|
|
|
|
Event *ev = new Event( EV_Actor_TurnTo );
|
|
ev->AddFloat( _yaw );
|
|
ev->AddInteger( useAnims );
|
|
_actor->PostEvent( ev, 0.0f );
|
|
_state = CINEMATIC_ACTOR_STATE_TURNING ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: locateActor
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Locates or spawns the real actor. If the actor
|
|
// is not already around, spawns a new one.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::_locateActor( void )
|
|
{
|
|
if ( !_alwaysSpawn )
|
|
{
|
|
if ( _actor ) return ;
|
|
_actor = Actor::FindActorByName( _name );
|
|
}
|
|
else
|
|
{
|
|
_actor = 0 ;
|
|
}
|
|
|
|
if ( !_actor || _actor->checkActorDead() )
|
|
{
|
|
_spawn();
|
|
_isAtSpot = true ;
|
|
}
|
|
|
|
assert( _actor );
|
|
if ( !_actor)
|
|
{
|
|
gi.Error( ERR_DROP, "Unable to locate or spawn cinematic actor %s\n", _name.c_str() );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: takeControlOfActor
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Takes control of the actor. Turns off AI. Sets
|
|
// the stimuli the actor responds to.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::takeControlOfActor( const Vector &origin, float yaw )
|
|
{
|
|
Event *ev = 0 ;
|
|
|
|
_origin = origin + _originOffset ;
|
|
_yaw = yaw + _yawOffset ;
|
|
|
|
_locateActor();
|
|
_actor->TurnAIOff();
|
|
_actor->RequestControl( this, Actor::ACTOR_CONTROL_LOCKED );
|
|
|
|
ev = new Event( EV_Actor_RespondTo );
|
|
ev->AddString( "pain" );
|
|
ev->AddInteger( doesIgnorePain() ? 0 : 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_PermanentlyRespondTo );
|
|
ev->AddString( "pain" );
|
|
ev->AddInteger( doesIgnorePain() ? 0 : 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_RespondTo );
|
|
ev->AddString( "sight" );
|
|
ev->AddInteger( doesIgnoreSight() ? 0 : 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_PermanentlyRespondTo );
|
|
ev->AddString( "sight" );
|
|
ev->AddInteger( doesIgnoreSight() ? 0 : 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_RespondTo );
|
|
ev->AddString( "sound" );
|
|
ev->AddInteger( doesIgnoreSound() ? 0 : 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_PermanentlyRespondTo );
|
|
ev->AddString( "sound" );
|
|
ev->AddInteger( doesIgnoreSound() ? 0 : 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
_actor->edict->svflags |= SVF_BROADCAST;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: releaseControlOfActor
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Releases control of the actor and turns AI
|
|
// back on.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::releaseControlOfActor( void )
|
|
{
|
|
assert( _actor );
|
|
Event *ev = 0 ;
|
|
|
|
_actor->ReleaseControl( this );
|
|
|
|
_actor->edict->svflags &= ~SVF_BROADCAST;
|
|
|
|
switch ( _afterBehavior )
|
|
{
|
|
case CINEMATIC_ACTOR_AFTER_BEHAVIOR_REMOVE_FROM_GAME:
|
|
_actor->ProcessEvent( EV_Remove );
|
|
_actor = 0 ;
|
|
break ;
|
|
|
|
case CINEMATIC_ACTOR_AFTER_BEHAVIOR_LEAVE_FREEZE:
|
|
ev = new Event( EV_Actor_SetStickToGround );
|
|
ev->AddInteger( 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetSimplifiedThink ) ;
|
|
ev->AddInteger( 0 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetUseGravity );
|
|
ev->AddInteger( 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetMovementMode );
|
|
ev->AddString( "normal" );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
// This little magic freeze the current animation on the
|
|
// last frame of the cinematic anim. This is intended
|
|
// for cinematics which need to appear to pause at
|
|
// the end (like for a dialog choice).
|
|
|
|
if ( _actor->edict->s.torso_anim & ANIM_BLEND )
|
|
_actor->animate->StopAnimatingAtEnd( torso );
|
|
|
|
if ( _actor->edict->s.anim & ANIM_BLEND )
|
|
_actor->animate->StopAnimatingAtEnd( legs );
|
|
|
|
break ;
|
|
|
|
case CINEMATIC_ACTOR_AFTER_BEHAVIOR_LEAVE_NO_AI:
|
|
ev = new Event( EV_Actor_SetStickToGround );
|
|
ev->AddInteger( 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetSimplifiedThink ) ;
|
|
ev->AddInteger( 0 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetUseGravity );
|
|
ev->AddInteger( 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetMovementMode );
|
|
ev->AddString( "normal" );
|
|
_actor->ProcessEvent( ev );
|
|
break ;
|
|
|
|
case CINEMATIC_ACTOR_AFTER_BEHAVIOR_LEAVE_WITH_AI:
|
|
ev = new Event( EV_Actor_SetStickToGround );
|
|
ev->AddInteger( 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetSimplifiedThink ) ;
|
|
ev->AddInteger( 0 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetUseGravity );
|
|
ev->AddInteger( 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetMovementMode );
|
|
ev->AddString( "normal" );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
_actor->TurnAIOn();
|
|
break ;
|
|
|
|
case CINEMATIC_ACTOR_AFTER_BEHAVIOR_KILL:
|
|
_actor->ProcessEvent( EV_Actor_Dead );
|
|
_actor = 0 ;
|
|
break ;
|
|
|
|
default:
|
|
break ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: getToPosition
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Moves a cinematic actor to their starting spot
|
|
// for a cinematic.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::getToPosition( void )
|
|
{
|
|
if ( !doesSnapToSpot() && !isAtSpot() )
|
|
{
|
|
// Move to our starting spot
|
|
Event *ev = new Event( EV_Actor_WalkTo );
|
|
ev->AddVector( _origin );
|
|
ev->AddString( _moveAnim );
|
|
_actor->PostEvent( ev, 0.1f );
|
|
_state = CINEMATIC_ACTOR_STATE_MOVING ;
|
|
}
|
|
else if ( !isAtSpot() )
|
|
{
|
|
_actor->setOrigin( _origin );
|
|
_actor->NoLerpThisFrame();
|
|
_turnActor( !doesSnapToSpot() );
|
|
}
|
|
else
|
|
{
|
|
_turnActor( !doesSnapToSpot() );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: spawn
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Spawns an actor with the specified tiki.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::_spawn( void )
|
|
{
|
|
ClassDef *cls;
|
|
Event *ev;
|
|
SpawnArgs args;
|
|
|
|
if ( !strstr( _tiki.c_str(), ".tik" ) )
|
|
{
|
|
_tiki += ".tik";
|
|
}
|
|
|
|
args.setArg( "model", _tiki.c_str() );
|
|
cls = args.getClassDef();
|
|
|
|
if ( !cls || !checkInheritance( &Actor::ClassInfo, cls ) )
|
|
{
|
|
gi.Error(ERR_DROP, "%s is not a valid Actor", _tiki.c_str() );
|
|
return;
|
|
}
|
|
|
|
_actor = ( Actor* )cls->newInstance();
|
|
|
|
ev = new Event( EV_Model );
|
|
ev->AddString( _tiki.c_str() );
|
|
_actor->ProcessEvent( ev ); //, EV_SPAWNARG );
|
|
|
|
ev = new Event( EV_SetOrigin );
|
|
ev->AddVector( _origin );
|
|
_actor->ProcessEvent( ev ); //, EV_SPAWNARG );
|
|
|
|
ev = new Event( EV_SetAngles );
|
|
ev->AddVector( Vector( 0.0f, _yaw, 0.0f ) );
|
|
_actor->ProcessEvent( ev ); //, EV_SPAWNARG );
|
|
|
|
ev = new Event( EV_Actor_SetUseGravity );
|
|
ev->AddInteger( 0 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
_actor->SetTargetName( _name.c_str() );
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: playAnimation
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Kicks off this actor's cinematic animation as
|
|
// specified in the cinematic file.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::playAnimation( void )
|
|
{
|
|
Event *ev ;
|
|
_actor->velocity = Vector::Identity();
|
|
|
|
ev = new Event( EV_Actor_SetUseGravity );
|
|
ev->AddInteger( 0 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
|
|
ev = new Event( EV_Actor_SetSimplifiedThink ) ;
|
|
ev->AddInteger( 1 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetStickToGround );
|
|
ev->AddInteger( 0 );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_SetMovementMode );
|
|
ev->AddString( "anim" );
|
|
_actor->ProcessEvent( ev );
|
|
|
|
ev = new Event( EV_Actor_Anim );
|
|
ev->AddString( _anim );
|
|
_actor->ProcessEvent( ev );
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: debug
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Draws a debug box around the actor's origin.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicActor::debug( void )
|
|
{
|
|
G_DrawXYBox( _origin, 8.0f, 0.8f, 0.6f, 0.3f, 1.0f );
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parse
|
|
// Class: CinematicActor
|
|
//
|
|
// Description: Parses the data for an actor out of the specified
|
|
// Cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed. We
|
|
// depend on being at the start of the
|
|
// actor data (after the opening).
|
|
//
|
|
// Returns: bool -- true upon success
|
|
//
|
|
//===============================================================
|
|
bool CinematicActor::parse( Script &cinematicFile )
|
|
{
|
|
const char *token = cinematicFile.GetToken( false );
|
|
Vector origin;
|
|
|
|
while ( token )
|
|
{
|
|
if ( stricmp( token, "name" )==0 )
|
|
{
|
|
setName( cinematicFile.GetString( false ) );
|
|
}
|
|
else if ( stricmp( token, "tiki" )==0 )
|
|
{
|
|
setTiki( cinematicFile.GetString( false ) );
|
|
}
|
|
else if ( stricmp( token, "anim" )==0 )
|
|
{
|
|
setAnim( cinematicFile.GetString( false ) );
|
|
}
|
|
else if ( stricmp( token, "origin")==0 )
|
|
{
|
|
setOriginOffset( cinematicFile.GetVector( false ) );
|
|
}
|
|
else if ( stricmp( token, "yaw" )==0 )
|
|
{
|
|
setYawOffset( cinematicFile.GetFloat( false ) );
|
|
}
|
|
else if ( stricmp( token, "moveanim" )==0 )
|
|
{
|
|
setMoveAnim( cinematicFile.GetString( false ) );
|
|
}
|
|
else if ( stricmp( token, "snap" )==0 )
|
|
{
|
|
setSnapToSpot( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
else if ( stricmp( token, "nopain" )==0 )
|
|
{
|
|
setIgnorePain( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
else if ( stricmp( token, "nosight")==0 )
|
|
{
|
|
setIgnoreSight( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
else if ( stricmp( token, "nosound")== 0 )
|
|
{
|
|
setIgnoreSound( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
else if ( stricmp( token, "removeAfter") == 0 )
|
|
{
|
|
setRemoveAfter( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
else if ( stricmp( token, "rootActor" ) == 0 )
|
|
{
|
|
setRootActor( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
else if ( stricmp( token, "afterBehavior") == 0 )
|
|
{
|
|
setAfterBehavior( cinematicFile.GetToken( false ) );
|
|
}
|
|
else if ( stricmp( token, "alwaysSpawn" ) == 0 )
|
|
{
|
|
setAlwaysSpawn( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
else if (stricmp( token, "}")==0 )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
token = cinematicFile.GetToken( true );
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
// C I N E M A T I C C A M E R A
|
|
//---------------------------------------------------------------
|
|
Event EV_CinematicCamera_StopPlaying
|
|
(
|
|
"cinematicCameraStopPlaying",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Stops a cinematic camera."
|
|
);
|
|
|
|
|
|
CLASS_DECLARATION( Listener, CinematicCamera, NULL )
|
|
{
|
|
{ &EV_CinematicCamera_StopPlaying, &CinematicCamera::_handleStopPlayingEvent },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
//===============================================================
|
|
// Name: CinematicCamera
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Constructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
CinematicCamera::CinematicCamera( void ) :
|
|
_moveType( CAMERA_MOVE_TYPE_FOLLOW_ANIM ),
|
|
_lookType( CAMERA_LOOK_TYPE_WATCH_ANIM ),
|
|
_camera( 0 ),
|
|
_playing( false ),
|
|
_selfRemoving( true ),
|
|
_name( "" ),
|
|
_camFile( "" ),
|
|
_moveActor( "" ),
|
|
_lookActor( "" ),
|
|
_originOffset( 0.0f, 0.0f, 0.0f ),
|
|
_yawOffset( 0.0f )
|
|
{
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: setMoveType
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Sets the movement type of a cinematic camera.
|
|
// Sets it by string value. The movement type
|
|
// determines how this camera moves during the
|
|
// cinematic.
|
|
//
|
|
// Parameters: const str& -- the string version of a movement type.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::setMoveType( const str &moveType )
|
|
{
|
|
if ( moveType == "STATIC" )
|
|
{
|
|
_moveType = CAMERA_MOVE_TYPE_STATIC ;
|
|
}
|
|
else if ( moveType == "ANIM" )
|
|
{
|
|
_moveType = CAMERA_MOVE_TYPE_FOLLOW_ANIM ;
|
|
}
|
|
else if ( moveType == "PLAYER" )
|
|
{
|
|
_moveType = CAMERA_MOVE_TYPE_FOLLOW_PLAYER ;
|
|
}
|
|
else if ( moveType == "ACTOR" )
|
|
{
|
|
_moveType = CAMERA_MOVE_TYPE_FOLLOW_ACTOR ;
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: setLookType
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Sets the look type of a cinematic camera.
|
|
// Sets it by string value. The look type
|
|
// determines how this camera watches during the
|
|
// cinematic.
|
|
//
|
|
// Parameters: const str& -- the string version of a look type.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::setLookType( const str &lookType )
|
|
{
|
|
if ( lookType == "ANIM" )
|
|
{
|
|
_lookType = CAMERA_LOOK_TYPE_WATCH_ANIM ;
|
|
}
|
|
else if ( lookType == "PLAYER" )
|
|
{
|
|
_lookType = CAMERA_LOOK_TYPE_WATCH_PLAYER ;
|
|
}
|
|
else if ( lookType == "ACTOR" )
|
|
{
|
|
_lookType = CAMERA_LOOK_TYPE_WATCH_ACTOR ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: startMoving
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Starts the camera moving along its path
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::start( void )
|
|
{
|
|
_playing = true ;
|
|
_camera->PostEvent( EV_Camera_CameraThink, FRAMETIME );
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: cut
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Cues this camera for playing.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::cut( void )
|
|
{
|
|
_camera->Cut( NULL );
|
|
SetCamera( _camera, 0.0f ); // switch time
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: reset
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Resets the internal state of the camera back to
|
|
// the start. Currently this doesn't do much.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::reset( void )
|
|
{
|
|
_playing = false ;
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: takeControlOfCamera
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Takes control of the camera.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::takeControlOfCamera( const Vector &origin, float yaw )
|
|
{
|
|
_locateCamera();
|
|
_camera->SetPlaybackOffsets( _yawOffset + yaw, _originOffset + origin );
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: releaseControlOfCamera
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Release the camera
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::releaseControlOfCamera( void )
|
|
{
|
|
if ( !_camera) return ;
|
|
|
|
CancelPendingEvents();
|
|
if ( isSelfRemoving() )
|
|
{
|
|
_camera->PostEvent( EV_Remove, 0.0f );
|
|
}
|
|
_camera = 0 ;
|
|
_playing = 0 ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: _locateCamera
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Locates or spawns the real camera. If the camera
|
|
// is not already around, spawns a new one.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::_locateCamera( void )
|
|
{
|
|
if ( _camera ) return ;
|
|
|
|
if ( !_camera )
|
|
{
|
|
_spawn();
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: _spawn
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Spawns a camera with the specified tiki.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::_spawn( void )
|
|
{
|
|
_camera = new Camera ;
|
|
assert( _camera );
|
|
|
|
str cameraName( _name );
|
|
cameraName += "Camera" ;
|
|
|
|
_camera->SetTargetName( cameraName.c_str() );
|
|
_camera->ProcessPendingEvents();
|
|
if ( _moveType == CAMERA_MOVE_TYPE_FOLLOW_ANIM )
|
|
{
|
|
Event *event = new Event( EV_Camera_LoadKFC );
|
|
event->AddString( _camFile );
|
|
_camera->ProcessEvent( event );
|
|
|
|
float pathLengthInSeconds = _camera->GetPathLengthInSeconds();
|
|
event = new Event( EV_CinematicCamera_StopPlaying );
|
|
PostEvent( event, pathLengthInSeconds );
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: _handleStopPlayingEvent
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Handles the stop playing event. This event tells
|
|
// the camara that it is done playing its cinematic
|
|
// sequence.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCamera::_handleStopPlayingEvent( Event * )
|
|
{
|
|
_playing = false ;
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: parse
|
|
// Class: CinematicCamera
|
|
//
|
|
// Description: Parses the data for a camera out of the specified
|
|
// Cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed. We
|
|
// depend on being at the start of the
|
|
// camera data (after the opening).
|
|
//
|
|
// Returns: bool -- true upon success
|
|
//
|
|
//===============================================================
|
|
bool CinematicCamera::parse( Script &cinematicFile )
|
|
{
|
|
const char *token = cinematicFile.GetToken( false );
|
|
|
|
while ( token )
|
|
{
|
|
if ( stricmp( token, "name" )==0 )
|
|
{
|
|
token = cinematicFile.GetString( false );
|
|
setName( token );
|
|
}
|
|
else if ( stricmp( token, "camfile" )==0 )
|
|
{
|
|
token = cinematicFile.GetString( false );
|
|
setCamFile( token );
|
|
}
|
|
else if ( stricmp( token, "movetype" ) == 0 )
|
|
{
|
|
token = cinematicFile.GetString( false );
|
|
setMoveType( token );
|
|
}
|
|
else if ( stricmp( token, "looktype" ) == 0 )
|
|
{
|
|
token = cinematicFile.GetString( false );
|
|
setLookType( token );
|
|
}
|
|
else if ( stricmp( token, "moveactor" ) == 0 )
|
|
{
|
|
token = cinematicFile.GetString( false );
|
|
setMoveActor( token );
|
|
}
|
|
else if ( stricmp( token, "lookactor" ) == 0 )
|
|
{
|
|
token = cinematicFile.GetString( false );
|
|
setLookActor( token );
|
|
}
|
|
else if ( stricmp( token, "origin" ) == 0 )
|
|
{
|
|
setOriginOffset( cinematicFile.GetVector( false ) );
|
|
}
|
|
else if ( stricmp( token, "yaw" ) == 0 )
|
|
{
|
|
setYawOffset( cinematicFile.GetFloat( false ) ) ;
|
|
}
|
|
else if ( stricmp( token, "selfRemoving" ) == 0 )
|
|
{
|
|
setSelfRemovingFlag( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
else if (stricmp( token, "}")==0 )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
token = cinematicFile.GetToken( true );
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
// C I N E M A T I C C U T
|
|
//---------------------------------------------------------------
|
|
Event EV_CinematicCut_FadeOut
|
|
(
|
|
"cinematiccutfadeout",
|
|
EV_CODEONLY,
|
|
"",
|
|
"",
|
|
"Fades out leading to a cinematic camera cut."
|
|
);
|
|
Event EV_CinematicCut_Cut
|
|
(
|
|
"cinematiccut",
|
|
EV_CODEONLY,
|
|
"",
|
|
"",
|
|
"Makes a cinematic camera cut."
|
|
);
|
|
|
|
CLASS_DECLARATION( Listener, CinematicCut, NULL )
|
|
{
|
|
{ &EV_CinematicCut_FadeOut, &CinematicCut::_handleFadeOutEvent },
|
|
{ &EV_CinematicCut_Cut, &CinematicCut::_handleCutEvent },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
//===============================================================
|
|
// Name: CinematicCut
|
|
// Class: CinematicCut
|
|
//
|
|
// Description: Constructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
CinematicCut::CinematicCut( void ) :
|
|
_cinematicCamera( 0 ),
|
|
_frame( 0 ),
|
|
_fadeOut( 0 ),
|
|
_fadeIn( 0 ),
|
|
_cameraName( "" )
|
|
{
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: cut
|
|
// Class: CinematicCut
|
|
//
|
|
// Description: Invokes this camera cut
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCut::postEvents( void )
|
|
{
|
|
Event *ev = 0 ;
|
|
|
|
if ( _fadeOut )
|
|
{
|
|
ev = new Event( EV_CinematicCut_FadeOut );
|
|
int fadeOutFrame = _frame - _fadeOut ;
|
|
PostEvent( ev, fadeOutFrame * 0.05 );
|
|
}
|
|
|
|
ev = new Event( EV_CinematicCut_Cut );
|
|
PostEvent( ev, _frame * 0.05 );
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: stop
|
|
// Class: CinematicCut
|
|
//
|
|
// Description: Cancels all outstanding events.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCut::stop( void )
|
|
{
|
|
CancelPendingEvents();
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: parse
|
|
// Class: CinematicCut
|
|
//
|
|
// Description: Parses the data for a cut out of the specified
|
|
// Cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed. We
|
|
// depend on being at the start of the
|
|
// cut block (after the opening).
|
|
//
|
|
// Returns: bool -- true upon success
|
|
//
|
|
//===============================================================
|
|
bool CinematicCut::parse( Script &cinematicFile )
|
|
{
|
|
const char *token = cinematicFile.GetToken( false );
|
|
bool lerp = false ;
|
|
int value = 0 ;
|
|
|
|
while ( token )
|
|
{
|
|
if ( stricmp( token, "toCamera" )==0 )
|
|
{
|
|
token = cinematicFile.GetString( false );
|
|
setCameraName( token );
|
|
}
|
|
else if ( stricmp( token, "fadeOut" )==0 )
|
|
{
|
|
value = cinematicFile.GetInteger( false );
|
|
setFadeOut( value );
|
|
}
|
|
else if ( stricmp( token, "fadeIn" ) == 0 )
|
|
{
|
|
value = cinematicFile.GetInteger( false );
|
|
setFadeIn( value );
|
|
}
|
|
else if ( stricmp( token, "frame" ) == 0 )
|
|
{
|
|
value = cinematicFile.GetInteger( false );
|
|
setFrame( value );
|
|
}
|
|
else if ( stricmp( token, "lerp" ) == 0 )
|
|
{
|
|
lerp = cinematicFile.GetBoolean( false ) ? true : false ;
|
|
setLerpFlag( lerp );
|
|
}
|
|
else if (stricmp( token, "}")==0 )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
token = cinematicFile.GetToken( true );
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
// P R O T E C T E D M E T H O D S
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
//===============================================================
|
|
// Name: handleFadeOutEvent
|
|
// Class: CinematicCut
|
|
//
|
|
// Description: Handles the EV_CinematicCut_FadeOut event. This
|
|
// triggers the fade out on the current camera, leading
|
|
// up to this camera cut.
|
|
//
|
|
// Parameters: Event* -- the event that triggered this call.
|
|
//
|
|
// Returns:
|
|
//
|
|
//===============================================================
|
|
void CinematicCut::_handleFadeOutEvent( Event * )
|
|
{
|
|
level.m_fade_color = Vector( 0.0f, 0.0f, 0.0f );
|
|
level.m_fade_time_start = _fadeOut * 0.05 ;
|
|
level.m_fade_time = _fadeOut * 0.05 ;
|
|
level.m_fade_alpha = 1.0f ;
|
|
level.m_fade_type = fadeout;
|
|
level.m_fade_style = alphablend;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: handleCutEvent
|
|
// Class: CinematicCut
|
|
//
|
|
// Description: Handles the EV_CinematicCut_Cut event. This
|
|
// triggers the actual camera cut, plus does the
|
|
// fade in if any specified.
|
|
//
|
|
// Parameters: Event* -- the event that triggered this call.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicCut::_handleCutEvent( Event * )
|
|
{
|
|
if ( _cinematicCamera )
|
|
{
|
|
_cinematicCamera->cut();
|
|
}
|
|
else
|
|
{
|
|
SetCamera( NULL, 0.0f );
|
|
}
|
|
|
|
if ( _fadeIn )
|
|
{
|
|
level.m_fade_color = Vector( 0.0f, 0.0f, 0.0f );
|
|
level.m_fade_time_start = _fadeIn * 0.05 ;
|
|
level.m_fade_time = _fadeIn * 0.05 ;
|
|
level.m_fade_alpha = 1.0f ;
|
|
level.m_fade_type = fadein ;
|
|
level.m_fade_style = alphablend ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
// C I N E M A T I C O R I G I N
|
|
//---------------------------------------------------------------
|
|
CLASS_DECLARATION( Listener, CinematicOrigin, NULL )
|
|
{
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
//===============================================================
|
|
// Name: CinematicOrigin
|
|
// Class: CinematicOrigin
|
|
//
|
|
// Description: Constructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
CinematicOrigin::CinematicOrigin( void ) :
|
|
_origin( 0.0f, 0.0f, 0.0f ),
|
|
_yaw( 0.0f ),
|
|
_name( "" )
|
|
{
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: debug
|
|
// Class: CinematicOrigin
|
|
//
|
|
// Description: Draws a debug box around this origin.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void CinematicOrigin::debug( void )
|
|
{
|
|
G_DrawXYBox( _origin, 8.0f, 0.8f, 0.6f, 0.8f, 1.0f );
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: parse
|
|
// Class: CinematicOrigin
|
|
//
|
|
// Description: Parses the data for an origin out of the specified
|
|
// Cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed. We
|
|
// depend on being at the start of the
|
|
// origin block (after the opening).
|
|
//
|
|
// Returns: bool -- true upon success
|
|
//
|
|
//===============================================================
|
|
bool CinematicOrigin::parse( Script &cinematicFile )
|
|
{
|
|
const char *token = cinematicFile.GetToken( false );
|
|
|
|
while ( token )
|
|
{
|
|
if ( stricmp( token, "name" )==0 )
|
|
{
|
|
setName( cinematicFile.GetString( false ) );
|
|
}
|
|
else if ( stricmp( token, "origin" )==0 )
|
|
{
|
|
setOrigin( cinematicFile.GetVector( false ) );
|
|
}
|
|
else if ( stricmp( token, "yaw" ) == 0 )
|
|
{
|
|
setYaw( cinematicFile.GetFloat( false ) );
|
|
}
|
|
else if (stricmp( token, "}")==0 )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
token = cinematicFile.GetToken( true );
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// C I N E M A T I C
|
|
//-----------------------------------------------------------
|
|
Event EV_Cinematic_Begin
|
|
(
|
|
"beginCinematic",
|
|
EV_DEFAULT,
|
|
"SB",
|
|
"originName callStartThreadFlag",
|
|
"Begins the cinematic at the specified named origin. If the"
|
|
"origin name isn't specified, begins at 0,0,0 with 0 degrees of yaw rotation."
|
|
);
|
|
|
|
Event EV_Cinematic_BeginAt
|
|
(
|
|
"beginCinematicAt",
|
|
EV_DEFAULT,
|
|
"VFB",
|
|
"originVector yawRotation callStartThreadFlag",
|
|
"Begins the cinematic at the specified origin with the specified rotation."
|
|
"If they are not specified, begins at 0,0,0 with 0 degrees of yaw rotation."
|
|
);
|
|
|
|
Event EV_Cinematic_End
|
|
(
|
|
"endCinematic",
|
|
EV_DEFAULT | EV_CONSOLE,
|
|
"B",
|
|
"callEndThreadFlag",
|
|
"Stop the cinematic."
|
|
);
|
|
|
|
Event EV_Cinematic_SetBeginThread
|
|
(
|
|
"setbeginthread",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"threadName",
|
|
"Sets the thread to call when the cinematic begins."
|
|
);
|
|
|
|
Event EV_Cinematic_SetEndThread
|
|
(
|
|
"setendthread",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"threadName",
|
|
"Sets the thread to call when the cinematic ends."
|
|
);
|
|
|
|
|
|
CLASS_DECLARATION( Entity, Cinematic, "cinematic" )
|
|
{
|
|
{ &EV_Cinematic_Begin, &Cinematic::handleBeginEvent },
|
|
{ &EV_Cinematic_BeginAt, &Cinematic::handleBeginAtEvent },
|
|
{ &EV_Cinematic_End, &Cinematic::handleEndEvent },
|
|
{ &EV_Cinematic_SetBeginThread, &Cinematic::handleSetBeginThreadEvent },
|
|
{ &EV_Cinematic_SetEndThread, &Cinematic::handleSetEndThreadEvent },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
//===============================================================
|
|
// Name: Cinematic
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Constructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
Cinematic::Cinematic( )
|
|
{
|
|
init();
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: Cinematic
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Constructor.
|
|
//
|
|
// Parameters: const str& -- filename of cinematic file.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
Cinematic::Cinematic( const str &filename ) :
|
|
_filename( filename),
|
|
_looping( false ),
|
|
_playing( false ),
|
|
_callStartThreadFlag( true ),
|
|
_resetCamera( true ),
|
|
_stage( CINEMATIC_STAGE_UNLOADED )
|
|
{
|
|
init();
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: ~Cinematic
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Destructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
Cinematic::~Cinematic( void )
|
|
{
|
|
_actorList.FreeObjectList();
|
|
_cameraList.FreeObjectList();
|
|
_cutList.FreeObjectList();
|
|
_originList.FreeObjectList();
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: init
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Initializes a newly constructed cinematic.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::init()
|
|
{
|
|
turnThinkOn();
|
|
|
|
_stage = CINEMATIC_STAGE_UNLOADED ;
|
|
|
|
setSolidType( SOLID_NOT );
|
|
setMoveType( MOVETYPE_NONE );
|
|
|
|
if ( sv_showcameras->integer )
|
|
{
|
|
setModel( "cinematic.tik" );
|
|
showModel();
|
|
}
|
|
else
|
|
{
|
|
hideModel();
|
|
}
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: reset
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Resets the internal state of the cinematic to
|
|
// its state before the cinematic begins.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::reset( void )
|
|
{
|
|
int numCinematicActors = _actorList.NumObjects();
|
|
for ( int cinematicActorIdx = 1; cinematicActorIdx <= numCinematicActors; ++cinematicActorIdx )
|
|
{
|
|
CinematicActor *cinematicActor = _actorList.ObjectAt( cinematicActorIdx );
|
|
cinematicActor->reset();
|
|
}
|
|
|
|
int numCinematicCameras = _cameraList.NumObjects();
|
|
for ( int cinematicCameraIdx = 1; cinematicCameraIdx <= numCinematicCameras; ++cinematicCameraIdx )
|
|
{
|
|
CinematicCamera *cinematicCamera = _cameraList.ObjectAt( cinematicCameraIdx );
|
|
cinematicCamera->reset();
|
|
}
|
|
|
|
_stage = CINEMATIC_STAGE_READY ;
|
|
_playing = false ;
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: Think
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Think routine for a cinematic
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::Think()
|
|
{
|
|
switch ( _stage )
|
|
{
|
|
case CINEMATIC_STAGE_WAITING_FOR_ACTORS:
|
|
if ( areActorsAtTheirPlaces() )
|
|
start() ;
|
|
break ;
|
|
case CINEMATIC_STAGE_ANIMATING:
|
|
if ( checkForCompletion() )
|
|
stop() ;
|
|
break ;
|
|
default:
|
|
break ;
|
|
}
|
|
|
|
if ( CinematicArmature::isInDebugMode() )
|
|
{
|
|
debug();
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: getCinematicActorByName
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Retrieve an actor by its name. Returns 0 (NULL)
|
|
// if the actor isn't found.
|
|
//
|
|
// This retrieves the first actor with the name.
|
|
//
|
|
// Parameters: const str& -- name of the actor to retrieve.
|
|
//
|
|
// Returns: CinematicCamera* -- pointer to the actor with the
|
|
// specified name. 0 (NULL) if
|
|
// not found.
|
|
//
|
|
//===============================================================
|
|
CinematicActor* Cinematic::getCinematicActorByName( const str &actorName )
|
|
{
|
|
int numActors = _actorList.NumObjects();
|
|
for ( int actorIdx = 1; actorIdx <= numActors; ++actorIdx )
|
|
{
|
|
CinematicActor *cinematicActor = _actorList.ObjectAt( actorIdx );
|
|
if ( cinematicActor->getName() == actorName )
|
|
{
|
|
return cinematicActor ;
|
|
}
|
|
}
|
|
|
|
return 0 ; // NULL
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: getCinematicCameraByName
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Retrieve a camera from its name. Returns 0 (NULL)
|
|
// if the camera isn't found. This is used by the
|
|
// cinematic to attach cameras to camera cuts.
|
|
//
|
|
// This retrieves the first camera with the name.
|
|
//
|
|
// Parameters: const str& -- name of the camera to retrieve.
|
|
//
|
|
// Returns: CinematicCamera* -- pointer to the camera with the
|
|
// specified name. 0 (NULL) if
|
|
// not found.
|
|
//
|
|
//===============================================================
|
|
CinematicCamera* Cinematic::getCinematicCameraByName( const str &cameraName )
|
|
{
|
|
int numCameras = _cameraList.NumObjects();
|
|
for ( int cameraIdx = 1; cameraIdx <= numCameras; ++cameraIdx )
|
|
{
|
|
CinematicCamera *cinematicCamera = _cameraList.ObjectAt( cameraIdx );
|
|
if ( cinematicCamera->getName() == cameraName )
|
|
{
|
|
return cinematicCamera ;
|
|
}
|
|
}
|
|
|
|
return 0 ; // NULL
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: getCinematicOriginByName
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Retrieve an origin by its name. Returns 0 (NULL)
|
|
// if the origin isn't found. This is used by the
|
|
// cinematic to support the playback of a cinematic
|
|
// at multiple origins in the world.
|
|
//
|
|
// This retrieves the first origin with the name.
|
|
//
|
|
// Parameters: const str& -- name of the origin to retrieve.
|
|
//
|
|
// Returns: CinematicOrigin* -- pointer to the origin with the
|
|
// specified name. 0 (NULL) if
|
|
// not found.
|
|
//
|
|
//===============================================================
|
|
CinematicOrigin* Cinematic::getCinematicOriginByName( const str &originName )
|
|
{
|
|
int numOrigins = _originList.NumObjects();
|
|
for ( int originIdx = 1; originIdx <= numOrigins; ++originIdx )
|
|
{
|
|
CinematicOrigin *cinematicOrigin = _originList.ObjectAt( originIdx );
|
|
if ( str::icmp( cinematicOrigin->getName().c_str(), originName.c_str() )==0 )
|
|
{
|
|
return cinematicOrigin ;
|
|
}
|
|
}
|
|
|
|
return 0 ; // NULL
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: _startAnimation
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Begins a cinematic actually playing. At the point
|
|
// this is called, all actors are in their places.
|
|
// All cameras are loaded. Now we tell all the actors
|
|
// to begin their animations, and the cameras to
|
|
// begin their playing.
|
|
//
|
|
// We set our state variable accordingly.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::_startAnimation( void )
|
|
{
|
|
int numCinematicActors = _actorList.NumObjects();
|
|
for (int cinematicActorIdx = 1; cinematicActorIdx <= numCinematicActors; ++cinematicActorIdx )
|
|
{
|
|
CinematicActor *cinematicActor = _actorList.ObjectAt( cinematicActorIdx );
|
|
cinematicActor->playAnimation();
|
|
}
|
|
|
|
int numCameras = _cameraList.NumObjects();
|
|
for ( int cameraIdx = 1; cameraIdx <= numCameras; ++cameraIdx )
|
|
{
|
|
CinematicCamera *cinematicCamera = _cameraList.ObjectAt( cameraIdx );
|
|
cinematicCamera->start();
|
|
}
|
|
|
|
int numCuts = _cutList.NumObjects();
|
|
for ( int cutIdx = 1; cutIdx <= numCuts; ++cutIdx )
|
|
{
|
|
CinematicCut *cinematicCut = _cutList.ObjectAt( cutIdx );
|
|
cinematicCut->postEvents();
|
|
}
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: _endAnimation
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Ends the currently playing cinematic
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::_endAnimation( void )
|
|
{
|
|
int numCinematicActors = _actorList.NumObjects();
|
|
for (int cinematicActorIdx = 1; cinematicActorIdx <= numCinematicActors; ++cinematicActorIdx )
|
|
{
|
|
CinematicActor *cinematicActor = _actorList.ObjectAt( cinematicActorIdx );
|
|
cinematicActor->releaseControlOfActor();
|
|
}
|
|
|
|
// Tell CinematicCameras to delete their cameras here
|
|
int numCinematicCameras = _cameraList.NumObjects();
|
|
for ( int cinematicCameraIdx = 1; cinematicCameraIdx <= numCinematicCameras; ++cinematicCameraIdx )
|
|
{
|
|
CinematicCamera *cinematicCamera = _cameraList.ObjectAt( cinematicCameraIdx );
|
|
cinematicCamera->releaseControlOfCamera();
|
|
}
|
|
|
|
int numCinematicCuts = _cutList.NumObjects();
|
|
for ( int cinematicCutIdx = 1; cinematicCutIdx <= numCinematicCuts; ++cinematicCutIdx )
|
|
{
|
|
CinematicCut *cinematicCut = _cutList.ObjectAt( cinematicCutIdx );
|
|
cinematicCut->stop();
|
|
}
|
|
|
|
// Restore the player's camera immediately if we've taken it
|
|
if ( doesResetCamera() && numCinematicCuts )
|
|
{
|
|
SetCamera( NULL, 0.0f );
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: isCompletion
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Checks to see if a cinematic is completed, done,
|
|
// finished, over, kaput, no more, el tora mea braca.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: bool -- true if completed.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::checkForCompletion( void )
|
|
{
|
|
int numCinematicActors = _actorList.NumObjects();
|
|
for (int cinematicActorIdx = 1; cinematicActorIdx <= numCinematicActors; ++cinematicActorIdx )
|
|
{
|
|
CinematicActor *cinematicActor = _actorList.ObjectAt( cinematicActorIdx );
|
|
if ( !cinematicActor->isAnimDone() ) return false ;
|
|
}
|
|
|
|
int numCinematicCameras = _cameraList.NumObjects();
|
|
for ( int cinematicCameraIdx = 1; cinematicCameraIdx <= numCinematicCameras; ++cinematicCameraIdx )
|
|
{
|
|
CinematicCamera *cinematicCamera = _cameraList.ObjectAt( cinematicCameraIdx );
|
|
if ( !cinematicCamera->isAnimDone() ) return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: areActorsAtTheirPlaces
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Checks to see if all the actors are at their
|
|
// places.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: bool -- true
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::areActorsAtTheirPlaces( void )
|
|
{
|
|
int numActors = _actorList.NumObjects();
|
|
for (int actorIdx = 1; actorIdx <= numActors; actorIdx++)
|
|
{
|
|
CinematicActor *actor = _actorList.ObjectAt( actorIdx );
|
|
if ( !actor->isAtSpot() ) return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: startAtNamedOrigin
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Starts the cinematic at the origin specified by
|
|
// name. If the name isn't specified (or found)
|
|
// the cinematic's origin is the world origin.
|
|
//
|
|
// Cinematics can have origins named in their cinematic
|
|
// file. This enables an artist to determine the best
|
|
// spots for the cinematic to play, and to alias them
|
|
// to a name the game scripter can use to play them
|
|
// back.
|
|
//
|
|
// Parameters: const str& -- the name of the origin to use.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::startAtNamedOrigin( const str &originName, bool callStartThread )
|
|
{
|
|
CinematicOrigin *cinematicOrigin = getCinematicOriginByName( originName );
|
|
Vector origin( 0.0f, 0.0f, 0.0f );
|
|
float yaw = 0.0f ;
|
|
|
|
if ( cinematicOrigin )
|
|
{
|
|
origin = cinematicOrigin->getOrigin();
|
|
yaw = cinematicOrigin->getYaw();
|
|
}
|
|
|
|
startAtOrigin( origin, yaw, callStartThread );
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: prepareToStart
|
|
// Class: Cinematic
|
|
//
|
|
// Description: This begins by
|
|
// finding the actors involved in the scene. Actors
|
|
// that are not available are spawned at their
|
|
// designated spot.
|
|
//
|
|
// Actors are then told to run to their spots (marks
|
|
// in stage terminology). Once all actors are at
|
|
// their marks, the actual animation begins.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: float -- the level time the cinematic was begun.
|
|
//
|
|
//===============================================================
|
|
void Cinematic::startAtOrigin( const Vector &origin, float yaw, bool callStartThread )
|
|
{
|
|
reset();
|
|
|
|
int numActors = _actorList.NumObjects();
|
|
for ( int actorIdx = 1; actorIdx <= numActors; ++actorIdx )
|
|
{
|
|
CinematicActor *cinematicActor = _actorList.ObjectAt( actorIdx );
|
|
cinematicActor->takeControlOfActor( origin, yaw );
|
|
cinematicActor->getToPosition();
|
|
}
|
|
|
|
int numCameras = _cameraList.NumObjects();
|
|
for ( int cameraIdx = 1; cameraIdx <= numCameras; ++cameraIdx )
|
|
{
|
|
CinematicCamera *cinematicCamera = _cameraList.ObjectAt( cameraIdx );
|
|
cinematicCamera->takeControlOfCamera( origin, yaw );
|
|
}
|
|
|
|
int numCuts = _cutList.NumObjects();
|
|
for ( int cutIdx = 1; cutIdx <= numCuts; ++cutIdx )
|
|
{
|
|
CinematicCut *cut = _cutList.ObjectAt( cutIdx );
|
|
CinematicCamera *camera = getCinematicCameraByName( cut->getCameraName() );
|
|
|
|
cut->setCinematicCamera( camera );
|
|
}
|
|
|
|
_stage = CINEMATIC_STAGE_WAITING_FOR_ACTORS ;
|
|
_playing = true ;
|
|
_callStartThreadFlag = callStartThread ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: start
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Starts the cinematic animation. Calls the
|
|
// start thread if a start thread has been specified
|
|
// and start thread call flag is set (passed in).
|
|
//
|
|
// When this function is called, the real cinematic
|
|
// can begin because all of the actors are found and
|
|
// at their places.
|
|
//
|
|
// Parameters: bool -- call the start thread if specified (defaults
|
|
// to true).
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::start( bool callStartThread )
|
|
{
|
|
if ( _startThread.length() && callStartThread )
|
|
{
|
|
ExecuteThread( _startThread );
|
|
}
|
|
|
|
_stage = CINEMATIC_STAGE_ANIMATING ;
|
|
|
|
_startAnimation();
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: stop
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Stops the playing of the current cinematic. All
|
|
// actors are switched back to AI mode. Remaining
|
|
// events are removed from the queue.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::stop( bool callEndThread )
|
|
{
|
|
// Make sure we don't stop this cinematic more than once
|
|
|
|
if ( !_playing )
|
|
return;
|
|
|
|
_playing = false;
|
|
|
|
_endAnimation();
|
|
|
|
if ( _stopThread.length() && callEndThread )
|
|
{
|
|
ExecuteThread( _stopThread );
|
|
}
|
|
|
|
_stage = CINEMATIC_STAGE_FINISHED ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: handleBeginEvent
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Starts the playback of this cinematic.
|
|
//
|
|
// Parameters: Event* -- this event. No arguments.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::handleBeginEvent( Event *ev )
|
|
{
|
|
bool callStartThread = true ;
|
|
str originName ;
|
|
|
|
if ( ev->NumArgs() == 1 )
|
|
{
|
|
originName = ev->GetString( 1 );
|
|
}
|
|
if ( ev->NumArgs() == 2 )
|
|
{
|
|
callStartThread = ev->GetBoolean( 2 );
|
|
}
|
|
|
|
startAtNamedOrigin( originName, callStartThread );
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: handleBeginAtEvent
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Begins the playback of this cinematic at the
|
|
// optionally specified origin and yaw rotation.
|
|
//
|
|
// Parameters: Event* -- EV_Cinematic_BeginAt event.
|
|
// - Arg 1 Optional vector origin (default 0,0,0)
|
|
// - Arg 2 Optional float yaw rotation (default 0 degrees)
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::handleBeginAtEvent( Event *ev )
|
|
{
|
|
Vector origin( 0.0f, 0.0f, 0.0f );
|
|
float yawRotation = 0.0f ;
|
|
bool callStartThread = true ;
|
|
|
|
if ( ev->NumArgs() >= 1 )
|
|
{
|
|
origin = ev->GetVector( 1 );
|
|
}
|
|
if ( ev->NumArgs() == 2 )
|
|
{
|
|
yawRotation = ev->GetFloat( 2 );
|
|
}
|
|
if ( ev->NumArgs() == 3 )
|
|
{
|
|
callStartThread = ev->GetBoolean( 3 );
|
|
}
|
|
|
|
startAtOrigin( origin, yawRotation, callStartThread );
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
// Name: handleEndEvent
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Ends the playback of this cinematic.
|
|
//
|
|
// Parameters: Event* -- EV_Cinematic_End
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::handleEndEvent( Event *ev )
|
|
{
|
|
bool callEndThread = true ;
|
|
|
|
if ( ev->NumArgs() == 1 )
|
|
{
|
|
callEndThread = ev->GetBoolean( 1 );
|
|
}
|
|
|
|
stop( callEndThread );
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: handleSetBeginThreadEvent
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Sets the name of the thread for this cinematic.
|
|
// This thread will get called at the beginning of the
|
|
// cinematic (after the actors reach their places).
|
|
//
|
|
// Parameters: Event* -- the event that triggered this call. The
|
|
// first argument must be a string, naming
|
|
// the play thread.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::handleSetBeginThreadEvent( Event *ev )
|
|
{
|
|
assert( ev );
|
|
|
|
if (ev->NumArgs() != 1)
|
|
{
|
|
ev->Error( "Usage: setStartThread <threadname>");
|
|
return ;
|
|
}
|
|
|
|
setStartThread( ev->GetString( 1 ) );
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: handleSetEndThreadEvent
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Sets the name of the stop thread for this cinematic.
|
|
// This thread will get called when the cinematic
|
|
// stops.
|
|
//
|
|
// Parameters: Event* -- the event that triggered this call. The
|
|
// first argument must be a string, naming
|
|
// the stop thread.
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::handleSetEndThreadEvent( Event *ev )
|
|
{
|
|
assert( ev );
|
|
|
|
if (ev->NumArgs() != 1)
|
|
{
|
|
ev->Error( "Usage: setStopThread <threadname>");
|
|
return ;
|
|
}
|
|
|
|
setStopThread( ev->GetString( 1 ) );
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: debug
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Calls debug on all actors, cameras, and cuts.
|
|
// Opportunity for them to output debug information
|
|
// such as drawing lines on the screen.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//===============================================================
|
|
void Cinematic::debug( void )
|
|
{
|
|
int numActors = _actorList.NumObjects();
|
|
for ( int actorIdx = 1; actorIdx <= numActors; ++actorIdx )
|
|
{
|
|
CinematicActor *cinematicActor = _actorList.ObjectAt( actorIdx );
|
|
cinematicActor->debug();
|
|
}
|
|
|
|
int numCameras = _cameraList.NumObjects();
|
|
for ( int cameraIdx = 1; cameraIdx <= numCameras; ++numCameras )
|
|
{
|
|
CinematicCamera *cinematicCamera = _cameraList.ObjectAt( cameraIdx );
|
|
cinematicCamera->debug();
|
|
}
|
|
|
|
int numCuts = _cutList.NumObjects();
|
|
for ( int cutIdx = 1; cutIdx <= numCuts; ++numCuts )
|
|
{
|
|
CinematicCut *cinematicCut = _cutList.ObjectAt( cutIdx );
|
|
cinematicCut->debug();
|
|
}
|
|
|
|
int numOrigins = _originList.NumObjects();
|
|
for ( int originIdx = 1; originIdx <= numOrigins; ++numOrigins )
|
|
{
|
|
CinematicOrigin *cinematicOrigin = _originList.ObjectAt( originIdx );
|
|
cinematicOrigin->debug();
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: load
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Loads the specified cinematic from file.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: bool -- true if successfully loaded. False otherwise.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::load( void )
|
|
{
|
|
Script cinematicFile ;
|
|
const char *token ;
|
|
|
|
if ( !gi.FS_Exists( _filename.c_str() ) )
|
|
{
|
|
gi.Printf( "File %s not found.\n", _filename.c_str() );
|
|
return false ;
|
|
}
|
|
|
|
cinematicFile.LoadFile( _filename.c_str());
|
|
while ( cinematicFile.TokenAvailable( true ) )
|
|
{
|
|
token = cinematicFile.GetToken( true );
|
|
if (stricmp( token, "Actors")==0)
|
|
{
|
|
if ( !parseActors( cinematicFile ) ) return false ;
|
|
}
|
|
else if (stricmp( token, "Cameras")==0)
|
|
{
|
|
if ( !parseCameras( cinematicFile ) ) return false ;
|
|
}
|
|
else if (stricmp( token, "Objects")==0)
|
|
{
|
|
if ( !parseObjects( cinematicFile ) ) return false ;
|
|
}
|
|
else if (stricmp( token, "Origins")==0)
|
|
{
|
|
if ( !parseOrigins( cinematicFile ) ) return false ;
|
|
}
|
|
else
|
|
{
|
|
gi.Printf("Unexpected token %s in cinematic file %s.\n", token, _filename.c_str());
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
_stage = CINEMATIC_STAGE_READY ;
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseActors
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parse the Actors block from a cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed.
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseActors( Script &cinematicFile )
|
|
{
|
|
if (!parseOpenBlock(cinematicFile, "Actors")) return false ;
|
|
const char *token = cinematicFile.GetToken( true );
|
|
while ( token )
|
|
{
|
|
if ( stricmp( token, "}" ) == 0 ) break ;
|
|
if ( stricmp( token, "Actor" ) == 0)
|
|
{
|
|
if (!parseActor( cinematicFile ))
|
|
return false ;
|
|
}
|
|
|
|
token = cinematicFile.GetToken( true );
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseActor
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parse an actor block from a cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed.
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseActor( Script &cinematicFile )
|
|
{
|
|
if (!parseOpenBlock( cinematicFile, "Actor" ) ) return false ;
|
|
|
|
CinematicActor *actor = new CinematicActor ;
|
|
if (!actor->parse( cinematicFile )) return false ;
|
|
|
|
_actorList.AddObject( actor );
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseCameras
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parses the cameras block from a cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseCameras( Script &cinematicFile )
|
|
{
|
|
if (!parseOpenBlock(cinematicFile, "Cameras")) return false ;
|
|
const char *token = cinematicFile.GetToken( true );
|
|
while ( token )
|
|
{
|
|
if ( strcmp( token, "}" ) == 0 ) break ;
|
|
|
|
if ( stricmp( token, "Camera" ) == 0)
|
|
{
|
|
if ( !parseCamera( cinematicFile )) return false ;
|
|
}
|
|
else if ( stricmp( token, "Cut" ) == 0 )
|
|
{
|
|
if ( !parseCut( cinematicFile ) )return false ;
|
|
}
|
|
else if ( stricmp( token, "ResetCamera" ) == 0 )
|
|
{
|
|
setResetCameraFlag( cinematicFile.GetBoolean( false ) ? true : false );
|
|
}
|
|
|
|
token = cinematicFile.GetToken( true );
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseCamera
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parses a camera block.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed.
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseCamera( Script &cinematicFile )
|
|
{
|
|
if ( !parseOpenBlock( cinematicFile, "Camera" ) ) return false ;
|
|
|
|
CinematicCamera *cinematicCamera = new CinematicCamera();
|
|
if (!cinematicCamera->parse( cinematicFile )) return false ;
|
|
|
|
_cameraList.AddObject( cinematicCamera );
|
|
return true ;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: parseCut
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parses a cut block.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed.
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseCut( Script &cinematicFile )
|
|
{
|
|
if ( !parseOpenBlock( cinematicFile, "Cut" ) ) return false ;
|
|
|
|
CinematicCut *cinematicCut = new CinematicCut();
|
|
if (!cinematicCut->parse( cinematicFile )) return false ;
|
|
|
|
_cutList.AddObject( cinematicCut );
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseObjects
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parse the objects block from a cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseObjects( Script &cinematicFile )
|
|
{
|
|
if (!parseOpenBlock(cinematicFile, "Objects")) return false ;
|
|
const char *token = cinematicFile.GetToken( true );
|
|
while ( token )
|
|
{
|
|
if (strcmp( token, "}") == 0) break ;
|
|
if (stricmp( token, "Object" ) == 0)
|
|
{
|
|
if (!parseObject( cinematicFile ))
|
|
return false ;
|
|
}
|
|
|
|
token = cinematicFile.GetToken( true );
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseObject
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parses an object block.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed.
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseObject( Script &cinematicFile )
|
|
{
|
|
if (!parseOpenBlock( cinematicFile, "Object" ) ) return false ;
|
|
//
|
|
return true ;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: parseOrigins
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parse the Origins block from a cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed.
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseOrigins( Script &cinematicFile )
|
|
{
|
|
if (!parseOpenBlock(cinematicFile, "Origins")) return false ;
|
|
const char *token = cinematicFile.GetToken( true );
|
|
while ( token )
|
|
{
|
|
if ( stricmp( token, "}" ) == 0 ) break ;
|
|
if ( stricmp( token, "Origin" ) == 0)
|
|
{
|
|
if ( !parseOrigin( cinematicFile ))
|
|
return false ;
|
|
}
|
|
|
|
token = cinematicFile.GetToken( true );
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseOrigin
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parse an origin block from a cinematic file.
|
|
//
|
|
// Parameters: Script& -- the cinematic file being parsed.
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseOrigin( Script &cinematicFile )
|
|
{
|
|
if ( !parseOpenBlock( cinematicFile, "Origin" ) ) return false ;
|
|
|
|
CinematicOrigin *cinematicOrigin = new CinematicOrigin();
|
|
if ( !cinematicOrigin->parse( cinematicFile )) return false ;
|
|
|
|
_originList.AddObject( cinematicOrigin );
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseOpenBlock
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parses the next token and determines if it is the
|
|
// expected open block token (default is "{"). Returns
|
|
// true on success, false otherwise.
|
|
//
|
|
// Parameters: Script& -- the script to pull tokens from
|
|
// const str& -- the name of the block we're opening
|
|
// const str& -- the expected open token (default "{")
|
|
//
|
|
// Returns: bool -- true upon success.
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseOpenBlock( Script &cinematicFile, const str &blockName, const str &openToken )
|
|
{
|
|
const char *token = cinematicFile.GetToken( true );
|
|
|
|
if (strcmp( token, openToken.c_str()) != 0)
|
|
{
|
|
gi.Error(ERR_DROP, "Expected %s to open %s block, found %s. Aborting parsing.", openToken.c_str(), blockName.c_str(), token);
|
|
return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
// Name: parseCloseBlock
|
|
// Class: Cinematic
|
|
//
|
|
// Description: Parses the next token and determines if it is the
|
|
// expected close block token (default is "}"). Returns
|
|
// true on success, false otherwise.
|
|
//
|
|
// Parameters: Script& -- the script to pull tokens from
|
|
// const str& -- the name of the block we're closing
|
|
// const str& -- the expected open token (default "}")
|
|
//
|
|
// Returns: bool -- true upon success
|
|
//
|
|
//===============================================================
|
|
bool Cinematic::parseCloseBlock( Script &cinematicFile, const str &blockName, const str &closeToken )
|
|
{
|
|
const char *token = cinematicFile.GetToken( true );
|
|
|
|
if (strcmp( token, closeToken.c_str()) != 0)
|
|
{
|
|
gi.Error(ERR_DROP, "Expected %s to close %s block, found %s. Aborting parsing.", closeToken.c_str(), blockName.c_str(), token);
|
|
return false ;
|
|
}
|
|
|
|
return false ;
|
|
}
|
|
|