736 lines
18 KiB
C++
736 lines
18 KiB
C++
|
/*
|
||
|
** Command & Conquer Renegade(tm)
|
||
|
** Copyright 2025 Electronic Arts Inc.
|
||
|
**
|
||
|
** This program is free software: you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation, either version 3 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** Confidential - Westwood Studios ***
|
||
|
***********************************************************************************************
|
||
|
* *
|
||
|
* Project Name : Commando *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/Combat/transition.cpp $*
|
||
|
* *
|
||
|
* $Author:: Byon_g $*
|
||
|
* *
|
||
|
* $Modtime:: 1/09/02 3:53p $*
|
||
|
* *
|
||
|
* $Revision:: 75 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
/*
|
||
|
** Includes
|
||
|
*/
|
||
|
#include "transition.h"
|
||
|
#include "soldier.h"
|
||
|
#include "debug.h"
|
||
|
#include "assets.h"
|
||
|
#include "combat.h"
|
||
|
#include "ccamera.h"
|
||
|
#include "gameobjmanager.h" // hack???
|
||
|
#include "scripts.h"
|
||
|
#include "hanim.h"
|
||
|
#include "slist.h"
|
||
|
#include "vehicle.h"
|
||
|
#include "phys3.h"
|
||
|
#include "wwprofile.h"
|
||
|
#include "diaglog.h"
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "pathaction.h"
|
||
|
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
const char * TransitionTypeNames[] = {
|
||
|
"LADDER_EXIT_TOP",
|
||
|
"LADDER_EXIT_BOTTOM",
|
||
|
"LADDER_ENTER_TOP",
|
||
|
"LADDER_ENTER_BOTTOM",
|
||
|
"LEGACY_VEHICLE_ENTER_0",
|
||
|
"LEGACY_VEHICLE_ENTER_1",
|
||
|
"LEGACY_VEHICLE_EXIT_0",
|
||
|
"LEGACY_VEHICLE_EXIT_1",
|
||
|
"VEHICLE_ENTER",
|
||
|
"VEHICLE_EXIT",
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
bool Is_Point_Inside( const Vector3 & pos, const Vector3 & min, const Vector3 & max )
|
||
|
{
|
||
|
return ( ( pos.X >= min.X ) && ( pos.X <= max.X ) &&
|
||
|
( pos.Y >= min.Y ) && ( pos.Y <= max.Y ) &&
|
||
|
( pos.Z >= min.Z ) && ( pos.Z <= max.Z ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Save and Load for TransitionDataClass
|
||
|
*/
|
||
|
namespace TRANSITION_DATA_CLASS_SAVELOAD
|
||
|
{
|
||
|
enum {
|
||
|
CHUNKID_VARIABLES = 0x11051106,
|
||
|
|
||
|
MICROCHUNKID_TYPE = 1,
|
||
|
MICROCHUNKID_ZONE,
|
||
|
MICROCHUNKID_ANIMATION_NAME,
|
||
|
MICROCHUNKID_ENDING_TM,
|
||
|
MICROCHUNKID_LADDER_INDEX
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
TransitionDataClass::TransitionDataClass( )
|
||
|
: Type( LADDER_EXIT_TOP )
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
const char * TransitionDataClass::Get_Type_Name( StyleType type )
|
||
|
{
|
||
|
WWASSERT( ((int)type) < Get_Num_Types() );
|
||
|
return TransitionTypeNames[((int)type)];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
bool TransitionDataClass::Save( ChunkSaveClass & csave )
|
||
|
{
|
||
|
using namespace TRANSITION_DATA_CLASS_SAVELOAD;
|
||
|
csave.Begin_Chunk( CHUNKID_VARIABLES );
|
||
|
|
||
|
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TYPE, Type );
|
||
|
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ZONE, Zone );
|
||
|
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ENDING_TM, EndingTM );
|
||
|
WRITE_MICRO_CHUNK_WWSTRING( csave, MICROCHUNKID_ANIMATION_NAME, AnimationName );
|
||
|
|
||
|
csave.End_Chunk();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
bool TransitionDataClass::Load( ChunkLoadClass & cload )
|
||
|
{
|
||
|
using namespace TRANSITION_DATA_CLASS_SAVELOAD;
|
||
|
while (cload.Open_Chunk()) {
|
||
|
switch(cload.Cur_Chunk_ID()) {
|
||
|
|
||
|
case CHUNKID_VARIABLES:
|
||
|
{
|
||
|
while (cload.Open_Micro_Chunk()) {
|
||
|
switch(cload.Cur_Micro_Chunk_ID()) {
|
||
|
|
||
|
READ_MICRO_CHUNK( cload, MICROCHUNKID_TYPE, Type );
|
||
|
READ_MICRO_CHUNK( cload, MICROCHUNKID_ZONE, Zone );
|
||
|
READ_MICRO_CHUNK( cload, MICROCHUNKID_ENDING_TM, EndingTM );
|
||
|
READ_MICRO_CHUNK_WWSTRING( cload, MICROCHUNKID_ANIMATION_NAME, AnimationName );
|
||
|
|
||
|
default:
|
||
|
Debug_Say(( "Unrecognized Transition Variable chunkID\n" ));
|
||
|
break;
|
||
|
}
|
||
|
cload.Close_Micro_Chunk();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
Debug_Say(( "Unrecognized Transition chunkID\n" ));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
cload.Close_Chunk();
|
||
|
}
|
||
|
|
||
|
switch ( Type ) {
|
||
|
case LEGACY_VEHICLE_ENTER_0:
|
||
|
case LEGACY_VEHICLE_ENTER_1:
|
||
|
Type = VEHICLE_ENTER;
|
||
|
break;
|
||
|
case LEGACY_VEHICLE_EXIT_0:
|
||
|
case LEGACY_VEHICLE_EXIT_1:
|
||
|
Type = VEHICLE_EXIT;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** TransitionCompletionDataStruct
|
||
|
*/
|
||
|
namespace TRANSITION_COMPLETION_SAVE_LOAD
|
||
|
{
|
||
|
|
||
|
enum {
|
||
|
CHUNKID_VARIABLES = 1105991816,
|
||
|
CHUNKID_VEHICLE,
|
||
|
|
||
|
MICROCHUNKID_TYPE = 1,
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
bool TransitionCompletionDataStruct::Save( ChunkSaveClass & csave )
|
||
|
{
|
||
|
using namespace TRANSITION_COMPLETION_SAVE_LOAD;
|
||
|
|
||
|
csave.Begin_Chunk( CHUNKID_VARIABLES );
|
||
|
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TYPE, Type );
|
||
|
csave.End_Chunk();
|
||
|
|
||
|
csave.Begin_Chunk( CHUNKID_VEHICLE );
|
||
|
Vehicle.Save( csave );
|
||
|
csave.End_Chunk();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool TransitionCompletionDataStruct::Load( ChunkLoadClass & cload )
|
||
|
{
|
||
|
using namespace TRANSITION_COMPLETION_SAVE_LOAD;
|
||
|
|
||
|
while (cload.Open_Chunk()) {
|
||
|
switch(cload.Cur_Chunk_ID()) {
|
||
|
|
||
|
case CHUNKID_VARIABLES:
|
||
|
while (cload.Open_Micro_Chunk()) {
|
||
|
switch(cload.Cur_Micro_Chunk_ID()) {
|
||
|
READ_MICRO_CHUNK( cload, MICROCHUNKID_TYPE, Type );
|
||
|
|
||
|
default:
|
||
|
Debug_Say(( "Unrecognized TransitionCompletion Variable chunkID\n" ));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
cload.Close_Micro_Chunk();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case CHUNKID_VEHICLE:
|
||
|
Vehicle.Load( cload );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Debug_Say(( "Unrecognized TransitionCompletion chunkID\n" ));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
cload.Close_Chunk();
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
** TransitionInstanceClass
|
||
|
*/
|
||
|
TransitionInstanceClass::TransitionInstanceClass( const TransitionDataClass & data ) :
|
||
|
Data( data ),
|
||
|
EndingTM( 1 ),
|
||
|
LadderIndex( -1 ),
|
||
|
Zone( Vector3( 0,0,0 ), Vector3( 0,0,0 ) )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TransitionInstanceClass::~TransitionInstanceClass( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool TransitionInstanceClass::Check( SoldierGameObj *obj, bool action_trigger )
|
||
|
{
|
||
|
Vector3 pos;
|
||
|
obj->Get_Position( &pos );
|
||
|
|
||
|
// make sure we are in the zone
|
||
|
if ( CollisionMath::Overlap_Test( Zone, pos ) == CollisionMath::OUTSIDE ) {
|
||
|
return false; // not inside
|
||
|
}
|
||
|
|
||
|
// ignore triggers when transitioning
|
||
|
if ( obj->Is_State_Locked() ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Bail if not manually triggered and not ladder exit and
|
||
|
if ( !action_trigger &&
|
||
|
( Get_Type() != TransitionDataClass::LADDER_EXIT_TOP ) &&
|
||
|
( Get_Type() != TransitionDataClass::LADDER_EXIT_BOTTOM ) ) {
|
||
|
#if 0
|
||
|
// no auto transitions or not human controlled
|
||
|
if ( !CombatManager::Are_Transitions_Automatic() ||
|
||
|
!obj->Is_Human_Controlled() )
|
||
|
#endif
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool condition = action_trigger;
|
||
|
|
||
|
if ( action_trigger == false ) {
|
||
|
const float MIN_VELOCITY = 0.1f;
|
||
|
// Check for auto trigger
|
||
|
Vector3 vel;
|
||
|
obj->Get_Velocity( vel );
|
||
|
if ( vel.Length() > MIN_VELOCITY ) {
|
||
|
|
||
|
Vector3 end_direction;
|
||
|
|
||
|
// make sure we meet the conditions
|
||
|
switch ( Get_Type() ) {
|
||
|
|
||
|
case TransitionDataClass::LADDER_ENTER_BOTTOM:
|
||
|
end_direction = EndingTM.Get_X_Vector();
|
||
|
end_direction.Normalize();
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::LADDER_ENTER_TOP:
|
||
|
end_direction = -EndingTM.Get_X_Vector();
|
||
|
end_direction.Normalize();
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::LADDER_EXIT_BOTTOM:
|
||
|
end_direction = Vector3( 0, 0, -1 );
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::LADDER_EXIT_TOP:
|
||
|
end_direction = Vector3( 0, 0, 1 );
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::VEHICLE_ENTER:
|
||
|
case TransitionDataClass::VEHICLE_EXIT:
|
||
|
vel.Z = 0; // don't consider vertical
|
||
|
end_direction = EndingTM.Get_Translation() - Zone.Center;
|
||
|
end_direction.Normalize();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Debug_Say(( "Unrecognized Transition Type\n" ));
|
||
|
condition = false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
// If still has length
|
||
|
if ( vel.Length() > MIN_VELOCITY ) {
|
||
|
vel.Normalize();
|
||
|
float dotp = Vector3::Dot_Product( vel, end_direction );
|
||
|
if ( dotp > 0.5f ) {
|
||
|
condition = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// make sure we meet the conditions
|
||
|
switch ( Get_Type() ) {
|
||
|
|
||
|
case TransitionDataClass::LADDER_EXIT_TOP:
|
||
|
case TransitionDataClass::LADDER_EXIT_BOTTOM:
|
||
|
if ( !obj->Is_On_Ladder() ) {
|
||
|
condition = false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::LADDER_ENTER_TOP:
|
||
|
case TransitionDataClass::LADDER_ENTER_BOTTOM:
|
||
|
if ( !obj->Is_Upright() ) {
|
||
|
condition = false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::VEHICLE_ENTER:
|
||
|
if ( !obj->Is_Upright() && !obj->Is_Wounded() ) {
|
||
|
// Added wounded because we couldn't enter vehicles in a tib field
|
||
|
condition = false;
|
||
|
}
|
||
|
|
||
|
VehicleGameObj * p_vehicle;
|
||
|
p_vehicle = (VehicleGameObj *) Vehicle.Get_Ptr();
|
||
|
WWASSERT(p_vehicle != NULL);
|
||
|
|
||
|
if (!obj->Is_Permitted_To_Enter_Vehicle() ||
|
||
|
!p_vehicle->Is_Entry_Permitted(obj)) {
|
||
|
condition = false;
|
||
|
}
|
||
|
|
||
|
// When entering a vehicle, ensure that there are no walls between us
|
||
|
// Do this by casting a ray from our position to the vehicle position; only
|
||
|
// checking against static geometry.
|
||
|
{
|
||
|
Vector3 p0,p1;
|
||
|
p_vehicle->Get_Position(&p0);
|
||
|
obj->Get_Position(&p1);
|
||
|
|
||
|
CastResultStruct result;
|
||
|
LineSegClass ray(p0,p1);
|
||
|
int colgroup = obj->Peek_Physical_Object()->Get_Collision_Group();
|
||
|
PhysRayCollisionTestClass raytest(ray,&result,colgroup,COLLISION_TYPE_PHYSICAL);
|
||
|
raytest.CheckDynamicObjs = false;
|
||
|
|
||
|
PhysicsSceneClass::Get_Instance()->Cast_Ray(raytest);
|
||
|
|
||
|
if (result.Fraction < 1.0f) {
|
||
|
condition = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::VEHICLE_EXIT:
|
||
|
if ( !obj->Is_In_Vehicle() ) {
|
||
|
condition = false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
default:
|
||
|
Debug_Say(( "Unrecognized Transition Type\n" ));
|
||
|
condition = false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( !condition ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check to ensure the object can teleport to the ending location
|
||
|
//
|
||
|
Matrix3D dummy_tm;
|
||
|
MoveablePhysClass *move_phys = obj->Peek_Physical_Object()->As_MoveablePhysClass();
|
||
|
|
||
|
switch ( Get_Type() ) {
|
||
|
|
||
|
case TransitionDataClass::LADDER_ENTER_TOP:
|
||
|
case TransitionDataClass::LADDER_ENTER_BOTTOM:
|
||
|
{
|
||
|
//
|
||
|
// Its not legal to get on a ladder when someone else is on the ladder.
|
||
|
// Try to detect this case.
|
||
|
//
|
||
|
if( obj == COMBAT_STAR && LadderIndex >= 0 ) {
|
||
|
ScriptableGameObj *occupant = PathActionClass::Get_Ladder_Occupant( LadderIndex );
|
||
|
if( occupant != NULL && occupant != obj ) {
|
||
|
condition = false;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case TransitionDataClass::LADDER_EXIT_TOP:
|
||
|
case TransitionDataClass::LADDER_EXIT_BOTTOM:
|
||
|
|
||
|
//
|
||
|
// When exiting a Ladder, we just have to check for a dynamic object blocking our
|
||
|
// exit point. (the third parameter to Can_Teleport_And_Stand is true...)
|
||
|
//
|
||
|
/*if ( move_phys != NULL &&
|
||
|
move_phys->Can_Teleport(EndingTM, true) == false)
|
||
|
{
|
||
|
condition = false;
|
||
|
}*/
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::VEHICLE_EXIT:
|
||
|
|
||
|
//
|
||
|
// When exiting a vehicle, we perform two steps:
|
||
|
// - ignore our vehicle and sweep the character to the exit transform
|
||
|
// - un-ignore the vehicle and do a teleport test.
|
||
|
//
|
||
|
if (move_phys != NULL) {
|
||
|
|
||
|
bool can_move_to;
|
||
|
|
||
|
VehicleGameObj * vgobj = Get_Vehicle();
|
||
|
PhysClass * pobj = vgobj->Peek_Physical_Object();
|
||
|
|
||
|
pobj->Inc_Ignore_Counter();
|
||
|
can_move_to = move_phys->Can_Move_To(EndingTM);
|
||
|
pobj->Dec_Ignore_Counter();
|
||
|
|
||
|
if ( (can_move_to == false) ||
|
||
|
(move_phys->Can_Teleport_And_Stand(EndingTM,&dummy_tm) == false) )
|
||
|
{
|
||
|
condition = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( !condition ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Start( obj );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void TransitionInstanceClass::Start( SoldierGameObj *obj )
|
||
|
{
|
||
|
// Debug_Say(( "Starting Animation\n" ));
|
||
|
|
||
|
// if this is the camera's target...
|
||
|
if ( COMBAT_STAR == obj ) {
|
||
|
// Get duration
|
||
|
#if 0
|
||
|
HAnimClass * animation = WW3DAssetManager::Get_Instance()->Get_HAnim( Data.Get_Animation_Name() );
|
||
|
if ( animation ) {
|
||
|
float anim_duration = animation->Get_Num_Frames() / animation->Get_Frame_Rate();
|
||
|
animation->Release_Ref();
|
||
|
// COMBAT_CAMERA->Set_Lerp_Time( anim_duration * 1.3f );
|
||
|
COMBAT_CAMERA->Set_Lerp_Time( anim_duration );
|
||
|
}
|
||
|
#else
|
||
|
COMBAT_CAMERA->Set_Lerp_Time( 1.0f );
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// set the object ending position & orientation
|
||
|
#ifdef WWDEBUG
|
||
|
Vector3 pos = EndingTM.Get_Translation();
|
||
|
if (!pos.Is_Valid()) {
|
||
|
WWDEBUG_SAY(("Transition EndingTM has invalid position: %f, %f, %f\r\n",pos.X,pos.Y,pos.Z));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
obj->Set_Transform( EndingTM );
|
||
|
|
||
|
if ( obj->Peek_Physical_Object() != NULL && obj->Peek_Physical_Object()->As_Phys3Class() != NULL ) {
|
||
|
obj->Peek_Physical_Object()->As_Phys3Class()->Set_Velocity( Vector3(0,0,0) );
|
||
|
}
|
||
|
|
||
|
// make the completion data
|
||
|
TransitionCompletionDataStruct * completion_data = new TransitionCompletionDataStruct;
|
||
|
completion_data->Type = Data.Get_Type();
|
||
|
completion_data->Vehicle = Vehicle;
|
||
|
|
||
|
//
|
||
|
// Mark ladders as being used/free as necessary
|
||
|
//
|
||
|
switch ( Get_Type() ) {
|
||
|
|
||
|
case TransitionDataClass::LADDER_ENTER_TOP:
|
||
|
case TransitionDataClass::LADDER_ENTER_BOTTOM:
|
||
|
{
|
||
|
//
|
||
|
// Mark this ladder as being "in use" so no one else tries to get on it
|
||
|
//
|
||
|
if( obj == COMBAT_STAR && LadderIndex >= 0 ) {
|
||
|
PathActionClass::Set_Ladder_Occupant( LadderIndex, obj );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case TransitionDataClass::LADDER_EXIT_TOP:
|
||
|
case TransitionDataClass::LADDER_EXIT_BOTTOM:
|
||
|
{
|
||
|
//
|
||
|
// Free this ladder so other's can use it
|
||
|
//
|
||
|
if( obj == COMBAT_STAR && LadderIndex >= 0 ) {
|
||
|
PathActionClass::Set_Ladder_Occupant( LadderIndex, NULL );
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
obj->Start_Transition_Animation( Data.Get_Animation_Name(), completion_data );
|
||
|
|
||
|
VehicleGameObj * vehicle = Get_Vehicle();
|
||
|
|
||
|
// If vehicle entry/exit, allow it to animate as well
|
||
|
switch ( Get_Type() ) {
|
||
|
|
||
|
case TransitionDataClass::VEHICLE_ENTER:
|
||
|
{
|
||
|
if ( vehicle ) {
|
||
|
vehicle->Passenger_Entering();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case TransitionDataClass::VEHICLE_EXIT:
|
||
|
{
|
||
|
WWASSERT( vehicle );
|
||
|
// obj->Set_Vehicle_State( SoldierGameObj::EXITING_VEHICLE, vehicle );
|
||
|
vehicle->Passenger_Exiting();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
#else
|
||
|
End( obj, completion_data );
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
void TransitionInstanceClass::End( SoldierGameObj *obj,
|
||
|
TransitionCompletionDataStruct * completion_data )
|
||
|
{
|
||
|
VehicleGameObj * vehicle = (VehicleGameObj *)completion_data->Vehicle.Get_Ptr();
|
||
|
|
||
|
switch ( completion_data->Type ) {
|
||
|
|
||
|
case TransitionDataClass::LADDER_EXIT_TOP:
|
||
|
case TransitionDataClass::LADDER_EXIT_BOTTOM:
|
||
|
obj->Exit_Ladder();
|
||
|
|
||
|
if ( obj == COMBAT_STAR ) {
|
||
|
Vector3 pos;
|
||
|
obj->Get_Position( &pos );
|
||
|
DIAG_LOG(( "LAEX", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::LADDER_ENTER_TOP:
|
||
|
case TransitionDataClass::LADDER_ENTER_BOTTOM:
|
||
|
obj->Enter_Ladder( completion_data->Type == TransitionDataClass::LADDER_ENTER_TOP );
|
||
|
|
||
|
if ( obj == COMBAT_STAR ) {
|
||
|
Vector3 pos;
|
||
|
obj->Get_Position( &pos );
|
||
|
DIAG_LOG(( "LAEN", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TransitionDataClass::VEHICLE_ENTER:
|
||
|
{
|
||
|
if ( vehicle != NULL ) {
|
||
|
vehicle->Add_Occupant( obj );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case TransitionDataClass::VEHICLE_EXIT:
|
||
|
{
|
||
|
if ( vehicle != NULL ) {
|
||
|
vehicle->Remove_Occupant( obj );
|
||
|
} else {
|
||
|
obj->Exit_Vehicle();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
Debug_Say(( "Unrecognized Transition Type\n" ));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Delete the data (soldier better not use it)
|
||
|
delete completion_data;
|
||
|
}
|
||
|
|
||
|
void TransitionInstanceClass::Set_Parent_Transform( const Matrix3D & tm )
|
||
|
{
|
||
|
Matrix3D::Multiply( tm, Data.Get_Ending_TM(), &EndingTM );
|
||
|
OBBoxClass::Transform( tm, Data.Get_Zone(), &Zone );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
** TransitionManager
|
||
|
*/
|
||
|
SList<TransitionInstanceClass> Transitions;
|
||
|
SList<TransitionInstanceClass> TransitionsDestroy;
|
||
|
|
||
|
void TransitionManager::Add( TransitionInstanceClass * transition )
|
||
|
{
|
||
|
Transitions.Add_Tail( transition );
|
||
|
}
|
||
|
|
||
|
void TransitionManager::Destroy( TransitionInstanceClass * transition )
|
||
|
{
|
||
|
TransitionsDestroy.Add_Tail( transition );
|
||
|
}
|
||
|
|
||
|
void TransitionManager::Reset( void )
|
||
|
{
|
||
|
Destroy_Pending();
|
||
|
|
||
|
while ( Transitions.Get_Count() ) {
|
||
|
delete Transitions.Remove_Head();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TransitionManager::Destroy_Pending( void )
|
||
|
{
|
||
|
while ( TransitionsDestroy.Get_Count() ) {
|
||
|
TransitionInstanceClass * trans = TransitionsDestroy.Remove_Head();
|
||
|
Transitions.Remove( trans );
|
||
|
delete trans;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool TransitionManager::Check( SoldierGameObj *obj, bool action_trigger )
|
||
|
{
|
||
|
WWPROFILE( "Transition Check" );
|
||
|
SLNode<TransitionInstanceClass> *ti_node;
|
||
|
for ( ti_node = Transitions.Head(); ti_node; ti_node = ti_node->Next()) {
|
||
|
if ( ti_node->Data()->Check( obj, action_trigger ) ) {
|
||
|
Destroy_Pending();
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TransitionManager::Build_Ladder_List (DynamicVectorClass<TransitionInstanceClass *> &list)
|
||
|
{
|
||
|
SLNode<TransitionInstanceClass> *ti_node = NULL;
|
||
|
for ( ti_node = Transitions.Head(); ti_node; ti_node = ti_node->Next()) {
|
||
|
|
||
|
//
|
||
|
// Is this a ladder transition?
|
||
|
//
|
||
|
TransitionDataClass::StyleType type = ti_node->Data()->Get_Type ();
|
||
|
if ( type == TransitionDataClass::LADDER_EXIT_TOP || type == TransitionDataClass::LADDER_EXIT_BOTTOM ||
|
||
|
type == TransitionDataClass::LADDER_ENTER_TOP || type == TransitionDataClass::LADDER_ENTER_BOTTOM)
|
||
|
{
|
||
|
list.Add( ti_node->Data () );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|