mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-20 04:30:12 +02:00
Quake 4 integrated with DoomRTX
This commit is contained in:
@@ -0,0 +1,836 @@
|
||||
|
||||
// VehicleDriver.cpp
|
||||
//
|
||||
// Copyright 2002-2004 Raven Software
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
const idEventDef VD_ChoosePathTarget( "choosePathTarget", "e", 'e' );
|
||||
const idEventDef EV_FollowOffset( "followOffset", "v" );
|
||||
const idEventDef EV_FireWeapon ( "fireWeapon", "ff" );
|
||||
|
||||
CLASS_DECLARATION( idActor, rvVehicleDriver )
|
||||
EVENT( EV_PostSpawn , rvVehicleDriver::Event_PostSpawn )
|
||||
EVENT( AI_EnterVehicle , rvVehicleDriver::Event_EnterVehicle )
|
||||
EVENT( AI_ExitVehicle , rvVehicleDriver::Event_ExitVehicle )
|
||||
EVENT( AI_ScriptedMove , rvVehicleDriver::Event_ScriptedMove )
|
||||
EVENT( AI_ScriptedDone , rvVehicleDriver::Event_ScriptedDone )
|
||||
EVENT( AI_ScriptedStop , rvVehicleDriver::Event_ScriptedStop )
|
||||
EVENT( EV_Activate , rvVehicleDriver::Event_Trigger )
|
||||
EVENT( EV_Speed , rvVehicleDriver::Event_SetSpeed )
|
||||
EVENT( EV_FireWeapon , rvVehicleDriver::Event_FireWeapon )
|
||||
EVENT( AI_FaceEntity , rvVehicleDriver::Event_FaceEntity )
|
||||
EVENT( AI_LookAt , rvVehicleDriver::Event_LookAt )
|
||||
EVENT( AI_SetLeader , rvVehicleDriver::Event_SetLeader )
|
||||
|
||||
//twhitaker: remove - begin
|
||||
EVENT( EV_FollowOffset , rvVehicleDriver::Event_SetFollowOffset )
|
||||
//twhitaker: remove - end
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::rvVehicleDriver
|
||||
================
|
||||
*/
|
||||
rvVehicleDriver::rvVehicleDriver ( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Spawn
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Spawn ( void ) {
|
||||
currentThrottle = 1.0f;
|
||||
faceTarget = NULL;
|
||||
lookTarget = NULL;
|
||||
leader = NULL;
|
||||
leaderFlags = 0;
|
||||
decelDistance = 0.0f;
|
||||
minDistance = 0.0f;
|
||||
fireEndTime = 0.0f;
|
||||
isMoving = false;
|
||||
avoidingLeader = false;
|
||||
pathingMode = VDPM_Random;
|
||||
pathingOrigin = vec3_origin;
|
||||
pathingEntity = NULL;
|
||||
|
||||
SIMDProcessor->Memset( &pathTargetInfo, 0, sizeof( PathTargetInfo ) );
|
||||
SIMDProcessor->Memset( &lastPathTargetInfo, 0, sizeof( PathTargetInfo ) );
|
||||
|
||||
PostEventMS( &EV_PostSpawn, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Think
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Think ( void ) {
|
||||
if ( !IsDriving() ) {
|
||||
if ( leader ) {
|
||||
leader->SetLeaderHint( VDLH_Continue );
|
||||
leader = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( pathTargetInfo.node ) {
|
||||
float targetDistance = 0.0f;
|
||||
float dotForward = 0.0f;
|
||||
float dotRight = 0.0f;
|
||||
float desiredThrottle = 1.0f;
|
||||
idEntity* currentPathTarget = pathTargetInfo.node;
|
||||
rvVehicle* vehicle = vehicleController.GetVehicle();
|
||||
idMat3 vehicleAxis = vehicle->GetAxis();
|
||||
idVec3 targetOrigin;
|
||||
idVec3 dirToTarget;
|
||||
usercmd_t cmd;
|
||||
idAngles ang;
|
||||
|
||||
// We may want to hack the auto correction variable based on what the state of the driver and the driver's leader.
|
||||
UpdateAutoCorrection();
|
||||
|
||||
if ( vehicle->IsAutoCorrecting( ) ) {
|
||||
if ( lastPathTargetInfo.node ) {
|
||||
currentPathTarget = lastPathTargetInfo.node;
|
||||
}
|
||||
|
||||
if ( g_debugVehicleDriver.GetInteger() != 0 ) {
|
||||
gameRenderWorld->DebugBounds( colorCyan, vehicle->GetPhysics()->GetAbsBounds().Expand( 30 ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Touch all the triggers that the vehicle touches
|
||||
vehicle->TouchTriggers();
|
||||
|
||||
GetTargetInfo( currentPathTarget, &targetOrigin, &dirToTarget, &dotForward, &dotRight, &targetDistance );
|
||||
|
||||
// The primary purpose of the following portions of code is to set the desiredThrottle variable.
|
||||
if ( IsMoving() ) {
|
||||
|
||||
// if we're slowing down lerp throttle.
|
||||
if ( pathTargetInfo.throttle < lastPathTargetInfo.throttle ) {
|
||||
desiredThrottle = idMath::Lerp( lastPathTargetInfo.throttle, pathTargetInfo.throttle, targetDistance / pathTargetInfo.initialDistance );
|
||||
} else {
|
||||
// otherwise accelerate rapidly or maintain throttle.
|
||||
desiredThrottle = pathTargetInfo.throttle;
|
||||
}
|
||||
|
||||
// we could potentially be a leader, so check the leader flags
|
||||
if ( leaderFlags & VDLH_SlowDown ) {
|
||||
desiredThrottle = 0.1f;
|
||||
} else if ( leaderFlags & VDLH_Wait ) {
|
||||
desiredThrottle = 0.0f;
|
||||
}
|
||||
|
||||
// if we're following a someone ...
|
||||
if ( leader ) {
|
||||
bool canSeeLeader = vehicle->CanSee( leader->vehicleController.GetVehicle(), false );
|
||||
float distanceToLeader = ( leader->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin() ).Length();
|
||||
avoidingLeader = false;
|
||||
|
||||
// update the leaders flags based on distance and visibility
|
||||
if ( !canSeeLeader ) {
|
||||
// if we can't see the leader, tell him to stop
|
||||
leader->SetLeaderHint( VDLH_Wait );
|
||||
|
||||
} else if ( distanceToLeader > decelDistance ) {
|
||||
// if we're too far from the leader, tell him to slow down
|
||||
leader->SetLeaderHint( VDLH_SlowDown );
|
||||
|
||||
} else {
|
||||
// we're within range of the leader so let him move along at a normal rate
|
||||
leader->SetLeaderHint( VDLH_Continue );
|
||||
|
||||
// if we're too close to the leader, we need to slow ourself down
|
||||
if ( distanceToLeader < minDistance ) {
|
||||
desiredThrottle = -0.2f;
|
||||
avoidingLeader = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the desiredThrottle variable should be set at this point, the only other thing that could change it
|
||||
// would be in SimulateKeys, if the dotForward < 0.
|
||||
}
|
||||
|
||||
vehicleController.GetInput( cmd, ang );
|
||||
|
||||
// Simulate Input
|
||||
SimulateKeys( cmd, dotForward, dotRight, desiredThrottle * currentThrottle, targetDistance );
|
||||
SimulateMouseMove( cmd );
|
||||
SimulateButtons( cmd );
|
||||
|
||||
vehicleController.SetInput( cmd, ang );
|
||||
|
||||
// Node Transition
|
||||
if( (!vehicle->IsAutoCorrecting() || !IsValidPathNode( currentPathTarget )) && isMoving ) {
|
||||
idVec3 point = targetOrigin - dirToTarget * pathTargetInfo.minDistance;
|
||||
|
||||
if( vehicle->GetPhysics()->GetAbsBounds().ContainsPoint( point ) ) {
|
||||
int numTargets = NumValidTargets( currentPathTarget );
|
||||
lastPathTargetInfo = pathTargetInfo;
|
||||
//TODO: ponder - should I be setting lastPathTargetInfo.node to pathTargetInfo.node or currentPathTarget???
|
||||
|
||||
if( numTargets ) {
|
||||
Event_ScriptedMove( ChooseNextNode( currentPathTarget ), 0, 0 );
|
||||
}
|
||||
|
||||
if( lastPathTargetInfo.exitVehicle ) {
|
||||
Event_ExitVehicle( true );
|
||||
} else if( lastPathTargetInfo.throttle == 0 || !numTargets ) {
|
||||
Event_ScriptedStop();
|
||||
|
||||
if( !numTargets ) {
|
||||
pathTargetInfo.node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Debug Output
|
||||
if ( g_debugVehicleDriver.GetInteger( ) != 0 ) {
|
||||
gameRenderWorld->DebugBounds( colorRed, idBounds(idVec3(-5, -5, -5), idVec3(5, 5, 5)), point );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // no path
|
||||
float dotForward;
|
||||
float dotRight;
|
||||
usercmd_t cmd;
|
||||
idAngles ang;
|
||||
|
||||
vehicleController.GetInput( cmd, ang );
|
||||
|
||||
if ( GetTargetInfo( faceTarget, NULL, NULL, &dotForward, &dotRight, NULL) ) {
|
||||
if( ( 1.0f - dotForward ) < VECTOR_EPSILON ) {
|
||||
Event_ScriptedStop();
|
||||
} else {
|
||||
SimulateKeys( cmd, dotForward, dotRight, 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
SimulateMouseMove( cmd );
|
||||
SimulateButtons( cmd );
|
||||
|
||||
vehicleController.SetInput( cmd, ang );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::GetTargetInfo
|
||||
================
|
||||
*/
|
||||
bool rvVehicleDriver::GetTargetInfo( const idEntity* target, idVec3* targetOrigin, idVec3* dirToTarget, float* dotForward, float* dotRight, float* distance ) const {
|
||||
if( !target || !IsDriving() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idMat3 vehicleAxis = vehicleController.GetVehicle()->GetAxis();
|
||||
idVec3 vehicleOrigin = vehicleController.GetVehicle()->GetOrigin();
|
||||
idVec3 forward = vehicleAxis[ 0 ];
|
||||
idVec3 localTargetOrigin = target->GetPhysics()->GetOrigin();
|
||||
localTargetOrigin.z = vehicleOrigin.z;// Find way to include vehicleAxis here
|
||||
idVec3 vectorToTarget = localTargetOrigin - vehicleOrigin;
|
||||
idVec3 localDirToTarget = vectorToTarget;
|
||||
float distToTarget = localDirToTarget.Normalize();
|
||||
|
||||
if( targetOrigin ) {
|
||||
*targetOrigin = localTargetOrigin;
|
||||
}
|
||||
|
||||
if( dirToTarget ) {
|
||||
*dirToTarget = localDirToTarget;
|
||||
}
|
||||
|
||||
if( distance ) {
|
||||
*distance = distToTarget;
|
||||
}
|
||||
|
||||
if( dotForward ) {
|
||||
*dotForward = localDirToTarget * forward;
|
||||
}
|
||||
|
||||
if( dotRight ) {
|
||||
*dotRight = localDirToTarget * vehicleAxis[ 1 ];
|
||||
}
|
||||
|
||||
// Debug help
|
||||
if ( g_debugVehicleDriver.GetInteger( ) != 0 ) {
|
||||
idStr temp;
|
||||
const idVec3 & origin = GetPhysics()->GetOrigin();
|
||||
gameRenderWorld->DebugLine( colorBlue, origin, target->GetPhysics()->GetOrigin() );
|
||||
gameRenderWorld->DebugBounds( colorBlue, GetPhysics()->GetAbsBounds() );
|
||||
gameRenderWorld->DebugBounds( colorBlue, target->GetPhysics()->GetBounds(), target->GetPhysics()->GetOrigin() );
|
||||
gameRenderWorld->DrawText( target->GetName(), vehicleOrigin + vectorToTarget + vehicleAxis[2] * 5.0f, 1.0f, colorBlue, gameLocal.GetLocalPlayer()->viewAxis );
|
||||
gameRenderWorld->DrawText( idStr( "State: " ) + LeaderHintsString( leaderFlags, temp ), origin, 1.0f, colorBlue, gameLocal.GetLocalPlayer()->viewAxis );
|
||||
|
||||
if ( vehicleController.GetVehicle()->IsAutoCorrecting() ) {
|
||||
gameRenderWorld->DebugBounds( colorPurple, vehicleController.GetVehicle()->GetPhysics()->GetAbsBounds() );
|
||||
gameRenderWorld->DrawText( "Auto-Correcting", vehicleOrigin, 1.0f, colorPurple, gameLocal.GetLocalPlayer()->viewAxis );
|
||||
}
|
||||
|
||||
if ( pathTargetInfo.node && g_debugVehicleDriver.GetInteger( ) == 2 ) {
|
||||
gameRenderWorld->DebugBounds( colorOrange, pathTargetInfo.node->GetPhysics()->GetBounds() );
|
||||
|
||||
for ( int ix = 0; ix < pathTargetInfo.node->targets.Num(); ix++ ) {
|
||||
gameRenderWorld->DebugLine( colorOrange, pathTargetInfo.node->GetPhysics()->GetOrigin(), pathTargetInfo.node->targets[ ix ]->GetPhysics()->GetOrigin(), 0, true );
|
||||
}
|
||||
}
|
||||
if ( leader ) {
|
||||
idVec4 & color = colorGreen;
|
||||
|
||||
if ( leader->GetLeaderHint() & VDLH_SlowDown ) {
|
||||
color = colorYellow;
|
||||
} else if ( leader->GetLeaderHint() & VDLH_Wait ) {
|
||||
color = colorRed;
|
||||
}
|
||||
|
||||
idStr str = idStr( "decel_distance: " ) + idStr( decelDistance ) + idStr( "\nmin_distance: " ) + idStr( minDistance );
|
||||
|
||||
gameRenderWorld->DrawText( str, leader->GetPhysics()->GetOrigin(), 1.0f, color, gameLocal.GetLocalPlayer()->viewAxis, 1, 0, true );
|
||||
gameRenderWorld->DebugLine( color, GetPhysics()->GetOrigin(), leader->GetPhysics()->GetOrigin(), 0, true );
|
||||
gameRenderWorld->DebugBounds( color, leader->vehicleController.GetVehicle()->GetPhysics()->GetAbsBounds(), vec3_origin, 0, true );
|
||||
gameRenderWorld->DebugCircle( color, leader->GetPhysics()->GetOrigin(), idVec3( 0, 0, 1 ), decelDistance, 10, 0, true );
|
||||
gameRenderWorld->DebugCircle( color, leader->GetPhysics()->GetOrigin(), idVec3( 0, 0, 1 ), minDistance, 10, 0, true );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::ChooseNextNode
|
||||
================
|
||||
*/
|
||||
idEntity* rvVehicleDriver::ChooseNextNode( idEntity* target ) {
|
||||
if( !target ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( func.Init( target->spawnArgs.GetString( "call_nextNode" )) <= 0 ) {
|
||||
idEntity * best = NULL;
|
||||
float bestDist;
|
||||
|
||||
switch ( pathingMode ) {
|
||||
case VDPM_MoveTo:
|
||||
bestDist = FLT_MAX;
|
||||
|
||||
for ( int i = target->targets.Num() - 1; i; i -- ) {
|
||||
float distance = ( target->targets[ i ]->GetPhysics()->GetOrigin() - pathingOrigin ).LengthSqr();
|
||||
|
||||
if ( bestDist > distance ) {
|
||||
bestDist = distance;
|
||||
best = target->targets[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case VDPM_MoveAway:
|
||||
bestDist = FLT_MIN;
|
||||
|
||||
for ( int i = target->targets.Num() - 1; i; i -- ) {
|
||||
float distance = ( target->targets[ i ]->GetPhysics()->GetOrigin() - pathingOrigin ).LengthSqr();
|
||||
|
||||
if ( bestDist < distance ) {
|
||||
bestDist = distance;
|
||||
best = target->targets[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
case VDPM_Custom:
|
||||
if ( pathingEntity ) {
|
||||
// best = pathingCallback( target );
|
||||
pathingEntity->ProcessEvent( &VD_ChoosePathTarget, target );
|
||||
best = gameLocal.program.GetReturnedEntity();
|
||||
}
|
||||
}
|
||||
|
||||
return ( best ) ? best : RandomValidTarget( target );
|
||||
}
|
||||
|
||||
func.InsertEntity( this, 0 );
|
||||
func.CallFunc( &spawnArgs );
|
||||
func.RemoveIndex( 0 );
|
||||
|
||||
return ( func.ReturnsAVal()) ? gameLocal.FindEntity( spawnArgs.GetString( func.GetReturnKey() )) : const_cast<idEntity*>( target );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::SimulateButtons
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::SimulateButtons( usercmd_t& cmd ) {
|
||||
cmd.buttons = (fireEndTime >= gameLocal.time) ? BUTTON_ATTACK : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::SimulateMouseMove
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::SimulateMouseMove( usercmd_t& cmd ) {
|
||||
idVec3 origin;
|
||||
idMat3 axis;
|
||||
|
||||
idVec3 vectorToTarget;
|
||||
idAngles anglesToTarget;
|
||||
idAngles turretAngles;
|
||||
idAngles deltaAngles;
|
||||
|
||||
if( !lookTarget ) {
|
||||
for( int ix = 0; ix < 3; ++ix ) {
|
||||
cmd.angles[ix] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
vehicleController.GetEyePosition( origin, axis );
|
||||
vectorToTarget = (lookTarget->GetPhysics()->GetOrigin() - origin).ToNormal();
|
||||
anglesToTarget = vectorToTarget.ToAngles().Normalize360();
|
||||
turretAngles = (axis[0]).ToAngles().Normalize360();
|
||||
deltaAngles = (anglesToTarget - turretAngles).Normalize180();
|
||||
|
||||
for( int ix = 0; ix < deltaAngles.GetDimension(); ++ix ) {
|
||||
cmd.angles[ix] += ANGLE2SHORT( deltaAngles[ix] );
|
||||
}
|
||||
|
||||
// Debug Output
|
||||
if( g_debugVehicleDriver.GetInteger( ) != 0 ) {
|
||||
gameRenderWorld->DebugLine( colorGreen, origin, origin + anglesToTarget.ToForward() * 100.0f, 17, true );
|
||||
gameRenderWorld->DebugLine( colorYellow, origin, origin + turretAngles.ToForward() * 100.0f, 17, true );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::SimulateKeys
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::SimulateKeys( usercmd_t& cmd, float dotForward, float dotRight, float speed, float distance ) {
|
||||
rvVehicle * vehicle = vehicleController.GetVehicle();
|
||||
|
||||
if( !vehicle ) {
|
||||
cmd.forwardmove = 0;
|
||||
cmd.rightmove = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
cmd.forwardmove = static_cast< signed char >( (!vehicle->IsAutoCorrecting() ? 127.0f : forwardThrustScale) * dotForward * speed );
|
||||
cmd.rightmove = static_cast< signed char >( ( ( dotForward < 0.0f ) ? rightThrustScale : -rightThrustScale ) * dotRight );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::SortValid
|
||||
================
|
||||
*/
|
||||
int rvVehicleDriver::SortValid( const void* a, const void* b ) {
|
||||
idEntityPtr<idEntity> A = *(idEntityPtr<idEntity>*)a;
|
||||
idEntityPtr<idEntity> B = *(idEntityPtr<idEntity>*)b;
|
||||
|
||||
return rvVehicleDriver::IsValidTarget( B ) - rvVehicleDriver::IsValidTarget( A );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::SortTargetList
|
||||
================
|
||||
*/
|
||||
int rvVehicleDriver::SortTargetList( idEntity* ent ) const {
|
||||
if( !ent ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int numValidEntities = 0;
|
||||
idEntity * target;
|
||||
|
||||
ent->RemoveNullTargets();
|
||||
qsort( ent->targets.Ptr(), NumTargets( ent ), ent->targets.TypeSize(), rvVehicleDriver::SortValid );
|
||||
|
||||
for( int ix = NumTargets( ent ) - 1; ix >= 0; --ix ) {
|
||||
target = GetTarget( ent, ix );
|
||||
|
||||
if( IsValidTarget( target ) ) {
|
||||
++numValidEntities;
|
||||
}
|
||||
}
|
||||
|
||||
return numValidEntities;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::RandomValidTarget
|
||||
================
|
||||
*/
|
||||
idEntity* rvVehicleDriver::RandomValidTarget( idEntity* ent ) const {
|
||||
int numValid = NumValidTargets( ent );
|
||||
return (!numValid) ? NULL : ent->targets[ rvRandom::irand(0, numValid - 1) ];
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::NumValidTargets
|
||||
================
|
||||
*/
|
||||
int rvVehicleDriver::NumValidTargets( idEntity* ent ) const {
|
||||
return SortTargetList(ent);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::NumTargets
|
||||
================
|
||||
*/
|
||||
int rvVehicleDriver::NumTargets( const idEntity* ent ) const {
|
||||
return (ent) ? ent->targets.Num() : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::GetTarget
|
||||
================
|
||||
*/
|
||||
idEntity* rvVehicleDriver::GetTarget( const idEntity* ent, int index ) const {
|
||||
return (ent) ? ent->targets[index] : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::IsValidPathNode
|
||||
================
|
||||
*/
|
||||
bool rvVehicleDriver::IsValidPathNode( const idEntity* ent ) {
|
||||
if( !ent ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ent->IsType( idTarget::GetClassType() );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::IsValidTarget
|
||||
================
|
||||
*/
|
||||
bool rvVehicleDriver::IsValidTarget( const idEntity* ent ) {
|
||||
return IsValidPathNode( ent ) || ent->IsType( rvVehicle::GetClassType() ) || ent->IsType( idPlayer::GetClassType() );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::SetLeader
|
||||
================
|
||||
*/
|
||||
bool rvVehicleDriver::SetLeader( idEntity* ent ) {
|
||||
if ( !ent || !ent->IsType( rvVehicleDriver::GetClassType() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
leader = static_cast<rvVehicleDriver*>( ent );
|
||||
minDistance = leader->spawnArgs.GetFloat( "min_distance", "500" );
|
||||
idStr decel_distance( minDistance * 3.0f );
|
||||
decelDistance = leader->spawnArgs.GetFloat( "decel_distance", decel_distance );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_PostSpawn
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_PostSpawn ( void ) {
|
||||
for ( int i = targets.Num() - 1; i >= 0; i-- ) {
|
||||
idEntity * ent = targets[ i ].GetEntity();
|
||||
if ( ent->IsType( rvVehicle::GetClassType() ) ) {
|
||||
Event_EnterVehicle( ent );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = targets.Num() - 1; i >= 0; i-- ) {
|
||||
idEntity * ent = targets[ i ].GetEntity();
|
||||
if ( ent->IsType( idTarget::GetClassType() ) ) {
|
||||
Event_ScriptedMove( ent, 0, 0 );
|
||||
}
|
||||
if ( ent->IsType( rvVehicleDriver::GetClassType() ) ) {
|
||||
SetLeader( ent );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_EnterVehicle
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_EnterVehicle ( idEntity * vehicle ) {
|
||||
if ( vehicle ) {
|
||||
forwardThrustScale = vehicle->spawnArgs.GetFloat( "driver_forward_thrust", ".75" ) * 127.0f;
|
||||
rightThrustScale = vehicle->spawnArgs.GetFloat( "driver_right_thrust", "1" ) * 127.0f;
|
||||
|
||||
EnterVehicle( vehicle );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_ExitVehicle
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_ExitVehicle( bool force ) {
|
||||
Event_ScriptedStop();
|
||||
|
||||
if( vehicleController.GetVehicle() && force && !ExitVehicle(force) ) {
|
||||
vehicleController.GetVehicle()->RemoveDriver( vehicleController.GetPosition(), force );
|
||||
}
|
||||
|
||||
pathTargetInfo.node = NULL;
|
||||
faceTarget = NULL;
|
||||
lookTarget = NULL;
|
||||
leader = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_ScriptedMove
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_ScriptedMove( idEntity *target, float minDist, bool exitVehicle ) {
|
||||
isMoving = false;
|
||||
|
||||
if( !target ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( IsValidTarget( target ) ) {
|
||||
isMoving = true;
|
||||
faceTarget = NULL;
|
||||
pathTargetInfo.node = target;
|
||||
pathTargetInfo.initialDistance = ( target->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin() ).Length();
|
||||
|
||||
if ( !target->IsType( idPlayer::GetClassType() ) ) {
|
||||
pathTargetInfo.minDistance = target->spawnArgs.GetFloat( "min_distance", va("%f", Max(200.0f, minDist)) );
|
||||
pathTargetInfo.throttle = idMath::ClampFloat( 0.0f, 1.0f, target->spawnArgs.GetFloat( "throttle", "1" ) );
|
||||
pathTargetInfo.exitVehicle = target->spawnArgs.GetBool( "exit_vehicle", exitVehicle ? "1" : "0" );
|
||||
|
||||
if( pathTargetInfo.exitVehicle ) {
|
||||
pathTargetInfo.throttle = 0.0f;
|
||||
}
|
||||
} else {
|
||||
pathTargetInfo.minDistance = minDist;
|
||||
pathTargetInfo.throttle = 1.0f;
|
||||
pathTargetInfo.exitVehicle = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
SIMDProcessor->Memset( &pathTargetInfo, 0, sizeof( PathTargetInfo ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_ScriptedDone
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_ScriptedDone( void ) {
|
||||
idThread::ReturnFloat( !IsMoving() );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_ScriptedStop
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_ScriptedStop( void ) {
|
||||
if( IsDriving() ) {
|
||||
usercmd_t cmd = { 0 };
|
||||
|
||||
vehicleController.SetInput( cmd, ang_zero );
|
||||
|
||||
if( pathTargetInfo.node ) {
|
||||
if( func.Init( pathTargetInfo.node->spawnArgs.GetString( "call_doneMoving" )) > 0 ) {
|
||||
func.InsertEntity( this, 0 );
|
||||
func.CallFunc( &spawnArgs );
|
||||
func.RemoveIndex( 0 );
|
||||
}
|
||||
|
||||
pathTargetInfo.node->ActivateTargets(this);
|
||||
pathTargetInfo.node = NULL;
|
||||
}
|
||||
|
||||
isMoving = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_Trigger
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_Trigger( idEntity *activator ) {
|
||||
if( IsDriving() && pathTargetInfo.node ) {
|
||||
isMoving = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_SetSpeed
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_SetSpeed( float speed ) {
|
||||
currentThrottle = speed;
|
||||
}
|
||||
|
||||
//twhitaker: remove - begin
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_SetFollowOffset
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_SetFollowOffset( const idVec3 &offset ) {
|
||||
gameLocal.Warning( "Script Event \"followOffset\" is deprecated, please remove it immediately to avoid errors." );
|
||||
}
|
||||
//twhitaker: remove - end
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_FireWeapon
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_FireWeapon( float weapon_index, float time ) {
|
||||
if( IsDriving() ) {
|
||||
fireEndTime = gameLocal.GetTime() + SEC2MS( time );
|
||||
vehicleController.SelectWeapon( weapon_index );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_FaceEntity
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_FaceEntity( const idEntity* entity ) {
|
||||
if( IsMoving() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
faceTarget = entity;
|
||||
isMoving = true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_LookAt
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_LookAt( const idEntity* entity ) {
|
||||
lookTarget = entity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Event_SetLeader
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Event_SetLeader( idEntity* newLeader ) {
|
||||
SetLeader( newLeader );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::UpdateAutoCorrection
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::UpdateAutoCorrection ( void ) {
|
||||
if ( IsDriving() ) {
|
||||
rvVehicle * vehicle = vehicleController.GetVehicle();
|
||||
|
||||
// Disregard your autocorrection state if we're slowing down to avoid collision with the leader.
|
||||
if ( vehicle->IsAutoCorrecting() ) {
|
||||
if ( avoidingLeader == true ) {
|
||||
vehicle->autoCorrectionBegin = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Save
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Save ( idSaveGame *savefile ) const {
|
||||
savefile->Write ( &pathTargetInfo, sizeof ( pathTargetInfo ) );
|
||||
savefile->Write ( &lastPathTargetInfo, sizeof ( lastPathTargetInfo ) );
|
||||
savefile->WriteFloat ( currentThrottle );
|
||||
|
||||
faceTarget.Save ( savefile );
|
||||
lookTarget.Save ( savefile );
|
||||
|
||||
leader.Save ( savefile );
|
||||
savefile->WriteInt ( leaderFlags );
|
||||
savefile->WriteFloat ( decelDistance );
|
||||
savefile->WriteFloat ( minDistance );
|
||||
savefile->WriteBool ( avoidingLeader );
|
||||
|
||||
savefile->WriteFloat ( fireEndTime );
|
||||
|
||||
func.Save ( savefile );
|
||||
|
||||
savefile->WriteBool ( isMoving );
|
||||
|
||||
savefile->WriteInt ( (int&)pathingMode );
|
||||
pathingEntity.Save ( savefile );
|
||||
savefile->WriteVec3 ( pathingOrigin );
|
||||
|
||||
savefile->WriteFloat( forwardThrustScale ); // cnicholson: Added unsaved var
|
||||
savefile->WriteFloat( rightThrustScale ); // cnicholson: Added unsaved var
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvVehicleDriver::Restore
|
||||
================
|
||||
*/
|
||||
void rvVehicleDriver::Restore ( idRestoreGame *savefile ) {
|
||||
savefile->Read ( &pathTargetInfo, sizeof ( pathTargetInfo ) );
|
||||
savefile->Read ( &lastPathTargetInfo, sizeof ( lastPathTargetInfo ) );
|
||||
savefile->ReadFloat ( currentThrottle );
|
||||
|
||||
faceTarget.Restore ( savefile );
|
||||
lookTarget.Restore ( savefile );
|
||||
|
||||
leader.Restore ( savefile );
|
||||
savefile->ReadInt ( leaderFlags );
|
||||
savefile->ReadFloat ( decelDistance );
|
||||
savefile->ReadFloat ( minDistance );
|
||||
savefile->ReadBool ( avoidingLeader );
|
||||
|
||||
savefile->ReadFloat ( fireEndTime );
|
||||
|
||||
func.Restore ( savefile );
|
||||
|
||||
savefile->ReadBool ( isMoving );
|
||||
|
||||
savefile->ReadInt ( (int&)pathingMode );
|
||||
pathingEntity.Restore ( savefile );
|
||||
savefile->ReadVec3 ( pathingOrigin );
|
||||
|
||||
savefile->ReadFloat( forwardThrustScale ); // cnicholson: Added unrestored var
|
||||
savefile->ReadFloat( rightThrustScale ); // cnicholson: Added unrestored var
|
||||
}
|
||||
Reference in New Issue
Block a user